sectr.server
sectr.server mounts an AgentApp as the runner invoke contract
(schema/invocation.schema.json): POST /invocations with
{session_id, invocation_id, route, transcript, reason}, answered by an SSE
stream of runner events. You almost never touch this module — sectr dev
and the production sidecar do:
sectr devspawnsuv run python -m sectr.server <entry>— the module form ofmain()below.- The production sidecar imports your app and calls
run(app)directly.
create_asgi(app)
Section titled “create_asgi(app)”Builds the FastAPI app implementing the contract:
- structurally validates the request body (missing/wrongly-typed fields → 422);
- dispatches by
routeto the registered handler; - constructs the
SessionContext(transcript envelopes + the polymorphic reason); - streams the handler through
sectr.driveas SSE —data:= one runner event JSON per frame.
sectr.drive enforces finality: exactly one terminal event —
NO_MORE_ACTIONS appended on generator exhaustion (turn over) or
ToolApprovalRequired last (turn suspended). Handlers can’t end a turn
wrongly; the adapter makes the contract impossible to violate by accident.
run(app) / python -m sectr.server <entry>
Section titled “run(app) / python -m sectr.server <entry>”run(app) serves on 127.0.0.1:$SECTR_PORT (default 8080) — the sidecar
sets the port. The CLI form resolves module:attribute, imports it, and
serves — that’s the entry sectr dev uses for the subprocess runner.