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:
get_workflowis the only source ofinitialActivity— the firstnext_activitycall needs it, so the sequencestart_session → get_workflow → next_activityis fixed.next_activitymoves;get_activityreads. The orchestrator advances the session and gets back only the new activity's id; the worker then loads the full definition. Later transitions come from thetransitionsfield of the current activity, validated server-side against the definition.- An active checkpoint locks the session. Between
yield_checkpointandrespond_checkpoint, navigation and content reads (next_activity,get_activity,get_technique,get_resource,get_trace) are refused; only the checkpoint tools andget_workflow_statusproceed.respond_checkpointwith a user choice is additionally rejected if it arrives less than three seconds after the yield — a response that fast did not involve a person. - Replays are safe. Yielding a checkpoint that was already resolved returns the cached response instead of pausing again, so a worker resumed with stale context cannot double-ask.
get_activityrequirescontext_tokens. The worker declares its own context window in tokens on every activity fetch. The server derives an eager step-technique bundling budget from it (availability headroom × a token→char factor, both server config) and inlines ungated step-bound techniques that fit. It is per-agent and per-call — never stored on the session, never defaulted. Omittingcontext_tokensis a validation error. See eager bundling and Resolution.
Errors: the call failed
Errors mean the call did not take effect. The useful distinction for an agent is what to do next:
| Error | Meaning | Sensible reaction |
|---|---|---|
| Parameter validation failure | The call violated the tool's schema; it never reached a handler. | Fix the call — never retry verbatim. |
WorkflowNotFoundError, ActivityNotFoundError, TechniqueNotFoundError, ResourceNotFoundError | A 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_INDEX | No session behind that index, or the token isn't a session index at all. | Resume by planning-folder slug via start_session rather than guessing indexes. |
SessionStoreError: SEAL_MISMATCH | The state file is not what the server last wrote — edited, corrupted, or restored. | Stop and surface to the user; the server will not act on state it cannot vouch for. |
SessionStoreError: COLLISION / WORKSPACE_INVALID | Two 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 refusals | Navigation 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:
| Warning | What it signals |
|---|---|
| Missing / unexpected steps in manifest | The reported step_manifest doesn't match the activity's declared steps — work was skipped, invented, or renamed. |
| Step order mismatch, empty step output | Steps reported out of declared order, or a step claimed complete with nothing to show. |
| Technique not fetched | A manifested technique step has no technique_fetched or technique_bundled event — the step was summarized from memory, not executed from its definition. |
| Workflow version drift | The definition changed on disk since start_session; the run continues under the new definition. |
| Parent chain depth | More than five levels of nested dispatch — usually a sign the dispatch topology has gone wrong. |
Why deviations warn instead of block follows the same rule — see the advisory layers on the fidelity page.
The trace
Every tool call 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) every fetch returns full content — right for disposable workers that start with empty context. In persistent mode the server keeps a per-agent ledger of content hashes and replaces anything already delivered with a short marker:
persistent mode. The ledger is keyed per agent and per channel (technique bundles, rules, individual techniques), 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" } or get_technique { 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, ungated step-bound techniques 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. Ungated technique steps are inlined in document order until the next would overflow the budget; gated steps (when/condition on the step or an enclosing loop) and oversized techniques stay lazy via get_technique { step_id }. A per-activity bundleTechniques.maxChars caps any single technique; maxChars: 0 opts the activity out entirely. Resources referenced by inlined techniques are never inlined — the worker still calls get_resource on demand.
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 .engineering/artifacts/planning/<slug>/ (the 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:
get_workflow_statusis the orchestrator's poll — position, active checkpoint, and child statuses without touching execution.- A child reaching its terminal activity flips its entry in the parent's
triggeredWorkflowstocompleted; the parent discovers this on its next status read rather than by callback. - Because children are embedded, not separate files, resuming the parent by folder name resumes the entire tree.
Next
Signatures for every tool are on the tool reference; server-side mechanics are in request lifecycle.