@standardagents/spec 0.40.12 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -60,6 +60,13 @@ declare global {
60
60
  */
61
61
  interface HookIdRegistry {
62
62
  }
63
+ /**
64
+ * Registry of handler names from agents/handlers/.
65
+ * Generated types add properties: interface HandlerRegistry { 'relay_pipe': true; }
66
+ * This gives us: type Handlers = keyof HandlerRegistry = 'relay_pipe'
67
+ */
68
+ interface HandlerRegistry {
69
+ }
63
70
  /**
64
71
  * Registry mapping prompt/agent names to their requiredSchema field names.
65
72
  * For agents, this maps to the side_a prompt's requiredSchema fields.
@@ -117,6 +124,11 @@ declare global {
117
124
  * Hook IDs are the unique identifiers defined in agents/hooks/ files.
118
125
  */
119
126
  type HookIds = keyof HookIdRegistry extends never ? string : keyof HookIdRegistry;
127
+ /**
128
+ * Union of all handler names, or string when registry is empty.
129
+ * Handler names are the file-derived identifiers from agents/handlers/.
130
+ */
131
+ type Handlers = keyof HandlerRegistry extends never ? string : keyof HandlerRegistry;
120
132
  }
121
133
  }
122
134
 
@@ -1068,18 +1080,29 @@ interface ThreadMetadata {
1068
1080
  }
1069
1081
  /**
1070
1082
  * Registry entry for a subagent child thread.
1083
+ *
1084
+ * Every child instance is a persistent thread. Session end — stop, fail,
1085
+ * error, or turn-cap — never terminates a thread: the entry's status
1086
+ * transitions (e.g. `running` → `idle` / `failed`), the thread remains
1087
+ * addressable, and a later message starts a new session with history intact.
1088
+ * Only explicit termination destroys an instance.
1071
1089
  */
1072
1090
  interface SubagentRegistryEntry {
1073
1091
  /** Child thread UUID used as stable reference address */
1074
1092
  reference: string;
1075
- /** Child agent name */
1093
+ /**
1094
+ * The relationship name this instance was spawned under — the `as` name
1095
+ * (defaulting to the agent name) of the owning side's declaration. This is
1096
+ * the name lifecycle tools address; `name` is the implementing agent
1097
+ * definition.
1098
+ */
1099
+ relationship: string;
1100
+ /** Child agent definition name */
1076
1101
  name: string;
1077
1102
  /** Child agent title (human-readable) */
1078
1103
  title?: string;
1079
1104
  /** Tool description shown to the parent LLM */
1080
1105
  description: string;
1081
- /** Whether this subagent instance is resumable */
1082
- resumable?: boolean;
1083
1106
  /** Whether parent execution blocks on this subagent */
1084
1107
  blocking?: boolean;
1085
1108
  /** Optional human-readable thread name (for example from `name:` tag) */
@@ -1087,24 +1110,34 @@ interface SubagentRegistryEntry {
1087
1110
  /**
1088
1111
  * Initial argument values supplied when the child was created.
1089
1112
  *
1090
- * For resumable subagents, these values persist for the lifetime of the
1091
- * child thread and are visible to both child sides. Runtimes SHOULD source
1092
- * this object from the receiving side's prompt argument schema. The registry
1093
- * copy is parent-visible metadata; the durable child-side source SHOULD live
1094
- * with the child thread metadata/properties and be restored into
1113
+ * These values persist for the lifetime of the child thread and are
1114
+ * visible to both child sides. Runtimes SHOULD source this object from the
1115
+ * child's side A prompt argument schema. The registry copy is
1116
+ * parent-visible metadata; the durable child-side source SHOULD live with
1117
+ * the child thread metadata/properties and be restored into
1095
1118
  * `ThreadState.arguments` during execution and endpoint access. Top-level
1096
- * keys SHOULD also be exposed to prompt variable interpolation for whichever
1097
- * child side is currently rendering.
1119
+ * keys SHOULD also be exposed to prompt variable interpolation for
1120
+ * whichever child side is currently rendering.
1098
1121
  */
1099
1122
  initialArguments?: Record<string, unknown>;
1100
1123
  /** Spawn group identifier used for grouping instances created together */
1101
1124
  spawnGroupId?: string;
1102
1125
  /** Instance creation timestamp (microseconds) */
1103
1126
  createdAt?: number;
1104
- /** Current status (`running`, `idle`, `terminated`, or custom text) */
1127
+ /**
1128
+ * Current status (`running`, `idle`, `failed`, `awaiting_human`,
1129
+ * `terminated`, or custom text). A child whose human-backed side is due to
1130
+ * take a turn parks in `awaiting_human`.
1131
+ */
1105
1132
  status: string;
1106
1133
  /** How this child reports information back to its parent thread */
1107
1134
  parentCommunication?: 'implicit' | 'explicit';
1135
+ /**
1136
+ * @deprecated Removed in 0.2.0 — every child instance is a persistent
1137
+ * thread, so there is no resumable/non-resumable distinction. See:
1138
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
1139
+ */
1140
+ resumable?: never;
1108
1141
  }
1109
1142
  /**
1110
1143
  * Options for retrieving messages.
@@ -1163,6 +1196,13 @@ interface Message {
1163
1196
  * (for example: `status_kind`, `subagent_event`). Message APIs may also
1164
1197
  * mark send-message and durable queue entries with `queued: true` until
1165
1198
  * they are injected into stored history.
1199
+ *
1200
+ * Provenance conventions (OPTIONAL, runtimes SHOULD set them): when a
1201
+ * message originates from a child instance, `metadata.subagent_id` carries
1202
+ * the child's reference UUID; when code forwards a message across threads,
1203
+ * `metadata.forwarded_from` carries the source thread id. These are
1204
+ * conventions, not requirements — userland must not need bracket-tag
1205
+ * prefixes in message text to recover provenance.
1166
1206
  */
1167
1207
  metadata?: Record<string, unknown>;
1168
1208
  /** Message processing status */
@@ -1205,10 +1245,16 @@ interface Message {
1205
1245
  subagent_description?: string | null;
1206
1246
  /** Subagent status projected from runtime registry (when available) */
1207
1247
  subagent_status?: string | null;
1208
- /** Whether the associated subagent is resumable (when available) */
1209
- subagent_resumable?: boolean | null;
1248
+ /** Subagent relationship name (`as`) projected from runtime registry (when available) */
1249
+ subagent_relationship?: string | null;
1210
1250
  /** Whether the associated subagent is blocking (when available) */
1211
1251
  subagent_blocking?: boolean | null;
1252
+ /**
1253
+ * @deprecated Removed in 0.2.0 — every child instance is a persistent
1254
+ * thread, so there is no resumable/non-resumable distinction. See:
1255
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
1256
+ */
1257
+ subagent_resumable?: never;
1212
1258
  /** Optional subagent instance thread name (when available) */
1213
1259
  subagent_thread_name?: string | null;
1214
1260
  /** Spawn group identifier for related subagent instances (when available) */
@@ -1230,12 +1276,13 @@ interface InjectMessageInput {
1230
1276
  /**
1231
1277
  * Input for queueing a message for delivery on the thread's next step.
1232
1278
  *
1233
- * Role mapping follows dual_ai conventions:
1234
- * - `assistant` maps to side_a
1235
- * - `user` maps to side_b
1279
+ * Role mapping is the single source of perspective truth, uniform across
1280
+ * queueing, injection, and rendering:
1281
+ * - `role: 'user'` — side B perspective (side A acts on it)
1282
+ * - `role: 'assistant'` — side A perspective (side B acts on it)
1236
1283
  */
1237
1284
  interface QueueMessageInput {
1238
- /** Message role (`user` queues side_b perspective, `assistant` queues side_a perspective) */
1285
+ /** Message role (`user` queues side B perspective, `assistant` queues side A perspective) */
1239
1286
  role: 'user' | 'assistant';
1240
1287
  /** Message content */
1241
1288
  content: string;
@@ -1635,7 +1682,7 @@ interface CodeExecutionResult {
1635
1682
  interface ExecutionState {
1636
1683
  /** Current flow ID (unique per execution) */
1637
1684
  readonly flowId: string;
1638
- /** Current side in dual_ai agents ('a' or 'b') */
1685
+ /** Which side is currently taking its turn ('a' or 'b') */
1639
1686
  readonly currentSide: 'a' | 'b';
1640
1687
  /** Total steps executed in this flow */
1641
1688
  readonly stepCount: number;
@@ -1652,7 +1699,8 @@ interface ExecutionState {
1652
1699
  /**
1653
1700
  * Force a specific side to play the next turn.
1654
1701
  *
1655
- * Only valid for dual_ai agents. Has no effect on ai_human agents.
1702
+ * Only meaningful when the forced side is prompt- or handler-backed;
1703
+ * forcing a human-backed side parks execution awaiting that side's input.
1656
1704
  *
1657
1705
  * @param side - The side to force ('a' or 'b')
1658
1706
  */
@@ -1703,6 +1751,9 @@ interface SetEnvOptions {
1703
1751
  }
1704
1752
  /**
1705
1753
  * Options for {@link ThreadState.stopSession}.
1754
+ *
1755
+ * Ending a session never terminates the thread — the thread stays
1756
+ * addressable and a later message starts a new session with history intact.
1706
1757
  */
1707
1758
  interface StopSessionOptions {
1708
1759
  /**
@@ -1828,7 +1879,8 @@ interface ThreadState {
1828
1879
  /**
1829
1880
  * Registry of subagent child instances owned by this thread.
1830
1881
  *
1831
- * Includes both resumable and non-resumable instances.
1882
+ * Every entry is a persistent thread; session end never removes an entry,
1883
+ * it only transitions the entry's status.
1832
1884
  */
1833
1885
  readonly children: SubagentRegistryEntry[];
1834
1886
  /**
@@ -1839,7 +1891,7 @@ interface ThreadState {
1839
1891
  /**
1840
1892
  * Arguments supplied when this thread was created or invoked.
1841
1893
  *
1842
- * For resumable subagent child threads, this is the durable
1894
+ * For subagent child threads, this is the durable
1843
1895
  * `subagent_create.arguments` object restored from child thread
1844
1896
  * metadata/properties. Both child sides see the same object. Runtimes also
1845
1897
  * expose these keys to prompt variable interpolation, including included
@@ -2048,6 +2100,10 @@ interface ThreadState {
2048
2100
  * `sessionStop` tool call. By default it has no parent-message or status side
2049
2101
  * effects. Pass `notifyParent` and/or `status` when those effects are desired.
2050
2102
  *
2103
+ * Stopping a session MUST NOT terminate the thread: the thread remains
2104
+ * addressable with its history intact, and a later message starts a new
2105
+ * session. Only `terminate()` destroys a thread.
2106
+ *
2051
2107
  * @throws If called outside an active execution context
2052
2108
  */
2053
2109
  stopSession(options?: StopSessionOptions): Promise<void>;
@@ -3823,236 +3879,18 @@ interface PromptToolConfig {
3823
3879
  options?: Record<string, unknown>;
3824
3880
  }
3825
3881
  /**
3826
- * Configuration for invoking a `dual_ai` agent as a subagent tool.
3827
- *
3828
- * Subagent tools are always autonomous `dual_ai` agents and support both:
3829
- * - Blocking vs non-blocking execution
3830
- * - Resumable vs non-resumable lifecycles
3831
- *
3832
- * Non-resumable subagents behave like normal tool calls.
3833
- * Resumable subagents are created/messaged through runtime-injected lifecycle
3834
- * tools (for example `subagent_create` and `subagent_message`) and tracked in
3835
- * the parent thread registry. The injected `subagent_create` tool MUST require
3836
- * a non-empty human-readable `name` argument and runtimes SHOULD persist it as
3837
- * a child thread display name.
3838
- *
3839
- * Lifecycle tools manage resumable relationships exclusively: runtimes MUST
3840
- * reject a `subagent_create` invocation that targets a relationship without
3841
- * `resumable` configuration, without creating a child, and the rejection
3842
- * SHOULD direct the model to invoke that tool directly instead. Runtimes
3843
- * SHOULD constrain the injected tool's target argument to the exposed names
3844
- * of the prompt's resumable relationships. Lifecycle tool references use the
3845
- * relationship's exposed tool `name`, never an internal agent identifier that
3846
- * differs from it.
3847
- *
3848
- * ### Pull-based child visibility
3849
- *
3850
- * Whenever resumable subagent configs exist, runtimes MUST also inject a
3851
- * `subagents` query tool that returns the model-visible registry snapshot
3852
- * (reference id, name, status, working-status text, initial arguments) as a
3853
- * tool result on demand. Runtimes MUST NOT additionally inject an ambient
3854
- * registry system message into request context when the query tool is
3855
- * available: child state is pull-based (plus completion messages), because a
3856
- * registry block that mutates between requests both invalidates provider
3857
- * prefix caches and reads as out-of-dialogue state to agentic-tuned models.
3858
- * The injected tool descriptions SHOULD direct the model to call `subagents`
3859
- * before `subagent_create` so existing instances are reused instead of
3860
- * duplicated.
3861
- *
3862
- * ### Persistent invocation arguments
3863
- *
3864
- * The child side that receives parent messages dictates initial invocation
3865
- * arguments through that side's prompt `requiredSchema`
3866
- * (`resumable.receives_messages`, defaulting to `side_a`). The invoking parent
3867
- * supplies them when calling the subagent tool or `subagent_create` as a
3868
- * structured `arguments` object.
3869
- *
3870
- * Unlike a plain tool call, these arguments are NOT ephemeral: runtimes MUST
3871
- * persist the validated arguments for the life of the child thread and make
3872
- * them available to BOTH `side_a` and `side_b` through `ThreadState.arguments`
3873
- * and prompt variable interpolation on every activation. This lets a system
3874
- * prompt reference spawn-time context for as long as the thread lives.
3875
- *
3876
- * If required arguments are missing or invalid, runtimes MUST reject creation
3877
- * with a `subagent_arguments_required` error rather than spawning the child.
3878
- *
3879
- * @example
3880
- * ```typescript
3881
- * {
3882
- * name: 'browser_agent',
3883
- * blocking: false,
3884
- * resumable: {
3885
- * receives_messages: 'side_a',
3886
- * maxInstances: 1,
3887
- * },
3888
- * }
3889
- * ```
3890
- *
3891
- * @example
3892
- * ```typescript
3893
- * // The same agent exposed under a task-specific tool name.
3894
- * {
3895
- * name: 'summarize_document',
3896
- * agent: 'document_agent',
3897
- * blocking: true,
3898
- * initUserMessageProperty: 'message',
3899
- * }
3900
- * ```
3882
+ * @deprecated Removed in 0.2.0 — subagent relationships are no longer
3883
+ * declared in a prompt's `tools` array. Declare them on the owning side's
3884
+ * `subagents` array instead (see `SubagentRelationship`): the tool's `name`
3885
+ * becomes `as` (or is dropped when it equals the agent name), `agent` stays
3886
+ * `agent`, and the `resumable` wrapper is unwrapped — `maxInstances` and
3887
+ * `parentCommunication` move to the relationship top level and
3888
+ * `receives_messages` is deleted (declare the relationship on the side that
3889
+ * received the messages). The owning side's prompt automatically receives the
3890
+ * lifecycle tools (`subagents`, `subagent_create`, `subagent_message`).
3891
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
3901
3892
  */
3902
- interface SubagentToolConfig<T extends string = StandardAgentSpec.Callables> {
3903
- /**
3904
- * Exposed tool name — the name the model invokes this subagent by.
3905
- *
3906
- * When `agent` is absent, this MUST reference a `dual_ai` agent with
3907
- * `exposeAsTool: true` directly. When `agent` is present, this may be any
3908
- * valid tool identifier; the runtime MUST expose the tool under this name
3909
- * and MUST resolve invocations to the agent named by `agent`.
3910
- */
3911
- name: T | (string & {});
3912
- /**
3913
- * The `dual_ai` agent this tool invokes, when the tool is exposed under a
3914
- * name other than the agent's own. Must reference a `dual_ai` agent with
3915
- * `exposeAsTool: true`. Defaults to `name`.
3916
- *
3917
- * The same agent may be exposed under different tool names by different
3918
- * prompts. Everything model-facing — the tool schema, instance registries,
3919
- * and subagent lifecycle tool references — uses the exposed `name`;
3920
- * runtimes resolve the implementing agent internally as `agent ?? name`.
3921
- */
3922
- agent?: T;
3923
- /**
3924
- * Whether parent execution blocks until the subagent returns a result.
3925
- *
3926
- * - `true`: Parent waits for completion (tool-call style)
3927
- * - `false`: Parent continues immediately and receives results asynchronously
3928
- *
3929
- * @default true
3930
- */
3931
- blocking?: boolean;
3932
- /**
3933
- * Property from tool-call arguments used as the initial message sent to the
3934
- * subagent on invocation.
3935
- *
3936
- * Uses the same semantics as {@link SubpromptConfig.initUserMessageProperty}.
3937
- */
3938
- initUserMessageProperty?: StandardAgentSpec.SchemaFields<T>;
3939
- /**
3940
- * Property from tool-call arguments containing attachment path(s) that should
3941
- * be sent to the subagent on invocation.
3942
- *
3943
- * Uses the same semantics as {@link SubpromptConfig.initAttachmentsProperty}.
3944
- */
3945
- initAttachmentsProperty?: StandardAgentSpec.SchemaFields<T>;
3946
- /**
3947
- * Property from tool-call arguments used to assign a human-readable name for
3948
- * each spawned child thread instance.
3949
- *
3950
- * Implementations SHOULD store this as a thread tag in the form
3951
- * `name:<value>` so UIs can render a concise per-instance title.
3952
- */
3953
- initAgentNameProperty?: StandardAgentSpec.SchemaFields<T>;
3954
- /**
3955
- * Execute this tool immediately when the prompt becomes active.
3956
- *
3957
- * - `true`: Execute immediately using runtime defaults.
3958
- * - Object: Execute immediately with explicit per-instance env relationships.
3959
- *
3960
- * When the object form is used:
3961
- * - `scopedEnv` names the per-instance env values copied into the child thread.
3962
- * - `nameEnv` and `descriptionEnv` identify the only per-instance env values
3963
- * that runtimes may expose to an internal bootstrap model when deriving
3964
- * initial child arguments.
3965
- *
3966
- * Runtimes MUST NOT expose `scopedEnv` values to the model unless the same env
3967
- * name is explicitly designated by `nameEnv` or `descriptionEnv`.
3968
- *
3969
- * Immediate tools run before the first LLM step for that activation.
3970
- */
3971
- immediate?: boolean | {
3972
- /**
3973
- * Scoped env name whose value may be used as the safe per-instance name
3974
- * hint for child bootstrap.
3975
- */
3976
- nameEnv?: string;
3977
- /**
3978
- * Scoped env name whose value may be used as the safe per-instance
3979
- * description hint for child bootstrap.
3980
- */
3981
- descriptionEnv?: string;
3982
- /**
3983
- * Scoped env names that should be copied into the child thread for each
3984
- * immediate instance group.
3985
- */
3986
- scopedEnv?: string[];
3987
- };
3988
- /**
3989
- * Optional branch flag env name.
3990
- *
3991
- * When set, this subagent is only enabled when the named env resolves to
3992
- * `true`, `1`, or `yes` (case-insensitive).
3993
- */
3994
- optional?: string;
3995
- /**
3996
- * Resumability configuration.
3997
- *
3998
- * - `false` (default): Non-resumable subagent
3999
- * - Object: Resumable subagent with message routing and instance limits
4000
- *
4001
- * When resumable mode is enabled, runtimes SHOULD provide a built-in create
4002
- * and message lifecycle interface instead of exposing raw agent callables for
4003
- * new instance creation.
4004
- */
4005
- resumable?: false | {
4006
- /**
4007
- * Which side of the child `dual_ai` conversation receives parent messages.
4008
- *
4009
- * - `side_a`: Messages are queued as `role: 'user'`
4010
- * - `side_b`: Messages are queued as `role: 'assistant'`
4011
- */
4012
- receives_messages: 'side_a' | 'side_b';
4013
- /**
4014
- * Maximum concurrent instances for this subagent tool.
4015
- *
4016
- * When reached, implementations may remove this tool from subsequent LLM
4017
- * requests and route new messages to existing instances.
4018
- *
4019
- * @default unlimited
4020
- */
4021
- maxInstances?: number;
4022
- /**
4023
- * How this child reports back to its parent.
4024
- *
4025
- * - `implicit` (default): Child completion is automatically queued to the parent.
4026
- * - `explicit`: The runtime does not auto-queue child completion; tools/hooks may
4027
- * use thread APIs such as `state.notifyParent()` or `state.stopSession()` when
4028
- * they choose to escalate or terminally end the session.
4029
- */
4030
- parentCommunication?: 'implicit' | 'explicit';
4031
- };
4032
- /**
4033
- * How this subagent reports completion back to its parent. Applies to
4034
- * non-resumable subagents; resumable subagents may instead set
4035
- * `resumable.parentCommunication`, which takes precedence when present.
4036
- *
4037
- * - `implicit` (default): the child's completion is auto-queued to the parent,
4038
- * which triggers a parent turn.
4039
- * - `explicit`: the runtime does NOT auto-queue the child's completion, so the
4040
- * parent is not woken. Use for background subagents that deliver their result
4041
- * another way (e.g. writing to the parent's thread KV) and should be "picked
4042
- * up" on the parent's next natural turn rather than forcing one.
4043
- */
4044
- parentCommunication?: 'implicit' | 'explicit';
4045
- /**
4046
- * Hide this subagent tool from the LLM's tool list while keeping the
4047
- * relationship declared, so runtime code (hooks calling
4048
- * `state.invokeTool()` / `queueTool()`) can still spawn it. Use for
4049
- * infrastructure subagents the model must never call itself (e.g. a
4050
- * background context-compaction agent).
4051
- *
4052
- * @default false
4053
- */
4054
- hidden?: boolean;
4055
- }
3893
+ type SubagentToolConfig<T extends string = string> = never;
4056
3894
  /**
4057
3895
  * Reasoning configuration for models that support extended thinking.
4058
3896
  * Applies to models like OpenAI o1/o3, Anthropic Claude with extended thinking,
@@ -4177,13 +4015,12 @@ interface PromptDefinition<N extends string = string, S extends ToolArgs = ToolA
4177
4015
  /**
4178
4016
  * Zod schema for validating inputs when this prompt is called as a tool.
4179
4017
  *
4180
- * When this prompt is the `side_a` prompt of a `dual_ai` agent exposed as a
4181
- * subagent, this schema also dictates the invocation arguments accepted by
4182
- * the subagent tool (and the runtime-injected `subagent_create` tool).
4183
- * Required fields are mandatory; optional fields are treated as suggested.
4184
- * Runtimes persist the validated arguments for the life of the child thread
4185
- * and expose them to both sides' prompt interpolation (see
4186
- * {@link SubagentToolConfig} "Persistent invocation arguments").
4018
+ * When this prompt backs side A of an agent composed as a subagent, this
4019
+ * schema also dictates the invocation arguments accepted by the
4020
+ * runtime-injected `subagent_create` tool. Required fields are mandatory;
4021
+ * optional fields are treated as suggested. Runtimes persist the validated
4022
+ * arguments for the life of the child thread and expose them to both
4023
+ * sides' prompt interpolation through `ThreadState.arguments`.
4187
4024
  */
4188
4025
  requiredSchema?: S;
4189
4026
  /**
@@ -4196,9 +4033,14 @@ interface PromptDefinition<N extends string = string, S extends ToolArgs = ToolA
4196
4033
  * - string: Simple tool name (custom or provider tool)
4197
4034
  * - SubpromptConfig: Sub-prompt used as a tool
4198
4035
  * - PromptToolConfig: Tool with environment values and/or options
4199
- * - SubagentToolConfig: `dual_ai` subagent invocation behavior
4200
4036
  *
4201
- * To enable handoffs, include ai_human agent names in this array.
4037
+ * To enable handoffs, include exposed agent names in this array.
4038
+ *
4039
+ * Subagent relationships are NOT declared here — they live on the owning
4040
+ * side's `subagents` array, and the runtime injects the lifecycle tools
4041
+ * (`subagents`, `subagent_create`, `subagent_message`) for the side's
4042
+ * non-hidden relationships automatically. Handlers may never appear in
4043
+ * this array.
4202
4044
  *
4203
4045
  * @example
4204
4046
  * ```typescript
@@ -4209,7 +4051,7 @@ interface PromptDefinition<N extends string = string, S extends ToolArgs = ToolA
4209
4051
  * ]
4210
4052
  * ```
4211
4053
  */
4212
- tools?: (StandardAgentSpec.Callables | SubpromptConfig | PromptToolConfig | SubagentToolConfig)[];
4054
+ tools?: (StandardAgentSpec.Callables | SubpromptConfig | PromptToolConfig)[];
4213
4055
  /**
4214
4056
  * Environment values provided by this prompt.
4215
4057
  * Prompt values override user-account and AgentBuilder-instance defaults.
@@ -4296,21 +4138,213 @@ type PromptInput<T extends PromptDefinition<string, ToolArgs>> = T['requiredSche
4296
4138
  declare function definePrompt<N extends string, S extends ToolArgs = never>(options: PromptDefinition<N, S>): PromptDefinition<N, S>;
4297
4139
 
4298
4140
  /**
4299
- * Agent definition types for Standard Agents.
4141
+ * Subagent relationship types for Standard Agents.
4142
+ *
4143
+ * A subagent relationship is declared on the side of an agent that owns it
4144
+ * (`side.subagents`), not on a prompt. The relationship is architecture:
4145
+ * which agent may be instantiated as a child, under what name, with what
4146
+ * lifecycle configuration. Prompts no longer declare relationships in their
4147
+ * `tools` arrays — the owning side's prompt automatically receives the
4148
+ * lifecycle tools (`subagents`, `subagent_create`, `subagent_message`) for
4149
+ * the side's non-hidden relationships.
4300
4150
  *
4301
- * Agents orchestrate conversations between AI models (dual_ai) or between
4302
- * AI and human users (ai_human). They define the prompts, stop conditions,
4303
- * and behavioral rules for each side of the conversation.
4151
+ * https://standardagentspec.com/0.2.0/specification/subagents
4304
4152
  *
4305
4153
  * @module
4306
4154
  */
4307
4155
  /**
4308
- * Agent conversation type.
4156
+ * A side-owned subagent relationship.
4157
+ *
4158
+ * Ownership rules:
4159
+ * - The relationship belongs to the side that declares it. Inbound child
4160
+ * traffic (completions, `notifyParent`, messages queued toward the parent)
4161
+ * lands on the owning side's perspective.
4162
+ * - A relationship name (`as`, defaulted or explicit) may appear on at most
4163
+ * ONE side of an agent — a definition-time error otherwise.
4164
+ * - Relationship names share the tool namespace. A name colliding with a
4165
+ * tool name, or with the reserved lifecycle tool names (`subagents`,
4166
+ * `subagent_create`, `subagent_message`), is a definition-time error.
4167
+ * - Two relationships may target the same `agent` under different `as`
4168
+ * names, each with independent configuration.
4169
+ *
4170
+ * Instance lifecycle: every child instance is a persistent thread. Session
4171
+ * end — stop, fail, error, or turn-cap — never terminates a thread; only
4172
+ * explicit termination destroys an instance. With `blocking: true`,
4173
+ * `maxInstances: 1`, and a live instance, `subagent_create` means
4174
+ * create-or-continue: message the existing instance and await that session's
4175
+ * close.
4309
4176
  *
4310
- * - `ai_human`: AI conversing with a human user (most common)
4311
- * - `dual_ai`: Two AI participants conversing with each other
4177
+ * @template Agent - The agent name type (string or type-safe union)
4178
+ *
4179
+ * @example
4180
+ * ```typescript
4181
+ * sideA: {
4182
+ * prompt: 'coordinator',
4183
+ * subagents: [
4184
+ * { agent: 'calendar_agent', as: 'work_calendar', scopedEnv: ['WORK_CAL_ID'] },
4185
+ * { agent: 'calendar_agent', as: 'personal_calendar', scopedEnv: ['PERSONAL_CAL_ID'] },
4186
+ * { agent: 'research_agent', blocking: true, maxInstances: 1 },
4187
+ * ],
4188
+ * }
4189
+ * ```
4312
4190
  */
4313
- type AgentType = 'ai_human' | 'dual_ai';
4191
+ interface SubagentRelationship<Agent extends string = StandardAgentSpec.Agents> {
4192
+ /**
4193
+ * Which agent definition to instantiate. Must reference an agent with
4194
+ * `exposeAsTool: true`.
4195
+ */
4196
+ readonly agent: Agent;
4197
+ /**
4198
+ * Relationship name; defaults to `agent`.
4199
+ *
4200
+ * This is the tool-surface name, the registry identity, and the name the
4201
+ * lifecycle tools' `agent` argument enumerates. Aliasing lets the same
4202
+ * child agent be composed twice under one side with independent
4203
+ * configuration.
4204
+ */
4205
+ readonly as?: string;
4206
+ /**
4207
+ * Model-facing description override for this relationship. Falls back to
4208
+ * the child agent's `toolDescription`.
4209
+ */
4210
+ readonly description?: string;
4211
+ /**
4212
+ * Maximum concurrent instances for this relationship. Unset = unbounded.
4213
+ */
4214
+ readonly maxInstances?: number;
4215
+ /**
4216
+ * Spawn an instance at THREAD CREATION, before any side takes a turn.
4217
+ *
4218
+ * - `true`: spawn immediately using runtime defaults.
4219
+ * - Object: spawn immediately with explicit per-instance env wiring.
4220
+ *
4221
+ * When the object form is used:
4222
+ * - `scopedEnv` names the per-instance env values copied into the child
4223
+ * thread.
4224
+ * - `nameEnv` and `descriptionEnv` identify the only per-instance env
4225
+ * values that runtimes may expose to an internal bootstrap model when
4226
+ * deriving initial child arguments.
4227
+ *
4228
+ * Runtimes MUST NOT expose `scopedEnv` values to a model unless the same
4229
+ * env name is explicitly designated by `nameEnv` or `descriptionEnv`.
4230
+ */
4231
+ readonly immediate?: boolean | {
4232
+ /**
4233
+ * Scoped env name whose value may be used as the safe per-instance
4234
+ * name hint for child bootstrap.
4235
+ */
4236
+ readonly nameEnv?: string;
4237
+ /**
4238
+ * Scoped env name whose value may be used as the safe per-instance
4239
+ * description hint for child bootstrap.
4240
+ */
4241
+ readonly descriptionEnv?: string;
4242
+ /**
4243
+ * Scoped env names copied into the child thread for each immediate
4244
+ * instance group.
4245
+ */
4246
+ readonly scopedEnv?: readonly string[];
4247
+ };
4248
+ /**
4249
+ * Whether `subagent_create` awaits the child session's close and returns
4250
+ * its result.
4251
+ *
4252
+ * - `true`: the invoking turn waits for the session result.
4253
+ * - `false` (default): the parent continues immediately and receives
4254
+ * results asynchronously.
4255
+ */
4256
+ readonly blocking?: boolean;
4257
+ /**
4258
+ * How this child reports back to its parent.
4259
+ *
4260
+ * - `implicit` (default): child completion/failure is automatically queued
4261
+ * to the owning side's perspective, which triggers a parent turn.
4262
+ * - `explicit`: the runtime does not auto-queue child completion; child
4263
+ * code escalates via `state.notifyParent()` / `state.setStatus()` when
4264
+ * it chooses.
4265
+ */
4266
+ readonly parentCommunication?: 'implicit' | 'explicit';
4267
+ /**
4268
+ * Env names copied from the parent into each spawned child thread.
4269
+ * Runtime-only; never model-visible unless designated by the `immediate`
4270
+ * object form's `nameEnv`/`descriptionEnv`.
4271
+ */
4272
+ readonly scopedEnv?: readonly string[];
4273
+ /**
4274
+ * Property from `subagent_create` arguments used as the initial user
4275
+ * message when spawning an instance.
4276
+ */
4277
+ readonly initUserMessageProperty?: StandardAgentSpec.SchemaFields<Agent>;
4278
+ /**
4279
+ * Property from `subagent_create` arguments containing attachment path(s)
4280
+ * to include with the initial message.
4281
+ */
4282
+ readonly initAttachmentsProperty?: StandardAgentSpec.SchemaFields<Agent>;
4283
+ /**
4284
+ * Property from `subagent_create` arguments used as a human-readable name
4285
+ * for each spawned instance. Implementations SHOULD store this as a thread
4286
+ * tag in the form `name:<value>`.
4287
+ */
4288
+ readonly initAgentNameProperty?: StandardAgentSpec.SchemaFields<Agent>;
4289
+ /**
4290
+ * Optional branch flag env name. When set, this relationship is only
4291
+ * enabled when the named env resolves to `true`, `1`, or `yes`
4292
+ * (case-insensitive).
4293
+ */
4294
+ readonly optional?: string;
4295
+ /**
4296
+ * Keep the relationship declared and spawnable by runtime code while
4297
+ * excluding it from every model request and from the injected `subagents`
4298
+ * registry snapshot. Use for infrastructure children the model must never
4299
+ * call or manage itself.
4300
+ *
4301
+ * @default false
4302
+ */
4303
+ readonly hidden?: boolean;
4304
+ /**
4305
+ * @deprecated Removed in 0.2.0 — the exposed tool name is now `as`, and
4306
+ * the target agent is `agent`. See the migration guide:
4307
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
4308
+ */
4309
+ readonly name?: never;
4310
+ /**
4311
+ * @deprecated Removed in 0.2.0 — every child instance is a persistent
4312
+ * thread; the `resumable` wrapper is gone. Move `maxInstances` and
4313
+ * `parentCommunication` to the relationship top level and delete
4314
+ * `receives_messages` (declare the relationship on the side that received
4315
+ * the messages). See the migration guide:
4316
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
4317
+ */
4318
+ readonly resumable?: never;
4319
+ /**
4320
+ * @deprecated Removed in 0.2.0 — child traffic lands on the perspective of
4321
+ * the side that OWNS the relationship. Declare the relationship on the
4322
+ * side that should receive the messages. See the migration guide:
4323
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
4324
+ */
4325
+ readonly receives_messages?: never;
4326
+ }
4327
+
4328
+ /**
4329
+ * Agent definition types for Standard Agents.
4330
+ *
4331
+ * An agent has exactly two sides, and each side is backed by exactly one of
4332
+ * three things: a human, a prompt, or a handler. There is no agent "type" —
4333
+ * everything that used to hang off a type enum is derived from what backs
4334
+ * each side.
4335
+ *
4336
+ * https://standardagentspec.com/0.2.0/specification/agents
4337
+ *
4338
+ * @module
4339
+ */
4340
+
4341
+ /**
4342
+ * @deprecated Removed in 0.2.0 — there is no agent "type". Sides are
4343
+ * backings: declare both sides explicitly with `human`, `prompt`, or
4344
+ * `handler`. See the migration guide:
4345
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
4346
+ */
4347
+ type AgentType = never;
4314
4348
  /**
4315
4349
  * Ordering position for a child agent's required hook on its parent.
4316
4350
  */
@@ -4319,22 +4353,23 @@ type ParentHookStage = 'before_parent' | 'after_parent';
4319
4353
  * A thread-scoped hook that a child agent requires on every direct parent.
4320
4354
  *
4321
4355
  * Downloading a package is inert. The hook becomes active automatically when
4322
- * an enabled parent prompt exposes this `dual_ai` agent as a child tool, and
4323
- * remains active for exactly the lifetime of that relationship.
4356
+ * an enabled parent side declares a subagent relationship targeting this
4357
+ * exposed agent, and remains active for exactly the lifetime of that
4358
+ * relationship. Any exposed agent may declare parent hooks.
4324
4359
  */
4325
4360
  interface ParentHookRequirement<Hook extends string = StandardAgentSpec.HookIds> {
4326
4361
  /** Child-local hook ID from `defineHook({ id })`. */
4327
- hook: Hook;
4362
+ readonly hook: Hook;
4328
4363
  /** Human-facing explanation shown by installers and composition UIs. */
4329
- reason: string;
4364
+ readonly reason: string;
4330
4365
  /** Whether the hook runs before or after the parent's own hook set. */
4331
- stage?: ParentHookStage;
4366
+ readonly stage?: ParentHookStage;
4332
4367
  }
4333
4368
  /**
4334
4369
  * Configuration for a session lifecycle tool.
4335
4370
  *
4336
- * Used by side-level lifecycle options (`sessionStop`, `sessionFail`, `sessionStatus`)
4337
- * to declare:
4371
+ * Used by prompt-side lifecycle options (`sessionStop`, `sessionFail`,
4372
+ * `sessionStatus`) to declare:
4338
4373
  * - which tool controls that lifecycle action
4339
4374
  * - which tool-argument field should be forwarded as message text
4340
4375
  * - which tool-argument field contains attachment path(s) to forward
@@ -4345,118 +4380,138 @@ interface SessionToolConfig<Callable extends string = StandardAgentSpec.Callable
4345
4380
  /**
4346
4381
  * Tool name for this session lifecycle action.
4347
4382
  */
4348
- name: Callable;
4383
+ readonly name: Callable;
4349
4384
  /**
4350
4385
  * Optional tool-argument property used as lifecycle message text.
4351
4386
  */
4352
- messageProperty?: string;
4387
+ readonly messageProperty?: string;
4353
4388
  /**
4354
4389
  * Optional tool-argument property containing attachment path(s).
4355
4390
  * Supports a single path string or an array of path strings.
4356
4391
  */
4357
- attachmentsProperty?: string;
4392
+ readonly attachmentsProperty?: string;
4358
4393
  }
4359
4394
  /**
4360
4395
  * Session lifecycle tool reference.
4361
4396
  *
4362
- * Can be either:
4363
- * - a plain tool name string (legacy/simple form)
4364
- * - a {@link SessionToolConfig} object (explicit mapping form)
4397
+ * Object form only — the bare-string binding was removed in 0.2.0. Use
4398
+ * `{ name: 'tool_name' }` in place of `'tool_name'`.
4365
4399
  */
4366
- type SessionToolBinding<Callable extends string = StandardAgentSpec.Callables> = Callable | SessionToolConfig<Callable>;
4400
+ type SessionToolBinding<Callable extends string = StandardAgentSpec.Callables> = SessionToolConfig<Callable>;
4367
4401
  /**
4368
- * Configuration for one side of an agent conversation.
4402
+ * A side backed by a human: a person takes this side's turns, through
4403
+ * whatever interface the runtime provides.
4404
+ *
4405
+ * The specification defines only the waiting state — execution parks
4406
+ * awaiting human input, fulfilled by an inbound message on this side's
4407
+ * perspective. Who the person is and how their input arrives is the
4408
+ * runtime's concern.
4369
4409
  *
4370
- * Each side has a prompt, stop conditions, and turn limits.
4371
- * For `ai_human` agents, only sideA (the AI) needs configuration.
4372
- * For `dual_ai` agents, both sides need configuration.
4410
+ * Human-backed sides cannot own subagent relationships (nothing there can
4411
+ * invoke them) and have no step, stop, or session-binding options.
4412
+ */
4413
+ interface HumanSide {
4414
+ /** Marks this side as human-backed. */
4415
+ readonly human: true;
4416
+ /**
4417
+ * Custom label for this side of the conversation.
4418
+ * Used in UI and logs for clarity.
4419
+ */
4420
+ readonly label?: string;
4421
+ readonly prompt?: never;
4422
+ readonly handler?: never;
4423
+ readonly subagents?: never;
4424
+ readonly stopOnResponse?: never;
4425
+ readonly stopTool?: never;
4426
+ readonly stopToolResponseProperty?: never;
4427
+ readonly maxSteps?: never;
4428
+ readonly sessionStop?: never;
4429
+ readonly sessionFail?: never;
4430
+ readonly sessionStatus?: never;
4431
+ }
4432
+ /**
4433
+ * A side backed by a prompt: a model takes this side's turns.
4373
4434
  *
4374
4435
  * @template Prompt - The prompt reference type (string or type-safe union)
4375
4436
  * @template Callable - The callable reference type (string or type-safe union)
4376
- *
4377
- * @example
4378
- * ```typescript
4379
- * const sideConfig: SideConfig = {
4380
- * label: 'Support Agent',
4381
- * prompt: 'customer_support',
4382
- * stopOnResponse: true,
4383
- * maxSteps: 10,
4384
- * };
4385
- * ```
4386
4437
  */
4387
- interface SideConfig<Prompt extends string = StandardAgentSpec.Prompts, Callable extends string = StandardAgentSpec.Callables> {
4438
+ interface PromptSide<Prompt extends string = StandardAgentSpec.Prompts, Callable extends string = StandardAgentSpec.Callables> {
4439
+ /**
4440
+ * The prompt to use for this side.
4441
+ * Must reference a prompt defined in agents/prompts/.
4442
+ */
4443
+ readonly prompt: Prompt;
4388
4444
  /**
4389
4445
  * Custom label for this side of the conversation.
4390
4446
  * Used in UI and logs for clarity.
4391
4447
  *
4392
4448
  * @example 'Support Agent', 'Customer', 'ATC', 'Pilot'
4393
4449
  */
4394
- label?: string;
4450
+ readonly label?: string;
4395
4451
  /**
4396
- * The prompt to use for this side.
4397
- * Must reference a prompt defined in agents/prompts/.
4452
+ * Subagent relationships OWNED by this side.
4453
+ *
4454
+ * The owning side's prompt automatically receives the lifecycle tools
4455
+ * (`subagents`, `subagent_create`, `subagent_message`) for the side's
4456
+ * non-hidden relationships — the side's declaration is the grant. Inbound
4457
+ * child traffic lands on this side's perspective.
4398
4458
  */
4399
- prompt: Prompt;
4459
+ readonly subagents?: readonly SubagentRelationship[];
4400
4460
  /**
4401
4461
  * Stop this side's turn when it returns a text response (no tool calls).
4402
4462
  * When true, the side's turn ends after producing a message without tools.
4403
4463
  * @default true
4404
4464
  */
4405
- stopOnResponse?: boolean;
4465
+ readonly stopOnResponse?: boolean;
4406
4466
  /**
4407
4467
  * Stop this side's turn when a specific tool is called.
4408
4468
  * Overrides stopOnResponse when the named tool is invoked.
4409
4469
  * Requires stopToolResponseProperty to extract the result.
4410
4470
  */
4411
- stopTool?: Callable;
4471
+ readonly stopTool?: Callable;
4412
4472
  /**
4413
4473
  * Property to extract from the stop tool's result.
4414
4474
  * Required when stopTool is set.
4415
4475
  * The extracted value is used to determine the conversation outcome.
4416
4476
  */
4417
- stopToolResponseProperty?: string;
4477
+ readonly stopToolResponseProperty?: string;
4418
4478
  /**
4419
4479
  * Maximum steps for this side before forcing a stop.
4420
4480
  * Safety limit to prevent runaway execution.
4421
4481
  * A step is one complete LLM request/response cycle.
4422
4482
  */
4423
- maxSteps?: number;
4483
+ readonly maxSteps?: number;
4424
4484
  /**
4425
4485
  * Tool that ends the entire session when called.
4426
4486
  *
4427
4487
  * Different from stopTool: this ends the session for both sides,
4428
- * not just this side's turn.
4429
- *
4430
- * Use object form to explicitly map message/attachment argument fields.
4488
+ * not just this side's turn. Ending a session never terminates the thread.
4431
4489
  *
4432
4490
  * In subagent runtimes, mapped message/attachments are the canonical
4433
4491
  * completion payload returned from child -> parent.
4434
4492
  */
4435
- sessionStop?: SessionToolBinding<Callable>;
4493
+ readonly sessionStop?: SessionToolBinding<Callable>;
4436
4494
  /**
4437
4495
  * Tool that fails the entire session when called.
4438
4496
  *
4439
- * Use this when the side cannot fulfill the request and needs to terminate
4440
- * the session with an error outcome.
4441
- *
4442
- * When used inside a subagent, this failure is propagated back to the parent
4443
- * as a terminal failure result.
4497
+ * Use this when the side cannot fulfill the request and needs to end
4498
+ * the session with an error outcome. Failing a session never terminates
4499
+ * the thread.
4444
4500
  *
4445
- * Use object form to explicitly map message/attachment argument fields.
4501
+ * When used inside a subagent, this failure is propagated back to the
4502
+ * parent as a terminal failure result.
4446
4503
  *
4447
4504
  * In subagent runtimes, mapped message/attachments are the canonical
4448
4505
  * failure payload returned from child -> parent.
4449
4506
  */
4450
- sessionFail?: SessionToolBinding<Callable>;
4507
+ readonly sessionFail?: SessionToolBinding<Callable>;
4451
4508
  /**
4452
- * Tool that publishes status updates to the parent thread when used as a subagent.
4509
+ * Tool that publishes status updates to the parent thread when this agent
4510
+ * runs as a subagent.
4453
4511
  *
4454
- * When called from a `dual_ai` subagent, message text is forwarded to
4455
- * the parent thread's subagent registry as this instance's current status.
4456
- *
4457
- * Use object form to explicitly map message/attachment argument fields.
4458
- *
4459
- * Status updates do not terminate the session.
4512
+ * Message text is forwarded to the parent thread's subagent registry as
4513
+ * this instance's current working status. Status updates do not end the
4514
+ * session.
4460
4515
  *
4461
4516
  * @example
4462
4517
  * ```typescript
@@ -4466,14 +4521,66 @@ interface SideConfig<Prompt extends string = StandardAgentSpec.Prompts, Callable
4466
4521
  * }
4467
4522
  * ```
4468
4523
  */
4469
- sessionStatus?: SessionToolBinding<Callable>;
4524
+ readonly sessionStatus?: SessionToolBinding<Callable>;
4525
+ readonly human?: never;
4526
+ readonly handler?: never;
4527
+ }
4528
+ /**
4529
+ * A side backed by a handler: deterministic code takes this side's turns.
4530
+ *
4531
+ * A handler turn has no steps to cap and ends when `execute` returns, so
4532
+ * step, stop, and session-binding options are not legal here — handlers end
4533
+ * sessions explicitly via `state.stopSession()`.
4534
+ *
4535
+ * @template Handler - The handler reference type (string or type-safe union)
4536
+ */
4537
+ interface HandlerSide<Handler extends string = StandardAgentSpec.Handlers> {
4538
+ /**
4539
+ * The handler that takes this side's turns.
4540
+ * Must reference a handler defined in agents/handlers/.
4541
+ */
4542
+ readonly handler: Handler;
4543
+ /**
4544
+ * Custom label for this side of the conversation.
4545
+ * Used in UI and logs for clarity.
4546
+ */
4547
+ readonly label?: string;
4548
+ /**
4549
+ * Subagent relationships OWNED by this side.
4550
+ *
4551
+ * Handlers need no tool grant; they reach children through `ThreadState`.
4552
+ * The declaration's job for a handler side is existence and lifecycle.
4553
+ * Inbound child traffic lands on this side's perspective.
4554
+ */
4555
+ readonly subagents?: readonly SubagentRelationship[];
4556
+ readonly human?: never;
4557
+ readonly prompt?: never;
4558
+ readonly stopOnResponse?: never;
4559
+ readonly stopTool?: never;
4560
+ readonly stopToolResponseProperty?: never;
4561
+ readonly maxSteps?: never;
4562
+ readonly sessionStop?: never;
4563
+ readonly sessionFail?: never;
4564
+ readonly sessionStatus?: never;
4470
4565
  }
4566
+ /**
4567
+ * Configuration for one side of an agent conversation.
4568
+ *
4569
+ * Exactly one backing per side: `human`, `prompt`, or `handler`. Both sides
4570
+ * human is reserved — runtimes MUST reject it in this version.
4571
+ *
4572
+ * @template Prompt - The prompt reference type (string or type-safe union)
4573
+ * @template Callable - The callable reference type (string or type-safe union)
4574
+ * @template Handler - The handler reference type (string or type-safe union)
4575
+ */
4576
+ type SideConfig<Prompt extends string = StandardAgentSpec.Prompts, Callable extends string = StandardAgentSpec.Callables, Handler extends string = StandardAgentSpec.Handlers> = HumanSide | PromptSide<Prompt, Callable> | HandlerSide<Handler>;
4471
4577
  /**
4472
4578
  * Agent definition configuration.
4473
4579
  *
4474
4580
  * @template N - The agent name as a string literal type
4475
4581
  * @template Prompt - The prompt reference type (string or type-safe union)
4476
4582
  * @template Callable - The callable reference type (string or type-safe union)
4583
+ * @template Handler - The handler reference type (string or type-safe union)
4477
4584
  *
4478
4585
  * @example
4479
4586
  * ```typescript
@@ -4481,63 +4588,65 @@ interface SideConfig<Prompt extends string = StandardAgentSpec.Prompts, Callable
4481
4588
  *
4482
4589
  * export default defineAgent({
4483
4590
  * name: 'support_agent',
4484
- * title: 'Customer Support Agent',
4485
- * type: 'ai_human',
4486
4591
  * sideA: {
4487
4592
  * label: 'Support',
4488
4593
  * prompt: 'customer_support',
4489
4594
  * stopOnResponse: true,
4490
4595
  * },
4596
+ * sideB: { human: true },
4491
4597
  * });
4492
4598
  * ```
4493
4599
  */
4494
- interface AgentDefinition<N extends string = string, Prompt extends string = StandardAgentSpec.Prompts, Callable extends string = StandardAgentSpec.Callables> {
4600
+ interface AgentDefinition<N extends string = string, Prompt extends string = StandardAgentSpec.Prompts, Callable extends string = StandardAgentSpec.Callables, Handler extends string = StandardAgentSpec.Handlers> {
4495
4601
  /**
4496
4602
  * Unique name for this agent.
4497
4603
  * Used as the identifier for thread creation and handoffs.
4498
4604
  * Should be snake_case (e.g., 'support_agent', 'research_flow').
4499
4605
  */
4500
- name: N;
4606
+ readonly name: N;
4501
4607
  /**
4502
4608
  * Human-readable title for the agent.
4503
4609
  * Optional - if not provided, the name will be used.
4504
4610
  * @deprecated Use name instead. Title will be removed in a future version.
4505
4611
  */
4506
- title?: string;
4612
+ readonly title?: string;
4507
4613
  /**
4508
- * Agent conversation type.
4509
- *
4510
- * - `ai_human`: AI conversing with a human user (default)
4511
- * - `dual_ai`: Two AI participants conversing
4512
- *
4513
- * @default 'ai_human'
4614
+ * @deprecated Removed in 0.2.0 — there is no agent "type". Delete this
4615
+ * field and declare both sides explicitly: what used to be
4616
+ * `type: 'ai_human'` is `sideB: { human: true }`; what used to be
4617
+ * `type: 'dual_ai'` is two prompt-backed sides. See the migration guide:
4618
+ * https://standardagentspec.com/0.2.0/getting-started/changelog
4514
4619
  */
4515
- type?: AgentType;
4620
+ readonly type?: never;
4516
4621
  /**
4517
- * Maximum total turns across both sides.
4518
- * Only applies to `dual_ai` agents.
4519
- * Prevents infinite loops in AI-to-AI conversations.
4622
+ * Maximum total exchanges across both sides before the runtime ends the
4623
+ * session.
4624
+ *
4625
+ * Optional on every side combination — a voluntary safety valve, not a
4626
+ * requirement. Exchange counting is uniform across backings: a handler
4627
+ * turn counts exactly like a prompt turn. Reaching the cap ends the
4628
+ * session; it never terminates the thread.
4520
4629
  */
4521
- maxSessionTurns?: number;
4630
+ readonly maxSessionTurns?: number;
4522
4631
  /**
4523
- * Configuration for Side A.
4524
- * For `ai_human`: This is the AI side.
4525
- * For `dual_ai`: This is the first AI participant.
4632
+ * Configuration for side A. Backed by exactly one of `human`, `prompt`,
4633
+ * or `handler`.
4526
4634
  */
4527
- sideA: SideConfig<Prompt, Callable>;
4635
+ readonly sideA: SideConfig<Prompt, Callable, Handler>;
4528
4636
  /**
4529
- * Configuration for Side B.
4530
- * For `ai_human`: Optional, the human side doesn't need config.
4531
- * For `dual_ai`: Required, the second AI participant.
4637
+ * Configuration for side B. Backed by exactly one of `human`, `prompt`,
4638
+ * or `handler`. Both sides are always explicit — for a chat agent this is
4639
+ * `sideB: { human: true }`.
4532
4640
  */
4533
- sideB?: SideConfig<Prompt, Callable>;
4641
+ readonly sideB: SideConfig<Prompt, Callable, Handler>;
4534
4642
  /**
4535
4643
  * Expose this agent as a tool for other prompts.
4536
4644
  * Enables agent composition and handoffs.
4537
- * When true, other prompts can invoke this agent as a tool.
4645
+ * When true, other prompts can invoke this agent as a tool and sides can
4646
+ * declare subagent relationships targeting it.
4538
4647
  * @default false
4539
4648
  */
4540
- exposeAsTool?: boolean;
4649
+ readonly exposeAsTool?: boolean;
4541
4650
  /**
4542
4651
  * Whether this agent is a PRIMARY, user-facing entry point (default true).
4543
4652
  *
@@ -4548,36 +4657,36 @@ interface AgentDefinition<N extends string = string, Prompt extends string = Sta
4548
4657
  * visible; UIs use this flag to keep them out of top-level agent lists
4549
4658
  * and pickers so one logical product agent doesn't show up N times.
4550
4659
  */
4551
- primary?: boolean;
4660
+ readonly primary?: boolean;
4552
4661
  /**
4553
4662
  * Description shown when agent is used as a tool.
4554
4663
  * Required if exposeAsTool is true.
4555
4664
  * Should clearly describe what this agent does.
4556
4665
  */
4557
- toolDescription?: string;
4666
+ readonly toolDescription?: string;
4558
4667
  /**
4559
4668
  * Brief description of what this agent does.
4560
4669
  * Useful for UIs and documentation.
4561
4670
  *
4562
4671
  * @example 'Handles customer support inquiries and resolves issues'
4563
4672
  */
4564
- description?: string;
4673
+ readonly description?: string;
4565
4674
  /**
4566
4675
  * Icon URL or absolute path for the agent.
4567
4676
  * Absolute paths (starting with `/`) are converted to full URLs in API responses.
4568
4677
  *
4569
4678
  * @example 'https://example.com/icon.svg' or '/icons/support.svg'
4570
4679
  */
4571
- icon?: string;
4680
+ readonly icon?: string;
4572
4681
  /**
4573
4682
  * Environment values provided by this agent.
4574
4683
  * Agent values are lower priority than thread/account/instance values.
4575
4684
  */
4576
- env?: Record<string, string>;
4685
+ readonly env?: Readonly<Record<string, string>>;
4577
4686
  /**
4578
4687
  * @deprecated Use `env` instead.
4579
4688
  */
4580
- tenvs?: Record<string, unknown>;
4689
+ readonly tenvs?: Readonly<Record<string, unknown>>;
4581
4690
  /**
4582
4691
  * npm package name for this agent when packed.
4583
4692
  * Used by the packing system to maintain consistent package identity
@@ -4585,7 +4694,7 @@ interface AgentDefinition<N extends string = string, Prompt extends string = Sta
4585
4694
  *
4586
4695
  * @example 'standardagent-support-agent', '@myorg/support-agent'
4587
4696
  */
4588
- packageName?: string;
4697
+ readonly packageName?: string;
4589
4698
  /**
4590
4699
  * Package version (semver format).
4591
4700
  * Used by the packing system to track versions across pack/unpack cycles.
@@ -4593,21 +4702,21 @@ interface AgentDefinition<N extends string = string, Prompt extends string = Sta
4593
4702
  *
4594
4703
  * @example '1.0.0', '2.3.1-beta.1'
4595
4704
  */
4596
- version?: string;
4705
+ readonly version?: string;
4597
4706
  /**
4598
4707
  * Package author/copyright holder.
4599
4708
  * Used by the packing system for the LICENSE file and package.json author field.
4600
4709
  *
4601
4710
  * @example 'John Doe', 'Acme Corp'
4602
4711
  */
4603
- author?: string;
4712
+ readonly author?: string;
4604
4713
  /**
4605
4714
  * License identifier (SPDX format).
4606
4715
  * Used by the packing system for LICENSE file generation.
4607
4716
  *
4608
4717
  * @example 'MIT', 'Apache-2.0', 'ISC'
4609
4718
  */
4610
- license?: string;
4719
+ readonly license?: string;
4611
4720
  /**
4612
4721
  * Hook IDs to run for this agent.
4613
4722
  * References hooks by their unique `id` property from defineHook().
@@ -4618,15 +4727,15 @@ interface AgentDefinition<N extends string = string, Prompt extends string = Sta
4618
4727
  * hooks: ['log_messages', 'track_tool_usage']
4619
4728
  * ```
4620
4729
  */
4621
- hooks?: StandardAgentSpec.HookIds[];
4730
+ readonly hooks?: readonly StandardAgentSpec.HookIds[];
4622
4731
  /**
4623
- * Hooks this agent requires on a direct parent when composed as a `dual_ai`
4624
- * child tool.
4732
+ * Hooks this agent requires on a direct parent when composed as a child.
4625
4733
  *
4626
- * Adding an enabled relationship activates these hooks automatically;
4627
- * downloading the package alone does not. Hooks execute against the
4628
- * parent's ThreadState and are resolved in this agent's package namespace.
4629
- * `reason` is required so composition tooling can disclose the behavior.
4734
+ * Legal on any exposed agent. Adding an enabled relationship activates
4735
+ * these hooks automatically; downloading the package alone does not.
4736
+ * Hooks execute against the parent's ThreadState and are resolved in this
4737
+ * agent's package namespace. `reason` is required so composition tooling
4738
+ * can disclose the behavior.
4630
4739
  *
4631
4740
  * @example
4632
4741
  * ```typescript
@@ -4637,14 +4746,18 @@ interface AgentDefinition<N extends string = string, Prompt extends string = Sta
4637
4746
  * }]
4638
4747
  * ```
4639
4748
  */
4640
- parentHooks?: ParentHookRequirement[];
4749
+ readonly parentHooks?: readonly ParentHookRequirement[];
4641
4750
  }
4642
4751
  /**
4643
4752
  * Defines an agent configuration.
4644
4753
  *
4645
- * Agents orchestrate conversations between AI models, or between AI and
4646
- * human users. They use prompts to configure each side of the conversation
4647
- * and define stop conditions to control conversation flow.
4754
+ * An agent has exactly two sides; each side is backed by a human, a prompt,
4755
+ * or a handler. Prompts and handlers own turns; humans park execution
4756
+ * awaiting input.
4757
+ *
4758
+ * Definition-time validation runs {@link validateAgentDefinition} and throws
4759
+ * with every error found, so a stale 0.1.0 shape fails with messages naming
4760
+ * exactly what to change.
4648
4761
  *
4649
4762
  * @template N - The agent name as a string literal type
4650
4763
  * @param options - Agent configuration options
@@ -4652,19 +4765,15 @@ interface AgentDefinition<N extends string = string, Prompt extends string = Sta
4652
4765
  *
4653
4766
  * @example
4654
4767
  * ```typescript
4655
- * // agents/agents/support_agent.ts
4656
- * import { defineAgent } from '@standardagents/spec';
4657
- *
4768
+ * // Chat agent: model on side A, person on side B
4658
4769
  * export default defineAgent({
4659
4770
  * name: 'support_agent',
4660
- * title: 'Customer Support Agent',
4661
- * type: 'ai_human',
4662
4771
  * sideA: {
4663
4772
  * label: 'Support',
4664
4773
  * prompt: 'customer_support',
4665
- * stopOnResponse: true,
4666
- * sessionStop: 'close_ticket',
4774
+ * sessionStop: { name: 'close_ticket' },
4667
4775
  * },
4776
+ * sideB: { human: true },
4668
4777
  * exposeAsTool: true,
4669
4778
  * toolDescription: 'Hand off to customer support',
4670
4779
  * });
@@ -4672,22 +4781,28 @@ interface AgentDefinition<N extends string = string, Prompt extends string = Sta
4672
4781
  *
4673
4782
  * @example
4674
4783
  * ```typescript
4675
- * // Dual AI agent (two AIs conversing)
4784
+ * // Relay agent: deterministic code on side A, person on side B
4676
4785
  * export default defineAgent({
4677
- * name: 'debate_agent',
4678
- * title: 'AI Debate',
4679
- * type: 'dual_ai',
4680
- * maxSessionTurns: 10,
4786
+ * name: 'relay_agent',
4681
4787
  * sideA: {
4682
- * label: 'Pro',
4683
- * prompt: 'debate_pro',
4684
- * stopOnResponse: true,
4788
+ * handler: 'relay_pipe',
4789
+ * subagents: [{ agent: 'assistant_agent', maxInstances: 1 }],
4685
4790
  * },
4791
+ * sideB: { human: true },
4792
+ * });
4793
+ * ```
4794
+ *
4795
+ * @example
4796
+ * ```typescript
4797
+ * // Two models conversing
4798
+ * export default defineAgent({
4799
+ * name: 'debate_agent',
4800
+ * maxSessionTurns: 10,
4801
+ * sideA: { label: 'Pro', prompt: 'debate_pro' },
4686
4802
  * sideB: {
4687
4803
  * label: 'Con',
4688
4804
  * prompt: 'debate_con',
4689
- * stopOnResponse: true,
4690
- * sessionStop: 'conclude_debate',
4805
+ * sessionStop: { name: 'conclude_debate' },
4691
4806
  * },
4692
4807
  * });
4693
4808
  * ```
@@ -4853,6 +4968,10 @@ interface ControllerContext {
4853
4968
  tools?: VirtualModuleRegistry<unknown>;
4854
4969
  /** Registry of hook definitions (injected at runtime) */
4855
4970
  hooks?: VirtualModuleRegistry<unknown>;
4971
+ /** Registry of handler definitions (injected at runtime) */
4972
+ handlers?: VirtualModuleRegistry<unknown>;
4973
+ /** Available handler names */
4974
+ handlerNames?: string[];
4856
4975
  /** Additional configuration (injected at runtime) */
4857
4976
  config?: Record<string, unknown>;
4858
4977
  }
@@ -5825,4 +5944,202 @@ interface HookDefinitionResult<K extends HookName> {
5825
5944
  */
5826
5945
  declare function defineHook<K extends HookName>(options: HookDefinitionOptions<K>): HookDefinitionResult<K>;
5827
5946
 
5828
- export { type AgentDefinition, type AgentType, type AttachmentRef, type CodeExecution, type CodeExecutionError, type CodeExecutionLog, type CodeExecutionOptions, type CodeExecutionResult, type CodeExecutionStatus, type ContentPart, type Controller, type ControllerContext, type ControllerReturn, type CreateFetch, type CredentialGrant, type DefineToolOptions, type DefinitionLoader, ENDPOINT_ACCESS_SYMBOL, type Effect, type EffectDefinition, type EmptyUsesState, type EndpointAccess, type EndpointOptions, type EnvValueType, type ErrorOrigin, type ExecutionState, type FetchLike, type FileChunk, type FilePart, type FileRecord, type FileStats, type FileStorage, type FindResult, type GetMessagesOptions, type GlobalNamespaceContext, type GrepResult, type HookContext, type HookDefinition, type HookDefinitionOptions, type HookDefinitionResult, type HookExecutionContext, type HookExecutionSource, type HookMessage, type HookName, type HookSignatures, type HookToolCall, type HookToolResult, type ImageContent, type ImagePart, type ImageUrlPart, type InferProviderOptions, type InjectMessageInput, type InspectedRequest, type LLMMessage, type LLMProviderInterface, type ListUserThreadsOptions, type ListUserValuesOptions, type MarkedThreadEndpoint, type MarkedUserEndpoint, type Message, type MessageUpdates, type MessagesResult, type ModelCapabilities, type ModelDefinition, type ModelProvider, type NamespaceContext, type PackageSignature, type PackedExports, type PackedMeta, type PackedMetadata, type PackedNamespaceContext, type ParentHookRequirement, type ParentHookStage, type PromptContent, type PromptDefinition, type PromptEnvPart, type PromptIncludePart, type PromptInput, type PromptPart, type PromptTextPart, type PromptToolConfig, type ProviderAssistantMessage, type ProviderAttachment, type ProviderConfigSlot, type ProviderConfigSlots, type ProviderConfigValueSource, type ProviderDefinition, ProviderError, type ProviderErrorCode, type ProviderErrorOptions, type ProviderExecutedToolResult, type ProviderFactory, type ProviderFactoryConfig, type ProviderFactoryWithOptions, type ProviderFinishReason, type ProviderGeneratedImage, type ProviderInstance, type ProviderMessage, type ProviderMessageContent, type ProviderMethodOverrides, type ProviderModelInfo, type ProviderModelsPage, type ProviderModelsQuery, type ProviderOverride, type ProviderOverrideContext, type ProviderReasoningDetail, type ProviderRequest, type ProviderResponse, type ProviderStreamChunk, type ProviderSyncOverride, type ProviderSystemMessage, type ProviderTool, type ProviderToolCallPart, type ProviderToolMessage, type ProviderToolResultContent, type ProviderUsage, type ProviderUsagePricing, type ProviderUserMessage, type ProviderWebSearchResult, type QueueMessageInput, type ReadFileStreamOptions, type ReaddirResult, type ReasoningConfig, type ResolveUsesState, type ResponseSummary, type RuntimeByteStream, type RuntimeStreamErrorCode, type RuntimeStreamRequest, type RuntimeStreamResult, type RuntimeStreams, type ScheduledEffect, type SessionToolBinding, type SessionToolConfig, type SetEnvOptions, type SideConfig, type SkillFileInput, type SkillMetadata, type SkillsNamespace, type StopSessionOptions, type StructuredPrompt, type SubagentRegistryEntry, type SubagentToolConfig, type SubpromptConfig, THREAD_ENDPOINT_SYMBOL, THREAD_STREAM_REASONING_PARAM, type TenvRawShape, type TextContent, type TextPart, type ThreadEndpointAuth, type ThreadEndpointHandler, type ThreadEndpointRouteParams, type ThreadHookName, type ThreadMessageChunkEvent, type ThreadMetadata, type ThreadReasoningChunkEvent, type ThreadState, type ThreadUser, type Tool, type ToolArgs, type ToolArgsNode, type ToolArgsRawShape, type ToolAttachment, type ToolConfig, type ToolContent, type ToolDefinition, type ToolResult, type ToolTenvs, type ToolVariables, USER_ENDPOINT_SYMBOL, type UserClientInfo, type UserEndpointHandler, type UserEndpointRouteParams, type UserHandle, type UserIdentity, type UserState, type UserThreadSummary, type UserValueEntry, type UsesAwareExecute, type UsesConstrainedState, type VariableDefinition, type VariableType, type VirtualModuleLoader, type VirtualModuleRegistry, type WriteFileOptions, belongsToPackage, defineAgent, defineController, defineEffect, defineHook, defineModel, definePrompt, defineProvider, defineThreadEndpoint, defineTool, defineUserEndpoint, getEndpointAccess, isPacked, isThreadEndpoint, isUserEndpoint, isVisibleInNamespace, mapReasoningLevel, providerConst, providerEnv, providerValue, validateToolName };
5947
+ /**
5948
+ * Handler definition types for Standard Agents.
5949
+ *
5950
+ * A handler is a function that takes one side's turns in a conversation.
5951
+ * When a side of an agent is backed by a handler, the runtime does not call
5952
+ * a model to answer an inbound message — it calls the handler function once,
5953
+ * with the thread state and the message, and whatever that function does is
5954
+ * the side's turn.
5955
+ *
5956
+ * A handler is NOT a hook (hooks decorate turns owned by something else, and
5957
+ * their failures are non-fatal), NOT a tool (tools are capabilities a
5958
+ * turn-owner chooses to invoke), and NOT an effect (effects run outside the
5959
+ * conversation flow). Its only seat is backing a side of an agent: handlers
5960
+ * MUST NOT be referenced by prompt `tools` arrays, hook lists, or effect
5961
+ * schedules, and implementations MUST reject such references at definition
5962
+ * time.
5963
+ *
5964
+ * https://standardagentspec.com/0.2.0/specification/handlers
5965
+ *
5966
+ * @module
5967
+ */
5968
+
5969
+ /**
5970
+ * Brand marking a value as a handler definition.
5971
+ *
5972
+ * The brand makes `HandlerDefinition` structurally unassignable to tool,
5973
+ * hook, and effect positions, so a handler referenced where those are
5974
+ * expected fails to compile wherever TypeScript can see the reference.
5975
+ * Implementations additionally reject by-name references that types cannot
5976
+ * catch during their definition-registry pass.
5977
+ */
5978
+ declare const HANDLER_SYMBOL: unique symbol;
5979
+ /**
5980
+ * A handler definition — deterministic code that owns one side's turns.
5981
+ *
5982
+ * Execution model (one turn):
5983
+ * 1. An inbound message arrives on the side's perspective.
5984
+ * 2. The runtime invokes `execute` once with the thread's `ThreadState` and
5985
+ * that message.
5986
+ * 3. The invocation returns (or throws). The turn is complete.
5987
+ *
5988
+ * There are no steps, no tool-choice loop, and no model requests for a
5989
+ * handler-backed side. When the agent sets `maxSessionTurns`, a handler turn
5990
+ * counts toward the exchange cap exactly like a prompt turn.
5991
+ *
5992
+ * Delivery is exactly-once per message, in message persistence order, one
5993
+ * invocation at a time per thread; messages that arrive while a turn is in
5994
+ * flight wait in the queue. A failed invocation is never automatically
5995
+ * redelivered — retry is a userland decision.
5996
+ *
5997
+ * Errors are fatal to the turn, and only the turn: the turn is marked failed
5998
+ * as a runtime-origin failure, the inbound message stays persisted, and the
5999
+ * session continues. A handler ends sessions explicitly via
6000
+ * `state.stopSession()`.
6001
+ *
6002
+ * @template State - The thread state type (defaults to {@link ThreadState})
6003
+ */
6004
+ interface HandlerDefinition<State = ThreadState> {
6005
+ /** Optional human-facing summary of what this handler does. */
6006
+ readonly description?: string;
6007
+ /**
6008
+ * The turn implementation.
6009
+ *
6010
+ * Receives the full `ThreadState` — it may forward (`queueMessage` toward a
6011
+ * child), respond (`injectMessage` as its own side's role), spawn children,
6012
+ * stop the session, and read/write thread values: anything tools can do.
6013
+ *
6014
+ * The `message` parameter is the full persisted {@link Message} — id, role,
6015
+ * content, silent flag, metadata, timestamps — not a narrowed view:
6016
+ * handlers are trusted definition code, like tools.
6017
+ *
6018
+ * There is no auto-reply channel: the runtime routes inbound; userland
6019
+ * decides outbound. If the handler wants to speak outward, that is code in
6020
+ * this function.
6021
+ */
6022
+ readonly execute: (state: State, message: Message) => Promise<void>;
6023
+ readonly [HANDLER_SYMBOL]: true;
6024
+ }
6025
+ /**
6026
+ * Options accepted by {@link defineHandler}.
6027
+ *
6028
+ * @template State - The thread state type (defaults to {@link ThreadState})
6029
+ */
6030
+ interface DefineHandlerOptions<State = ThreadState> {
6031
+ /** Optional human-facing summary of what this handler does. */
6032
+ readonly description?: string;
6033
+ /** The turn implementation. See {@link HandlerDefinition.execute}. */
6034
+ readonly execute: (state: State, message: Message) => Promise<void>;
6035
+ }
6036
+ /**
6037
+ * Defines a handler — deterministic code that backs one side of an agent and
6038
+ * takes that side's turns in place of a model.
6039
+ *
6040
+ * Handlers live in their own definition directory (`agents/handlers/` in the
6041
+ * conventional layout). The handler's name is derived from its file name and
6042
+ * referenced from exactly one place: the `handler` property of a side
6043
+ * configuration.
6044
+ *
6045
+ * @template State - The thread state type (defaults to {@link ThreadState})
6046
+ * @param options - Handler configuration options
6047
+ * @returns The branded handler definition for registration
6048
+ *
6049
+ * @example
6050
+ * ```typescript
6051
+ * // agents/handlers/relay_pipe.ts
6052
+ * import { defineHandler } from '@standardagents/spec';
6053
+ *
6054
+ * export default defineHandler({
6055
+ * description: 'Forwards inbound user traffic to the assistant child and relays answers back.',
6056
+ * execute: async (state, message) => {
6057
+ * const assistant = state.children.find(c => c.relationship === 'assistant_agent');
6058
+ * if (!assistant) return;
6059
+ * const child = await state.getChildThread(assistant.reference);
6060
+ * await child?.queueMessage({ role: 'user', content: message.content ?? '' });
6061
+ * },
6062
+ * });
6063
+ * ```
6064
+ */
6065
+ declare function defineHandler<State = ThreadState>(options: DefineHandlerOptions<State>): HandlerDefinition<State>;
6066
+ /**
6067
+ * Type guard: is this value a handler definition created by
6068
+ * {@link defineHandler}?
6069
+ */
6070
+ declare function isHandler(value: unknown): value is HandlerDefinition;
6071
+
6072
+ /**
6073
+ * Pure definition-time validation for Standard Agents.
6074
+ *
6075
+ * `validateAgentDefinition` covers everything the type system cannot express
6076
+ * structurally: the single-owner rule across sides, reserved relationship
6077
+ * names, the both-sides-human gate, parentHooks shape, and legible rejection
6078
+ * of removed 0.1.0 fields. Implementations wire it into definition loading
6079
+ * so a stale 0.1.0 project's boot failure doubles as its migration
6080
+ * checklist.
6081
+ *
6082
+ * Existence checks (does the referenced prompt/handler/agent actually
6083
+ * exist?) and real tool-name collision checks require the definition
6084
+ * registry and are the implementation's responsibility; this module is pure
6085
+ * and dependency-free.
6086
+ *
6087
+ * @module
6088
+ */
6089
+ /**
6090
+ * Every issue code `validateAgentDefinition` can emit.
6091
+ */
6092
+ declare const DEFINITION_ISSUE_CODES: readonly ["agent_name_missing", "agent_name_invalid", "agent_side_missing", "agent_side_invalid", "agent_side_backing_missing", "agent_side_backing_conflict", "agent_side_option_invalid_for_backing", "agent_subagents_on_human_side", "agent_both_sides_human", "agent_legacy_type", "agent_session_binding_legacy_string", "agent_session_binding_invalid", "agent_stop_tool_response_property_missing", "agent_max_steps_invalid", "agent_max_session_turns_invalid", "agent_tool_description_missing", "agent_parent_hooks_invalid", "agent_tenvs_deprecated", "subagent_agent_missing", "subagent_relationship_invalid", "subagent_relationship_duplicate", "subagent_relationship_reserved_name", "subagent_max_instances_invalid", "subagent_legacy_name", "subagent_legacy_resumable", "subagent_legacy_receives_messages"];
6093
+ /**
6094
+ * Union of all definition issue codes.
6095
+ */
6096
+ type DefinitionIssueCode = (typeof DEFINITION_ISSUE_CODES)[number];
6097
+ /**
6098
+ * One problem found in a definition.
6099
+ */
6100
+ interface DefinitionIssue {
6101
+ /** Stable machine-readable code for this issue. */
6102
+ readonly code: DefinitionIssueCode;
6103
+ /** Errors block loading; warnings should be reported once, loudly. */
6104
+ readonly severity: 'error' | 'warning';
6105
+ /** Human-facing message naming exactly what to change. */
6106
+ readonly message: string;
6107
+ /** Dot/bracket path to the offending field (e.g. `sideA.subagents[1].as`). */
6108
+ readonly path: string;
6109
+ }
6110
+ /**
6111
+ * Relationship names reserved for the runtime-injected subagent lifecycle
6112
+ * tools. A relationship `as` name colliding with one of these is a
6113
+ * definition-time error.
6114
+ */
6115
+ declare const RESERVED_RELATIONSHIP_NAMES: readonly ["subagents", "subagent_create", "subagent_message"];
6116
+ /**
6117
+ * Validates one agent definition, purely and without a registry.
6118
+ *
6119
+ * Accepts `unknown` so removed 0.1.0 shapes — which no longer typecheck —
6120
+ * can still be diagnosed with legible, field-naming errors at load time.
6121
+ *
6122
+ * @param def - The candidate agent definition
6123
+ * @returns Every issue found; empty when the definition is valid
6124
+ */
6125
+ declare function validateAgentDefinition(def: unknown): DefinitionIssue[];
6126
+
6127
+ /**
6128
+ * @standardagents/spec
6129
+ *
6130
+ * Standard Agents Specification - TypeScript types and definitions.
6131
+ *
6132
+ * This package provides the canonical type definitions and helper functions
6133
+ * for the Standard Agents specification. It serves as the source of truth
6134
+ * for all agent, model, prompt, tool, hook, and endpoint definitions.
6135
+ *
6136
+ * @packageDocumentation
6137
+ */
6138
+
6139
+ /**
6140
+ * The Standard Agent Specification version these types implement.
6141
+ * Implementations report conformance against exactly one version.
6142
+ */
6143
+ declare const SPEC_VERSION = "0.2.0";
6144
+
6145
+ export { type AgentDefinition, type AgentType, type AttachmentRef, type CodeExecution, type CodeExecutionError, type CodeExecutionLog, type CodeExecutionOptions, type CodeExecutionResult, type CodeExecutionStatus, type ContentPart, type Controller, type ControllerContext, type ControllerReturn, type CreateFetch, type CredentialGrant, DEFINITION_ISSUE_CODES, type DefineHandlerOptions, type DefineToolOptions, type DefinitionIssue, type DefinitionIssueCode, type DefinitionLoader, ENDPOINT_ACCESS_SYMBOL, type Effect, type EffectDefinition, type EmptyUsesState, type EndpointAccess, type EndpointOptions, type EnvValueType, type ErrorOrigin, type ExecutionState, type FetchLike, type FileChunk, type FilePart, type FileRecord, type FileStats, type FileStorage, type FindResult, type GetMessagesOptions, type GlobalNamespaceContext, type GrepResult, HANDLER_SYMBOL, type HandlerDefinition, type HandlerSide, type HookContext, type HookDefinition, type HookDefinitionOptions, type HookDefinitionResult, type HookExecutionContext, type HookExecutionSource, type HookMessage, type HookName, type HookSignatures, type HookToolCall, type HookToolResult, type HumanSide, type ImageContent, type ImagePart, type ImageUrlPart, type InferProviderOptions, type InjectMessageInput, type InspectedRequest, type LLMMessage, type LLMProviderInterface, type ListUserThreadsOptions, type ListUserValuesOptions, type MarkedThreadEndpoint, type MarkedUserEndpoint, type Message, type MessageUpdates, type MessagesResult, type ModelCapabilities, type ModelDefinition, type ModelProvider, type NamespaceContext, type PackageSignature, type PackedExports, type PackedMeta, type PackedMetadata, type PackedNamespaceContext, type ParentHookRequirement, type ParentHookStage, type PromptContent, type PromptDefinition, type PromptEnvPart, type PromptIncludePart, type PromptInput, type PromptPart, type PromptSide, type PromptTextPart, type PromptToolConfig, type ProviderAssistantMessage, type ProviderAttachment, type ProviderConfigSlot, type ProviderConfigSlots, type ProviderConfigValueSource, type ProviderDefinition, ProviderError, type ProviderErrorCode, type ProviderErrorOptions, type ProviderExecutedToolResult, type ProviderFactory, type ProviderFactoryConfig, type ProviderFactoryWithOptions, type ProviderFinishReason, type ProviderGeneratedImage, type ProviderInstance, type ProviderMessage, type ProviderMessageContent, type ProviderMethodOverrides, type ProviderModelInfo, type ProviderModelsPage, type ProviderModelsQuery, type ProviderOverride, type ProviderOverrideContext, type ProviderReasoningDetail, type ProviderRequest, type ProviderResponse, type ProviderStreamChunk, type ProviderSyncOverride, type ProviderSystemMessage, type ProviderTool, type ProviderToolCallPart, type ProviderToolMessage, type ProviderToolResultContent, type ProviderUsage, type ProviderUsagePricing, type ProviderUserMessage, type ProviderWebSearchResult, type QueueMessageInput, RESERVED_RELATIONSHIP_NAMES, type ReadFileStreamOptions, type ReaddirResult, type ReasoningConfig, type ResolveUsesState, type ResponseSummary, type RuntimeByteStream, type RuntimeStreamErrorCode, type RuntimeStreamRequest, type RuntimeStreamResult, type RuntimeStreams, SPEC_VERSION, type ScheduledEffect, type SessionToolBinding, type SessionToolConfig, type SetEnvOptions, type SideConfig, type SkillFileInput, type SkillMetadata, type SkillsNamespace, type StopSessionOptions, type StructuredPrompt, type SubagentRegistryEntry, type SubagentRelationship, type SubagentToolConfig, type SubpromptConfig, THREAD_ENDPOINT_SYMBOL, THREAD_STREAM_REASONING_PARAM, type TenvRawShape, type TextContent, type TextPart, type ThreadEndpointAuth, type ThreadEndpointHandler, type ThreadEndpointRouteParams, type ThreadHookName, type ThreadMessageChunkEvent, type ThreadMetadata, type ThreadReasoningChunkEvent, type ThreadState, type ThreadUser, type Tool, type ToolArgs, type ToolArgsNode, type ToolArgsRawShape, type ToolAttachment, type ToolConfig, type ToolContent, type ToolDefinition, type ToolResult, type ToolTenvs, type ToolVariables, USER_ENDPOINT_SYMBOL, type UserClientInfo, type UserEndpointHandler, type UserEndpointRouteParams, type UserHandle, type UserIdentity, type UserState, type UserThreadSummary, type UserValueEntry, type UsesAwareExecute, type UsesConstrainedState, type VariableDefinition, type VariableType, type VirtualModuleLoader, type VirtualModuleRegistry, type WriteFileOptions, belongsToPackage, defineAgent, defineController, defineEffect, defineHandler, defineHook, defineModel, definePrompt, defineProvider, defineThreadEndpoint, defineTool, defineUserEndpoint, getEndpointAccess, isHandler, isPacked, isThreadEndpoint, isUserEndpoint, isVisibleInNamespace, mapReasoningLevel, providerConst, providerEnv, providerValue, validateAgentDefinition, validateToolName };