Protocol

The tool reference gives the signatures; this page covers call order, errors and warnings, trace tokens, reference delivery, and dispatch on the wire.

Call order and authentication

Three tools are callable cold — discover, list_workflows, and health_check. Everything else requires the session_index issued by start_session, and a few ordering rules carry the whole protocol:

Errors: the call failed

Errors mean the call did not take effect. The useful distinction for an agent is what to do next:

ErrorMeaningSensible reaction
Parameter validation failureThe call violated the tool's schema; it never reached a handler.Fix the call — never retry verbatim.
WorkflowNotFoundError, ActivityNotFoundError, TechniqueNotFoundError, ResourceNotFoundErrorA definition referenced by id does not exist in the mounted corpus.Re-check the reference against list_workflows / the activity's declared steps; a typo is far likelier than a missing file.
SessionStoreError: NOT_FOUND / INVALID_INDEXNo session behind that index, or the token isn't a session index at all. Where a planning folder's session.json could not be read, the error names that folder.Resume by planning-folder slug via start_session rather than guessing indexes; for a named unreadable folder, restore it from its last commit or start a fresh session.
SessionStoreError: SEAL_MISMATCHThe state file is not what the server last sealed — edited outside the server, or sealed under another signing key.Stop and surface to the user; the server will not act on state it cannot vouch for.
SessionStoreError: SESSION_INVALIDThe state file cannot be read as a session: it is not JSON, or the session schema rejects it.Restore the folder from its last commit, or start a fresh session.
SessionStoreError: SESSION_OUTDATEDThe state file predates the frontier and holds no position to resume from.Start a fresh session.
SessionStoreError: STALE_WRITEAnother call recorded against the session while this one was in flight; a parent and its children share one file, so they count as one session. Nothing was written.Call again with the same arguments — the repeat applies the change to the state as it now stands. Keep one call in flight per session.
SessionStoreError: FOLDER_OCCUPIEDThe planning folder already holds a run. Nothing was written.Pass the returned session_index to continue that run, or a distinct planning_folder to open another.
SessionStoreError: COLLISION / WORKSPACE_INVALIDTwo folders derived the same index, or the workspace path is unusable.Both are setup problems for a human, not something to retry around.
Checkpoint gate refusalsNavigation attempted while a checkpoint is active, or a response arrived too fast.Resolve the checkpoint properly; the gate is the feature.

Warnings: the call succeeded, and left evidence

Validation that requires interpretation never blocks — it lands in _meta.validation as { status, warnings } on the successful response, and is recorded in the trace. Warnings an orchestrator should expect to read:

WarningWhat it signals
Missing / unexpected steps in manifestThe reported step_manifest doesn't match the activity's declared steps — work was skipped, invented, or renamed.
Step order mismatch, empty step outputSteps reported out of declared order, or a step claimed complete with nothing to show.
Technique not fetchedA manifested technique step has no technique_fetched or technique_bundled event — the step was summarized from memory, not executed from its definition.
Workflow version driftThe definition changed on disk since start_session; the run continues under the new definition.

Why deviations warn instead of block follows the same rule — see the advisory layers on the fidelity page.

The trace

Each call that carries a session_index, apart from the read-only diagnostics get_trace, get_workflow_status and inspect_session, appends an event — tool, timing, outcome, workflow, activity, agent, and any validation warnings — to an in-process, per-session buffer (up to 1,000 sessions; the oldest is evicted beyond that). Each next_activity response additionally carries _meta.trace_token: the events since the previous transition, HMAC-signed into a compact token. The tokens are the durable half of the design — an orchestrator that accumulates them can hand the set to get_trace and reconstruct a tamper-evident account of the run even after the in-memory buffer is gone. Calling get_trace with no tokens returns the live buffer for the session.

Reference delivery

Sessions run in one of two delivery modes, recorded as contextMode. In fresh mode (the default) a first delivery to a context is full — right for a dispatched worker, whose context starts empty. A context returning under the identity its dispatch minted still receives markers for the blocks every activity repeats, and opts into reference delivery per call for the rest. In persistent mode the server keeps a per-agent ledger of content hashes and replaces anything already delivered with a short marker:

Reference delivery A fetch through get_activity, get_technique, or get_resource reaches a decision: is the content hash already in the session's delivered ledger? If yes, the response is a short unchanged marker with the content hash. If no, the full content is delivered and its hash is recorded in the ledger. get_activity / get_technique / get_resource hash already in the ledger? deliveredContent, per agent { delivery: "unchanged", content_hash } full content delivered hash recorded in the ledger yes no
Reference delivery in persistent mode. The ledger is keyed per agent and per channel (technique bundles, rules, individual techniques, resources), so an orchestrator and a worker on the same session have independent delivery state. An agent that has lost its context can force re-delivery with get_activity { bundle: "full" }, get_technique { full: true }, or get_resource { full: true }.

The marker is a contract, not a hint: delivery: "unchanged" asserts the content is byte-identical to what this agent already received, which the server can promise because payload composition is deterministic. If your context no longer contains the earlier copy, ask for full delivery rather than proceeding from a summary.

Eager step-technique bundling

Every get_activity call automatically inlines small step-bound techniques whose gate answers true under a step_techniques map — there is no per-activity opt-in. The worker supplies context_tokens; the server computes a cumulative per-activity character budget:

context_tokens × headroomFraction × charsPerToken — defaults 0.80 and 4, overridable via BUNDLE_HEADROOM_FRACTION and BUNDLE_CHARS_PER_TOKEN. The worker bundle the activity rides in — its role rules and contract techniques — is counted first; technique steps with no gate, or a gate that answers true, are then inlined in document order until the next would overflow what remains; a step whose gate (when/condition on the step or an enclosing loop) answers false or has no answer at delivery, and an oversized technique, stay lazy via get_technique { step_id }. A per-activity bundleTechniques.maxChars caps any single technique; maxChars: 0 opts the activity out entirely. Under reference delivery the bodies of resources the inlined techniques link ride a resources map; otherwise their ids ride resource_refs for get_resource.

Bundled entries share the technique:<resolvedId> ledger key with get_technique, so in persistent context mode a bundled delivery collapses a later step-bound refetch to an unchanged marker. Each bundled step is recorded as a technique_bundled event and counts toward manifest fidelity checks alongside technique_fetched.

Enforcement notes and provenance

The server is a state ledger and payload composer, not an executor. Some constructs are agent-interpreted — step ordering, condition evaluation, actions[] verbs, protocol execution — and the server never checks them. Because a payload-only reader cannot see this classification, get_activity surfaces an enforcement_notes block (also in _meta) when the current activity contains agent-interpreted constructs: an actions note when a step is kind:action or carries an actions[] list; an auto_advance note when a checkpoint declares autoAdvanceMs. An activity without these constructs carries no block.

A step-bound get_technique fetch annotates the binding seam: each of the technique's own inputs carries a source: line stating where its value comes from (step-binding value, workflow variable, prior step output, declared default, or UNRESOLVED); remapped outputs carry a destination: line. Contract-inherited inputs are annotated only when the resolution says something the block note does not. Classification is purely static — same corpus and step always produce byte-identical annotations, which is what makes reference delivery safe.

Dispatch in practice

A typical work package starts before any planning folder exists: the meta session created by start_session for workflow selection is transient, living in the system temp directory. The first dispatch_child that commits to real work does three things at once — promotes the transient session into the engineering planning root (typically artifacts/planning/<slug>/, or .engineering/artifacts/planning/<slug>/ in legacy single-root mode; slug from your request or a dated fallback), creates the child session embedded in the parent's file, and returns the child's own session_index for the worker. From there:

Next

Signatures for every tool are on the tool reference; server-side mechanics are in request lifecycle.