Schema reference
The JSON Schemas that define workflows, activities, techniques, conditions, and session state. The Zod schemas in src/schema/ are the source of truth; the JSON files under schemas/ are generated from them (npm run build:schemas) and validate workflow definitions at authoring time.
The field tables below show each schema's top-level shape and are rendered from the checked-in schema files. For authoring guidance — how the pieces fit together when writing a workflow — read the schema guide.
activity.schema.json
Activity definition schema — unified ordered, kind-tagged steps[] (technique | action | checkpoint | loop).
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique identifier for the activity |
version | string | yes | Semantic version of the activity |
name | string | yes | Human-readable activity name |
description | string | no | Detailed description of the activity |
techniques | string[] | no | Activity-wide technique references (:: paths); bundled into get_activity. |
bundleTechniques | object | no | Opt-in hybrid bundling: get_activity inlines each ungated step technique whose composed wire form is at most maxChars; larger and gated ones remain lazy-fetched via get_technique. Bundled deliveries are recorded as technique_bundled history events and satisfy the manifest fidelity check. |
steps | (technique | action | checkpoint | loop)[] | no | Ordered, kind-tagged execution steps for this activity |
decisions | object[] | no | Conditional branching points; branch conditions are evaluated by the orchestrator, not the server. |
decisions[].id | string | yes | - |
decisions[].name | string | yes | - |
decisions[].description | string | no | - |
decisions[].branches | object[] | yes | - |
decisions[].branches[].id | string | yes | - |
decisions[].branches[].label | string | yes | - |
decisions[].branches[].condition | condition | no | - |
decisions[].branches[].transitionTo | string | no | Activity ID to transition to. Omit for terminal branches (workflow ends) |
decisions[].branches[].isDefault | boolean | no | Default: false |
transitions | object[] | no | Navigation to other activities. Legality is validated warn-only at next_activity — an out-of-graph transition warns in _meta.validation but is not blocked. |
transitions[].to | string | yes | Activity ID to transition to |
transitions[].condition | condition | no | - |
transitions[].isDefault | boolean | no | Default: false |
triggers | object[] | no | Workflows the orchestrator dispatches from this activity (via dispatch_child with an explicit workflow_id); the server does not act on trigger declarations. |
triggers[].workflow | string | yes | ID of the workflow to trigger |
triggers[].description | string | no | Description of when/why this workflow is triggered |
triggers[].passContext | string[] | no | Context variable names the dispatching agent relays to the child workflow. The server does not copy them — a child session's bag starts from the child workflow's own declared defaults, nothing more. |
outcome | string[] | no | Expected outcomes when activity completes successfully. Advisory — the server does not reconcile them against activity_manifest outcomes. |
required | boolean | no | Whether this activity is required in the workflow Default: true |
rules | string[] | no | Activity-level rules and constraints that agents must follow |
artifactPrefix | string | no | Numeric prefix for artifact filenames, inferred from the activity filename (e.g., "02" from 02-design-philosophy.yaml). Server-computed — do not set in definition files. |
condition.schema.json
Condition expression schema
One of 4 variants: simple, and, or, not.
session-file.schema.json
Server-managed session file (session.
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
schemaVersion | 1 | yes | - |
sessionIndex | string | yes | - |
workflowId | string | yes | - |
workflowVersion | string | yes | - |
agentId | string | yes | - |
seq | integer | yes | - |
ts | integer | yes | - |
startedAt | string | yes | - |
currentActivity | string | no | Default: "" |
currentTechnique | string | no | Default: "" |
condition | string | no | Default: "" |
activeCheckpoint | object | no | - |
variables | object | no | Default: {} |
completedActivities | string[] | no | Default: [] |
skippedActivities | string[] | no | Default: [] |
checkpointResponses | object | no | Default: {} |
history | object[] | no | Default: [] |
history[].timestamp | string | yes | - |
history[].type | "workflow_started" | "workflow_completed" | "workflow_aborted" | "workflow_triggered" | "workflow_returned" | "workflow_suspended" | "activity_entered" | "activity_exited" | "activity_skipped" | "step_started" | "step_completed" | "checkpoint_reached" | "checkpoint_response" | "checkpoint_replayed" | "decision_reached" | "decision_branch_taken" | "loop_started" | "loop_iteration" | "loop_completed" | "loop_break" | "variable_set" | "error" | "technique_fetched" | "resource_fetched" | "technique_bundled" | "variables_seeded" | yes | - |
history[].activity | string | no | - |
history[].step | integer | no | - |
history[].checkpoint | string | no | - |
history[].decision | string | no | - |
history[].loop | string | no | - |
history[].data | object | no | - |
history[].error | object | no | - |
status | "running" | "completed" | "aborted" | no | Default: "running" |
triggeredWorkflows | object[] | no | Default: [] |
triggeredWorkflows[].workflowId | string | yes | - |
triggeredWorkflows[].sessionIndex | string | yes | - |
triggeredWorkflows[].triggeredAt | string | yes | - |
triggeredWorkflows[].triggeredFrom | object | yes | - |
triggeredWorkflows[].status | "running" | "completed" | "aborted" | "error" | yes | - |
triggeredWorkflows[].completedAt | string | no | - |
triggeredWorkflows[].returnedContext | object | no | - |
triggeredWorkflows[].state | session-file | no | - |
planningFolderPath | string | no | - |
contextMode | "persistent" | "fresh" | no | - |
deliveredContent | object | no | - |
parentSession | session-file | no | - |
state.schema.json
Workflow state schema
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
workflowId | string | yes | - |
workflowVersion | string | yes | - |
stateVersion | integer | no | Default: 1 |
startedAt | string | yes | - |
updatedAt | string | yes | - |
completedAt | string | no | - |
currentActivity | string | no | - |
currentStep | integer | no | - |
completedActivities | string[] | no | Default: [] |
skippedActivities | string[] | no | Default: [] |
completedSteps | object | no | Default: {} |
checkpointResponses | object | no | Default: {} |
decisionOutcomes | object | no | Default: {} |
activeLoops | object[] | no | Default: [] |
activeLoops[].activityId | string | yes | - |
activeLoops[].loopId | string | yes | - |
activeLoops[].currentIteration | integer | yes | - |
activeLoops[].totalItems | integer | no | - |
activeLoops[].currentItem | any | no | - |
activeLoops[].startedAt | string | yes | - |
variables | object | no | Default: {} |
history | object[] | no | Default: [] |
history[].timestamp | string | yes | - |
history[].type | "workflow_started" | "workflow_completed" | "workflow_aborted" | "workflow_triggered" | "workflow_returned" | "workflow_suspended" | "activity_entered" | "activity_exited" | "activity_skipped" | "step_started" | "step_completed" | "checkpoint_reached" | "checkpoint_response" | "checkpoint_replayed" | "decision_reached" | "decision_branch_taken" | "loop_started" | "loop_iteration" | "loop_completed" | "loop_break" | "variable_set" | "error" | "technique_fetched" | "resource_fetched" | "technique_bundled" | "variables_seeded" | yes | - |
history[].activity | string | no | - |
history[].step | integer | no | - |
history[].checkpoint | string | no | - |
history[].decision | string | no | - |
history[].loop | string | no | - |
history[].data | object | no | - |
history[].error | object | no | - |
status | "running" | "paused" | "suspended" | "completed" | "aborted" | "error" | no | Default: "running" |
parentWorkflow | object | no | - |
triggeredWorkflows | object[] | no | Default: [] |
triggeredWorkflows[].workflowId | string | yes | - |
triggeredWorkflows[].planningSlug | string | no | - |
triggeredWorkflows[].sessionIndex | string | no | - |
triggeredWorkflows[].triggeredAt | string | yes | - |
triggeredWorkflows[].triggeredFrom | object | yes | - |
triggeredWorkflows[].status | "running" | "completed" | "aborted" | "error" | yes | - |
triggeredWorkflows[].completedAt | string | no | - |
triggeredWorkflows[].returnedContext | object | no | - |
lastError | object | no | - |
technique.schema.json
Technique definition schema for workflow-server
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique identifier for the technique |
version | string | yes | Semantic version of the technique |
capability | string | yes | What this technique enables agents to do |
provenance_note | string | no | Delivery-only, server-populated on a step-bound get_technique: states the output delivery mechanics that the source:/destination: annotations rely on. Never authored in technique markdown. |
rules | rulesDefinition | no | - |
inputs | inputsDefinition | no | - |
inherited_inputs | inheritedInputs | no | - |
protocol | protocolDefinition | no | - |
outputs | outputsDefinition | no | - |
inherited_outputs | inheritedOutputs | no | - |
workflow.schema.json
Workflow definition schema
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
$schema | string | no | - |
id | string | yes | Unique workflow identifier |
version | string | yes | Semantic version |
title | string | yes | Human-readable workflow title |
description | string | no | Detailed workflow description |
author | string | no | Author metadata; not read by the server. |
tags | string[] | no | - |
rules | object | no | Workflow rules partitioned by audience: workflow (orchestrator-only) and activity (inherited by every activity, injected into get_activity). Entries are rule strings or { ref } references into fragments.rules. |
fragments | object | no | Shared rule texts and checkpoint bodies, declared once and imported by reference ([workflow::]name) from rules slots and kind:checkpoint steps — this workflow's or another's. Resolved at load; agents always receive materialized content. |
variables | object[] | no | Workflow-level variable declarations, rendered in get_workflow for agents. The session variable bag is seeded from each declaration's defaultValue at session creation; thereafter the server writes it only through checkpoint setVariable effects. |
variables[].name | string | "requirements" | "features" | "exclusions" | "dimensions" | "tasks" | "results" | "submodules" | "paths" | "fields" | "filters" | "stats" | "effects" | "substitutions" | "findings" | "assumptions" | "subsystems" | "transitions" | "options" | "branches" | "agents" | "changes" | "failures" | "items" | "files" | "gaps" | "outcomes" | "body" | "query" | "repo" | "owner" | "number" | "title" | "branch" | "diff" | "limit" | "name" | "sha" | "url" | "head" | "base" | "ref" | "labels" | "path" | "cursor" | "cql" | "jql" | "description" | "assignee" | "depth" | "direction" | "summary" | "state" | "target" | "adr" | "type" | "mode" | "kind" | yes | Qualified snake_case noun phrase (>=2 words, AP-60), or an enumerated bare-word exemption. |
variables[].type | "string" | "number" | "boolean" | "array" | "object" | yes | Declared type. The server validates checkpoint setVariable values against it, warn-only: a mismatch is stored as written and surfaced in _meta.validation and on the variable_set history event. Agents honor it for their own writes. |
variables[].description | string | no | - |
variables[].defaultValue | any | no | Initial value the server seeds into the session variable bag at session creation (start_session fresh sessions and dispatch_child children), recorded as one variables_seeded history event. Do not gate a defaulted variable with exists/notExists — seeding makes the gate constant (check:variable-model enforces this). |
variables[].required | boolean | no | Authoring metadata; the server does not check that the variable is ever set. Default: false |
techniques | object | no | Workflow techniques partitioned by audience: workflow (orchestrator, bundled into get_workflow) and activity (inherited by every activity, injected into get_activity). |
initialActivity | string | no | ID of the first activity to execute. Required for sequential workflows, optional when all activities are independent entry points. |
activities | object[] | no | Activities that comprise this workflow. Activities with transitions form sequences; activities without transitions are independent entry points. Omitted in definition files where activities are separate files. |
activities[].id | string | yes | Unique identifier for the activity |
activities[].version | string | yes | Semantic version of the activity |
activities[].name | string | yes | Human-readable activity name |
activities[].description | string | no | Detailed description of the activity |
activities[].techniques | string[] | no | Activity-wide technique references (:: paths); bundled into get_activity. |
activities[].bundleTechniques | object | no | Opt-in hybrid bundling: get_activity inlines each ungated step technique whose composed wire form is at most maxChars; larger and gated ones remain lazy-fetched via get_technique. Bundled deliveries are recorded as technique_bundled history events and satisfy the manifest fidelity check. |
activities[].steps | (technique | action | checkpoint | loop)[] | no | Ordered, kind-tagged execution steps for this activity |
activities[].decisions | object[] | no | Conditional branching points; branch conditions are evaluated by the orchestrator, not the server. |
activities[].decisions[].id | string | yes | - |
activities[].decisions[].name | string | yes | - |
activities[].decisions[].description | string | no | - |
activities[].decisions[].branches | object[] | yes | - |
activities[].decisions[].branches[].id | string | yes | - |
activities[].decisions[].branches[].label | string | yes | - |
activities[].decisions[].branches[].condition | condition | no | - |
activities[].decisions[].branches[].transitionTo | string | no | Activity ID to transition to. Omit for terminal branches (workflow ends) |
activities[].decisions[].branches[].isDefault | boolean | no | Default: false |
activities[].transitions | object[] | no | Navigation to other activities. Legality is validated warn-only at next_activity — an out-of-graph transition warns in _meta.validation but is not blocked. |
activities[].transitions[].to | string | yes | Activity ID to transition to |
activities[].transitions[].condition | condition | no | - |
activities[].transitions[].isDefault | boolean | no | Default: false |
activities[].triggers | object[] | no | Workflows the orchestrator dispatches from this activity (via dispatch_child with an explicit workflow_id); the server does not act on trigger declarations. |
activities[].triggers[].workflow | string | yes | ID of the workflow to trigger |
activities[].triggers[].description | string | no | Description of when/why this workflow is triggered |
activities[].triggers[].passContext | string[] | no | Context variable names the dispatching agent relays to the child workflow. The server does not copy them — a child session's bag starts from the child workflow's own declared defaults, nothing more. |
activities[].outcome | string[] | no | Expected outcomes when activity completes successfully. Advisory — the server does not reconcile them against activity_manifest outcomes. |
activities[].required | boolean | no | Whether this activity is required in the workflow Default: true |
activities[].rules | string[] | no | Activity-level rules and constraints that agents must follow |
activities[].artifactPrefix | string | no | Numeric prefix for artifact filenames, inferred from the activity filename (e.g., "02" from 02-design-philosophy.yaml). Server-computed — do not set in definition files. |