No session_index required.
| Tool | Parameters | Returns | Description |
|---|---|---|---|
discover |
- | Server info and discovery instructions |
Entry point for the workflow server. Returns the server name, version, and the bootstrap procedure an agent should follow. The discovery instructions describe how to call list_workflows and start_session to begin a session. |
list_workflows |
- | Array of workflow definitions (each with id, title, version, and tags) |
Lists all available workflow definitions. Each entry in the returned array contains an id (unique workflow identifier), title (human-readable name), version (semver string), and tags (array of categorization strings for matching a user's goal to a workflow). |
health_check |
- | Server status and stats | Returns the server health status. The response includes the server version, the number of workflows available, and the server uptime. |
| Tool | Parameters | Returns | Description |
|---|---|---|---|
start_session |
agent_id, workflow_id?, planning_slug?, parent_planning_slug?, context_mode? |
session_index, planning_slug, workflow info |
Starts a new session or resumes an existing one, optionally with a parent for nested-workflow dispatch. Fresh sessions default to the meta workflow when no workflow_id is provided. agent_id sets the recorded agent identity in session.json, distinguishing orchestrator from worker calls in the trace. planning_slug is a single-segment slug for the planning folder under <workspace>/.engineering/artifacts/planning/<slug>/; it determines where session.json and the sealed .session-token live and deterministically derives the 6-character base32 session_index. When planning_slug is omitted, the server mints a transitional slug. To resume a session, pass the same planning_slug again — the server loads the existing session.json, verifies the seal, and returns the same session_index. For nested dispatch, also pass parent_planning_slug; the server snapshots the parent's session.json (seal-verified) under the child's parentSession field for trace correlation and recursive parent traversal. context_mode declares the session's delivery context model: "persistent" opts into reference delivery; omitted (or "fresh") delivers full content on every call — the correct mode when disposable workers each execute in a fresh context. On resume, a supplied context_mode overwrites the recorded value. Fresh sessions start with the variable bag seeded from the workflow's declared defaultValues, recorded as a variables_seeded history event (resumes never re-seed — the mutated bag is preserved); dispatch_child seeds each child's bag from the child workflow's own declarations the same way. Server restarts are transparent because state lives in session.json rather than in an agent-held token. |
get_workflow_status |
session_index |
status (active/blocked/completed), current_activity, completed_activities, last_checkpoint info, workflow, and parent context |
Checks the status of the current workflow session. session_index identifies the session. The returned status is one of active, blocked, or completed. current_activity names the activity the agent is executing. completed_activities lists all finished activities (from session.json). last_checkpoint contains the most recent checkpoint details. workflow reflects the current workflow metadata. If the session was created with a parent_planning_slug, the parent field contains the parent's session info derived from the parentSession snapshot. |
inspect_session |
session_index, view?, child_index?, variable? |
A compact structured projection of the addressed session, selected by view, serialised as JSON text |
Read-only inspection of a session's on-disk state. view selects the projection: summary (default, the composite of all below), identity (workflow/session/agent header + current position), variables (the variable bag), checkpoints (each checkpoint response as optionId, respondedAt, variablesSet), activities (completed / skipped / current), history (event count, a per-type byType tally, and the milestones sub-sequence), and children (a one-line digest per triggeredWorkflows child). child_index descends one positional level into the addressed session's triggeredWorkflows[child_index].state and projects that child instead (an out-of-range index returns the actionable NOT_FOUND message); deeper children are reached by passing that child's own session_index. variable — meaningful only with view: variables — narrows the result to a single key's value. The tool reads through the same sealed load path as every other tool (so it verifies integrity) but never mutates state, and is not gated on an active checkpoint — it is usable while the session is blocked, which is exactly when an orchestrator wants to look. It returns a shaped projection, never the raw session.json. |
All require session_index. The workflow is determined from session.json (recorded at start_session). Each response includes the session_index and a validation result in _meta.
| Tool | Parameters | Returns | Description |
|---|---|---|---|
get_workflow |
session_index |
The technique bundle, then lightweight workflow metadata | Loads the workflow structure for the current session. The response begins with the technique bundle — the resolved orchestrator techniques (the workflow's techniques.workflow plus the core orchestrator techniques), delivered as techniques, rules, and unresolved. A --- separator precedes the workflow body, which is lightweight metadata: orchestrator rules (the flattened rules.workflow + rules.universal), variables, initialActivity, and activity stubs (id, name, required). Per-activity step detail and the worker-facing rules.activity / techniques.activity are delivered to workers via get_activity. The bundle gives the orchestrator immediate access to the techniques and rules it needs without separate get_technique calls. |
next_activity |
session_index, activity_id, transition_condition?, step_manifest?, activity_manifest? |
activity_id, name, and trace token in _meta |
Transitions from the current activity to the next activity in the workflow. This is the orchestrator's tool — it validates the transition (advisory: an out-of-graph transition warns in _meta.validation, it is not blocked), advances session.json (writing session.json and resealing .session-token atomically), and records the trace, but does NOT return the activity definition. session_index identifies the session. activity_id is the next activity to transition to — for the first call, use the initialActivity value from get_workflow; for subsequent calls, use an activity ID from the transitions field of the current activity's response. The optional transition_condition records the condition that triggered this transition; the server checks it against the declared condition text by exact string equality (warn-only — a paraphrase or when-spelling variant warns). The optional step_manifest provides a structured summary of completed steps from the previous activity, validated for completeness and order, and cross-checked (warn-only) against the technique_fetched and technique_bundled events recorded during the activity — see Fidelity Observability. The optional activity_manifest provides an advisory summary of all completed activities. The returned activity_id and name confirm the transition target. A trace_token in _meta captures the mechanical trace for the completed activity. Hard gate: Calling next_activity while a blocking checkpoint is active (activeCheckpoint set in session.json) produces a hard error. |
get_activity |
session_index, context_tokens, bundle? |
The activity technique bundle, the workflow's inherited activity_rules, then the complete activity definition |
Loads the complete activity definition for the current activity in the session. This is the worker's tool — call it after the orchestrator has called next_activity to transition. The response begins with the technique bundle, delivered as techniques, rules, and unresolved, separated from the activity body by ---. The bundle resolves the workflow's techniques.activity (technique references inherited by EVERY activity) plus the activity's own techniques[] plus the core worker techniques — mirroring how rules.activity is inherited. The server then injects activity_rules — the workflow's rules.activity plus the dual-audience rules.universal, the worker-facing rules inherited by EVERY activity (workflow rules.workflow are orchestrator-only and never appear here). session_index identifies the session and determines the current activity from session.json (no activity_id parameter is needed). context_tokens is REQUIRED — the worker declares its own context window in tokens; the server derives an eager step-technique bundling budget from it (availability headroom × a token→char factor, both server config) and inlines the activity's ungated step-bound techniques that fit, in document order, under that budget. It is per-agent and per-call — never stored on the session, never defaulted; omitting it is a validation error (the call is rejected). The activity body includes all steps, checkpoints, loops, decisions, transitions, rules, and the activity's techniques references — everything needed to execute the activity. bundle overrides the delivery mode for the bundle and activity_rules: "reference" activates reference delivery for this call, "full" forces full delivery; when omitted, the mode follows the session's context_mode ("persistent" → reference, otherwise full). Eligible ungated step-bound techniques are inlined corpus-wide under a step_techniques map — see Hybrid Technique Bundling. When the activity contains constructs the server does not execute, the response also carries a short enforcement_notes block naming who acts — see Enforcement Boundary. |
yield_checkpoint |
session_index, checkpoint_id |
Status, checkpoint_handle, and instructions |
Yields execution to the orchestrator at a checkpoint step. session_index identifies the session and must have an active activity. checkpoint_id identifies the checkpoint to yield (must match a checkpoint defined in the current activity). The server records the active checkpoint in session.json (activeCheckpoint) and returns a one-shot opaque checkpoint_handle the worker yields to the orchestrator via a <checkpoint_yield> block. Hard gate: Cannot yield a new checkpoint while another checkpoint is already active in session.json. |
resume_checkpoint |
session_index, checkpoint_handle |
Status and recorded effects | Resumes execution after the orchestrator resolves a checkpoint. session_index identifies the session and checkpoint_handle is the one-shot handle issued by yield_checkpoint. The server validates that the checkpoint has been resolved (i.e., activeCheckpoint is cleared in session.json) before allowing the worker to proceed, and returns the recorded variable effects. Hard gate: Cannot resume if activeCheckpoint is still set. |
present_checkpoint |
checkpoint_handle |
Full checkpoint definition | Used by the orchestrator to load full checkpoint details from a worker's yielded checkpoint_handle. The server decodes the handle, looks up the active checkpoint recorded in session.json, and returns the checkpoint definition including the message to present to the user, available options with their effects, and auto-advance configuration. |
respond_checkpoint |
checkpoint_handle, option_id?, auto_advance?, condition_not_met? |
Resolution status and any defined effect |
Used by the orchestrator to resolve a yielded checkpoint. Exactly one resolution mode must be provided: option_id records the user's selected option (validated against the checkpoint definition, with a minimum response time enforced), auto_advance uses the checkpoint's defaultOption (only valid for non-blocking checkpoints after autoAdvanceMs elapses), or condition_not_met dismisses a conditional checkpoint whose condition evaluated to false (only valid when the checkpoint has a condition field). The returned effect contains the state changes defined by the selected option, with per-effect enforcement: the server applies setVariable to the session variable bag (validated against the declared variable type warn-only — a mismatch is stored as written and surfaced in _meta.validation; {name} template passthroughs are exempt), records skipActivities in the session's skippedActivities bookkeeping, and returns transitionTo for the orchestrator to enact via next_activity (selecting the option does not itself move the session). The server clears activeCheckpoint from session.json and records the response under checkpointResponses. |
All require session_index. The workflow is determined from session.json.
| Tool | Parameters | Returns | Description |
|---|---|---|---|
get_technique |
session_index, step_id?, full? |
Fully composed technique as YAML | Loads a single composed technique within the current workflow or activity. If called before next_activity (no current activity in session), it loads the workflow's first declared technique (the first entry of the workflow's techniques.workflow). If called during an activity, it resolves the technique reference from the activity definition; with step_id, it loads the technique assigned to that step; without step_id, the activity's first declared technique (the first entry of the activity's techniques[]). The returned technique is fully composed: it inherits its ancestor techniques' base contract recursively (inputs/outputs/rules merged; the ancestor's Initial/Final protocol blocks wrap the descendant protocol and the server renumbers). A step-bound fetch (step_id supplied) also annotates the binding seam: each of the technique's own inputs carries a source: stating where its value comes from under the name-match convention (step-binding value, workflow variable, prior step output, declared default — or UNRESOLVED, which additionally surfaces as a warn-only entry in _meta.validation.warnings); contract-inherited entries carry a source: only where it says something their scope note does not (a step-binding override, or a producer positioned later in the workflow). Each output the step binding remaps carries a destination: naming the session-bag name it lands under, and a provenance_note states the output delivery mechanics. Annotations are resolved statically from declarations and document order, so the annotated payload is deterministic for a given corpus and step. Techniques are loaded one at a time. In a session with context_mode: "persistent", a refetch whose composed content is byte-identical to what the session+agent already received returns a short unchanged-reference (delivery: unchanged + content_hash) instead of the full payload — see reference delivery; full: true forces full content for a context that no longer holds the earlier delivery. Every fetch (either delivery path) is recorded in the session history as a technique_fetched event — see Fidelity Observability. |
get_resource |
session_index, resource_id |
Resource content, id, version, and session_index |
Loads a resource's full content by its slug. session_index identifies the session. resource_id is a text-only slug. Bare slugs (e.g., "review-mode") resolve within the session's workflow. Prefixed cross-workflow references (e.g., "meta/bootstrap-protocol") resolve from the named workflow. The returned content includes the resource body, an id field, and a version field. Each fetch is recorded in the session history as a resource_fetched event — see Fidelity Observability. |
| Tool | Parameters | Returns | Description |
|---|---|---|---|
get_trace |
session_index, trace_tokens? |
Trace source, event count, and array of events | Resolves accumulated trace tokens into full event data for post-execution analysis. session_index identifies the session. The optional trace_tokens parameter is an array of HMAC-signed trace tokens previously accumulated from next_activity calls. When trace_tokens is provided, the server decodes and returns the full event records for those specific tokens. When omitted, returns the in-memory trace for the current session. The response includes the trace source, the total event count, and the array of trace events with timing and validation details. |
Each session has a 6-character base32 session_index returned by start_session. The index is deterministically derived from the planning slug (<workspace>/.engineering/artifacts/planning/<slug>/), so the same slug always resolves to the same index across server restarts.
The canonical session state lives on disk in two files under the planning folder, both owned by the server:
session.json— Plaintext, JSON-Schema-validated state (schemas/session-file.schema.json). HoldssessionIndex,workflowId,workflowVersion,agentId,seq,ts,currentActivity,currentTechnique,condition,activeCheckpoint(if a checkpoint is in flight),variables,completedActivities,skippedActivities,checkpointResponses,history,triggeredWorkflows, and (for child workflows) a snapshot of the parent underparentSession..session-token— A sealed, HMAC-signed envelope bindingsession.jsonto the workspace + server signing key. Mismatch between the two on read raises a hardSealMismatchError.
Writes are atomic (write-temp + rename) and performed on every authenticated tool call. Reads verify the seal before returning state. Server restarts are transparent — the agent simply passes the same session_index (or resumes via start_session({ agent_id, planning_slug })) and the server reloads session.json from disk.
Agents pass only the session_index on every authenticated tool call; they do not read or write the session files themselves.
- Call
discoverto learn the bootstrap procedure and available workflows - Call
list_workflowsto match the user's goal to a workflow - Call
start_session({ agent_id, planning_slug })to get asession_index(defaults to themetaworkflow when noworkflow_idis provided). Resuming a session uses the same call shape with the sameplanning_slug. To start a session for a different workflow, passworkflow_id. - Call
get_workflow({ session_index })to load the workflow structure. The response begins with the technique bundle (techniques,rules,unresolved), followed by activity stubs andinitialActivity. - Call
next_activity({ session_index, activity_id: initialActivity })to transition to the first activity (returnsactivity_idandnameonly) - Call
get_activity({ session_index })to load the complete activity definition. The response begins with the technique bundle for the activity'stechniques[](techniques,rules,unresolved), followed by the raw activity body. - Execute the steps and protocol of each technique in the bundle from step 6.
- Call
get_resourcefor each resource a technique references when needed. Callget_techniqueto load a technique that is not already in the bundle. - When encountering a checkpoint step, call
yield_checkpoint, yield to the orchestrator, and wait to be resumed viaresume_checkpoint. - Read
transitionsfrom theget_activityresponse; callnext_activitywith astep_manifestto advance - Accumulate
_meta.trace_tokenfrom eachnext_activitycall for post-execution trace resolution
Note:
get_techniqueloads a single composed technique on demand — the workflow's first declared technique before any activity, or the technique for the current activity (optionally astep_id's technique). The bundle returned byget_workflow/get_activitysupplies most behaviour without per-step technique fetches.
The server validates each call against the recorded state in session.json. Validation results are returned in _meta.validation:
{
"_meta": {
"session_index": "<6-char-base32>",
"trace_token": "<trace-token (on next_activity only)>",
"validation": {
"status": "valid",
"warnings": []
}
}
}Validation checks:
- Activity transition — the requested activity is a valid transition from the activity recorded in
session.json(advisory — an out-of-graph transition warns, it is not blocked) - Version drift — the workflow version hasn't changed since the session started
- Transition condition — when
transition_conditionis provided, it is matched by exact string equality against the declared condition text (advisory; a paraphrase warns) - Step completion — when
step_manifestis provided, validates every ungated top-level step present, in declaration order, with non-empty outputs;when/condition-gated steps may be omitted and loop-body step ids are accepted but not required - Technique-fetch fidelity — when
step_manifestis provided, a manifested technique step with notechnique_fetchedortechnique_bundledevent recorded in the session history during the activity draws a warning (advisory) — see Fidelity Observability - Activity manifest — when
activity_manifestis provided, validates activity IDs exist in the workflow (advisory) - Seal integrity —
.session-tokenis verified againstsession.jsonon every read (rejects tampered state) - Checkpoint gate — when
activeCheckpointis set insession.json, most tools are hard-blocked untilrespond_checkpointclears it
Warnings do not block execution — the tool still returns its result. They enable agent self-correction. All validation warnings are captured in the execution trace.
The server is a state ledger and payload composer, not an executor. Three enforcement classes cover the whole API surface:
-
Engine-enforced (hard errors or state mutation): session identity and seal verification; the active-checkpoint gate on content tools; checkpoint resolution — option validity, minimum response time, the
autoAdvanceMstimer, replay of recorded responses — and the application ofsetVariableeffects to the variable bag; load-time structure (schema validation, per-kind step contracts, step-id uniqueness, technique resolution and composition, artifact-contract synthesis). -
Warn-only (
_meta.validation): transition legality,initialActivity-first,transition_conditiontext match, step and activity manifests, technique-fetch fidelity, version drift. -
Agent-interpreted (never checked by the server): step ordering and execution; all condition evaluation —
when,condition,breakCondition, decision branches, transition conditions; loop mechanics and iteration bounds;actions[]verbs; technique protocols, input bindings, and output remaps; artifact writing; rule compliance.Variable
defaultValues are not agent-interpreted: the server seeds them into the variable bag at session start (variables_seeded), and a variabletypeis warn-only validated when a checkpoint'ssetVariableeffect writes the bag (a mismatch is stored as written and surfaced in_meta.validation; see therespond_checkpointrow).
The single declarative path from a workflow definition into engine-held state is a checkpoint option's setVariable effect. Field-by-field classification lives in the schema guide.
Because a payload-only reader cannot see this classification, get_activity surfaces the relevant slice on the wire: when the current activity contains agent-interpreted constructs, the response carries an enforcement_notes block (also in _meta). An actions note appears when a step is kind:action or carries an actions[] list (agent-executed — the server records the step but applies no verb and sets no variable from it); an auto_advance note appears when a checkpoint declares autoAdvanceMs (the timer is server-enforced on respond_checkpoint { auto_advance: true }, while blocking is an advisory directive). An activity without these constructs carries no block.
When a worker encounters a checkpoint step during activity execution, it calls yield_checkpoint. The server records activeCheckpoint in session.json and returns a one-shot checkpoint_handle. Calling next_activity while activeCheckpoint is set produces a hard error (not a warning). Most other tools are also gated while a checkpoint is active.
The worker yields the checkpoint_handle to the orchestrator. To clear the gate, the orchestrator calls respond_checkpoint using the handle:
{ "checkpoint_handle": "...", "option_id": "proceed" }Three resolution modes:
option_id— the user's selected option. Validated against the checkpoint definition. Minimum response time enforced (default 3s since checkpoint issuance).auto_advance: true— use the checkpoint'sdefaultOption. Only valid for checkpoints that define bothdefaultOptionandautoAdvanceMs; the server enforces the fullautoAdvanceMstimer. Theblockingfield is an orchestrator directive (present and wait for the user) that the server does not consult here — a checkpoint intended to block must simply not declaredefaultOption/autoAdvanceMs.condition_not_met: true— dismiss a conditional checkpoint whose condition evaluated to false (the agent evaluates the condition; the server checks only that the field exists). Only valid when the checkpoint has a structuredconditionfield — a checkpoint gated with the inlinewhenexpression is not dismissible this way.
The response includes the effects from the selected option. Enforcement is per-effect: the server applies setVariable to the session variable bag, records skipActivities in skippedActivities, and returns transitionTo without acting on it — the orchestrator enacts the transition via next_activity. The server clears activeCheckpoint, and the orchestrator relays the effects back to the worker, which then calls resume_checkpoint({ session_index, checkpoint_handle }) to proceed.
When transitioning between activities via next_activity, agents include a step_manifest parameter — a structured summary of completed steps from the previous activity:
{
"step_manifest": [
{ "step_id": "resolve-target", "output": "Target verified at /path" },
{ "step_id": "initialize-target", "output": "Checked out main, pulled latest" }
]
}Each entry's output is a short summary of what the step produced. A step with more than one declared output reports a JSON object keyed by output id (e.g. {"reference_path": "lib/x", "component_name": "x"}); the technique-protocol spec §7.5 is the canonical statement, and a step-bound technique's provenance_note cites it at point of use.
The server validates (warn-only): every ungated top-level step present, relative declaration order preserved, non-empty outputs. A step gated by when or condition may be omitted — the agent evaluated the gate and skipped it. Loop-body step ids are accepted (report one entry per iteration if useful) but never required, since the iteration count is agent-determined and may be zero. A missing manifest triggers a warning. step.required is a worker hint the server does not consult.
The manifest is also cross-checked against fidelity observability: a manifested technique step whose technique was neither fetched nor delivered inline via a bundling activity during the activity draws a warning (see Fidelity Observability).
The server records every content fetch in the session history (session.json#history):
get_techniqueappends atechnique_fetchedevent — the resolved technique id, the boundstep_idwhen one was supplied, and the session'sagentId, under the activity current at fetch time. Both delivery paths record: an unchanged-reference answer in persistent context mode is still a fetch.get_activityappends atechnique_bundledevent per step technique it delivers inline for a bundling activity (resolved technique id,step_id, agent) — see Hybrid Technique Bundling. Kept distinct fromtechnique_fetchedso the event stream separates agent-initiated fetches from server-pushed bundle deliveries. Both delivery paths record, as for fetches.get_resourceappends aresource_fetchedevent (resource ref + agent). Observability only — the server cannot know which resources an activity requires, so no validation reads these events.
next_activity reads the technique_fetched and technique_bundled events when validating a step_manifest: a manifested technique step with no delivery recorded during the current activity visit (a loop-back revisit needs its own fetches) warns in _meta.validation. A step is covered by a step-bound fetch, by any fetch in the activity that resolved to the same technique operation — so one fetch covers several manifested steps bound to the same operation — or by an inline bundle delivery. The check is advisory, like all manifest validation: it surfaces silent degradation (steps reported complete without their technique content ever being loaded) without blocking execution.
When transitioning between activities via next_activity, agents can include an activity_manifest parameter — a structured summary of activities completed so far:
{
"activity_manifest": [
{ "activity_id": "start-work-package", "outcome": "completed", "transition_condition": "default" },
{ "activity_id": "design-philosophy", "outcome": "completed", "transition_condition": "skip_optional_activities == true" }
]
}Validation is advisory — the server warns on unknown activity IDs or empty outcomes but does not reject the call.
Each next_activity call returns an HMAC-signed trace token in _meta.trace_token. The token contains the mechanical trace (tool calls, timing, validation warnings) for the activity just completed. Agents accumulate these opaque tokens and resolve them via get_trace for post-execution analysis. See Workflow Fidelity for details.
discover,list_workflows,health_check
A technique is a markdown definition of a capability. Its file carries frontmatter with metadata.version, a ## Capability section, ## Inputs / ## Outputs sections whose #### sub-sections name the components (with reserved #### artifact and #### default components), a ## Protocol section (### N. Title blocks or a flat list), and a ## Rules section. Failure handling lives inline in the protocol step that triggers it. A technique can contain nested techniques. A technique body carries capability, flow, inputs, protocol, and outputs.
Techniques are addressed by :: paths of the form [workflow::]technique[::nested…]. A reference within the same workflow is implicit. Resolution checks the current workflow first, then meta. Slashes in a path are normalized to ::.
An activity references techniques via a flat techniques[] array, and a workflow declares cross-cutting techniques via techniques.workflow (orchestrator) and techniques.activity (inherited by every activity). The server resolves those references and bundles them into the responses of get_workflow and get_activity as three buckets: techniques (the resolved technique bodies), rules (their behavioural invariants), and unresolved (references that did not resolve). The get_workflow bundle resolves techniques.workflow; the get_activity bundle resolves techniques.activity (inherited) plus the activity's own techniques[]. The bundle gives the orchestrator and worker the techniques and rules they need without separate get_technique calls.
Full delivery on every call is the default: in disposable-worker topologies each get_activity lands in a fresh agent context, and the repeated bundle is load-bearing. A session in which a single agent context executes the whole walk can opt into reference delivery instead — content the session+agent has already received is replaced by a short marker rather than repeated.
- Opt-in:
start_session { context_mode: "persistent" }(also accepted bydispatch_childfor the child session), or per call viaget_activity { bundle: "reference" }. The per-call opt-in exists only onget_activity;get_techniquedelta mode follows the session'scontext_mode. - Ledger: the server records a per-agent hash of every
get_activitybundle technique, rules block,activity_rulesblock, fullget_techniquepayload, andget_workfloworchestrator ops bundle it delivers (insession.json#deliveredContent, keyed byagentId). Recording happens in every mode, so a per-callbundle: "reference"can refer back to content delivered under the default full mode. Content keys are namespaced by delivery channel (bundle:*,technique:*,activity_rules:*,workflow_bundle:*) so a marker only ever references content delivered in that same channel. get_workflowops-bundle slimming: undercontext_mode: "persistent", the orchestrator ops bundle (above the---separator) is content-keyed underworkflow_bundle:<hash>; on a resume where this agent already holds it, the whole bundle collapses to a single{ delivery: "unchanged", content_hash }marker while the post-separator workflow summary stays full. Fresh/default sessions always receive the ops bundle in full.get_activityreference mode: the response carriesbundle_mode: referenceplus abundle_note; each bundle technique whose composed content is byte-identical to a prior delivery collapses to{ delivery: "unchanged", content_hash }, as do therulesandactivity_rulesblocks. Techniques new to the activity (or whose content changed) arrive in full, and within a full eagerly-inlinedstep_techniquesentry the shared contract/rules blocks may themselves be markers (see Block-level delivery below). The activity body itself is always delivered.get_techniquedelta mode: active when the session'scontext_modeis"persistent"; a byte-identical refetch returnsdelivery: unchanged+content_hashinstead of the composed technique. Step-bound provenance annotations (source:/destination:) are part of the composed content; they are static per corpus and step, so a same-step refetch stays byte-identical and collapses, while fetching the same op from a different step (different binding context) re-delivers in full rather than answering with a stale reference.- Block-level delivery: finer-grained than the whole-technique collapse above. A not-yet-seen technique's shared blocks — the contract-inherited
inherited_inputs/inherited_outputsand the mergedrules— are content-keyed individually (technique:<block>:<hash>). When such a block was already delivered by a sibling technique that shares the workflow contract, it collapses to a{ delivery: "unchanged", content_hash }marker at its position in the payload while the technique-specific core stays full. This applies on both theget_techniquefull-delivery path and each eagerly-inlinedget_activitystep_techniquesentry. Content-keying keeps it stale-free: a block annotated with binding-seam provenance hashes differently and correctly delivers in full.get_technique { full: true }/get_activity { bundle: "full" }re-deliver every block. - Full-content escapes:
get_activity { bundle: "full" }andget_technique { full: true }force full delivery — use them when the calling context no longer holds the earlier payload (e.g. it was summarized away). - Agent scoping: the ledger is keyed by the session's recorded
agentId; resuming a session under a differentagent_idstarts that agent from an empty ledger, so its first deliveries are full even in reference mode.
Eager step-technique bundling is automatic and corpus-wide: get_activity inlines the composed content of every activity's small, ungated step-bound techniques under a step_techniques map, so those steps execute without a fetch round-trip. There is no per-activity opt-in — the worker's REQUIRED context_tokens sizes the bundle.
- Budget: the eager-delivery budget is a cumulative per-activity character budget =
context_tokens × headroomFraction × charsPerToken, whereheadroomFraction(default 0.80) andcharsPerToken(default 4) are server config (env-overridable:BUNDLE_HEADROOM_FRACTION,BUNDLE_CHARS_PER_TOKEN). The budget accounts for technique body sizes only — a technique'sresources[]references count, but not the resolved content of those resources (resources are never inlined; see below). Ungated technique steps are inlined in document order until adding the next would overflow the budget; the remainder stay lazy. - What is bundled: each ungated technique-kind step, in document order, until the cumulative budget is exhausted. A
when/conditionon the step itself or on an enclosing loop keeps it lazy, so bundling never delivers content for a step that may not execute. A per-activitybundleTechniques: { maxChars: <n> }is an explicit per-technique size cap layered on the budget (any single technique larger thanmaxCharsstays lazy);maxChars: 0opts the activity out of eager bundling entirely. Everything not inlined remains aget_technique { step_id }fetch. - Resources stay lazy: bundling inlines step techniques only, never their referenced resources. An inlined entry carries the technique's
resources[]references exactly as aget_techniquefetch does, but the worker still callsget_resource { resource_id }on demand for each one. Resources are frequently shared across techniques, so inlining them per-technique would duplicate content. Leavingget_resourcelazy also preserves it as a purposeful call. - Response shape: bundled entries arrive in the ops section under
step_techniques, keyed by step id. Each entry leads with a discrete▼ STEP <step_id> · technique <name>arrival marker, then the step's full composition — activity-group resolution, ancestor contract, inherited-input blocks, and binding-seam provenance annotations — identical to what the step-boundget_techniquefetch returns. Astep_techniques_noteprescribes the deliberate in-order engagement (below) and states that steps absent from the map still require a fetch, and_meta.bundled_stepslists the bundled step ids. - Intentional stepping: the act of calling
get_techniqueis a deliberate "I now turn to this step" beat. Inlining removes that call, so the worker substitutes for it: process inlinedstep_techniquesstrictly in step order and, on reaching each step, EMIT a one-line▶ step <step_id>begin-beat before executing it. That emitted beat carries the intentional act and is the stepwise observability trace for bundled steps — the worker does NOT ping the server per bundled step; the delivery-timetechnique_bundledevents already record coverage. - Ledger interplay: bundled entries share the
technique:<resolvedId>ledger key withget_technique, so in a persistent-context session a bundled delivery collapses a later step-bound refetch to an unchanged-reference — and reference-mode re-delivery of the activity collapses already-delivered bundled entries to{ delivery: "unchanged", content_hash }markers (the▼ STEPmarker rides along).bundle: "full"re-delivers everything. - Fidelity: each bundled step is recorded as a
technique_bundledhistory event and counts as delivery coverage fornext_activity's manifest fidelity check — see Fidelity Observability.
An ancestor technique's Initial and Final protocol blocks wrap a descendant's protocol, applied recursively up the technique's ancestry. The server renumbers the composed protocol so the steps read as a single ordered sequence.
Drives workflow execution: session lifecycle, state persistence, activity dispatch, transition evaluation, checkpoint flow (yield, bubble, present-to-user, respond, resume), and sub-workflow handling. Activities reference it via the :: path.
Cross-cutting behavioural rules — orchestrator-discipline, checkpoint-discipline, operational-discipline, file-sensitivity, code-commentary. These rules appear in the rules bucket of every orchestrator and worker bundle.
A workflow may declare techniques partitioned by audience, mirroring the rules.{workflow, activity} model:
techniques.workflow— orchestrator-level technique references, bundled intoget_workflowalongside the core orchestrator techniques.get_technique(before any activity) returns the composed body of the first of these.techniques.activity— technique references inherited by every activity; the server injects them into eachget_activitytechnique bundle, ahead of the activity's owntechniques[]. Declaring a common technique here once avoids duplicating it across every activity'stechniques[].