{"version":3,"file":"spawn-sub-agent.mjs","names":[],"sources":["../../../../../../../ai/src/agent/spawn-sub-agent.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { AgentExecuteOptions } from \"../contracts/agent/agent-options.type\";\nimport type { AgentContract } from \"../contracts/agent/agent.contract\";\nimport type { AgentResult } from \"../contracts/result/agent-result.type\";\nimport type { ModelContract } from \"../contracts/model.contract\";\nimport type { SystemPromptContract } from \"../contracts/system-prompt.contract\";\nimport { budget, type BudgetOptions } from \"../middleware/builtins/budget\";\nimport type { AgentToolEntry } from \"../tool/executable-as-tool\";\nimport { agent } from \"./agent\";\n\n/**\n * Spec for `spawnSubAgent` — a one-shot agent invocation. `spawnSubAgent`\n * is a thin convenience wrapper: it builds a fresh `agent()` from this\n * spec, optionally attaches a `budget` middleware, runs the `task` once,\n * and returns the `AgentResult`. There is no separate \"sub-agent\" runtime\n * — a spawn is an ordinary new `agent()` instance, so it starts from an\n * empty conversation with its own tools/prompt exactly the way every\n * `agent()` does.\n *\n * `budget` is the one field that adds something a bare `agent()` config\n * doesn't already give you ergonomically: a first-class per-task\n * cost/token cap. When set, the spawn runs under a `budget` middleware\n * that aborts the moment a cap is crossed, so a delegated subtask cannot\n * overrun its allowance. (Equivalent to passing\n * `middleware: [budget(...)]` to a plain agent — this just promotes it to\n * a spec field.) Distinct from `maxTrips`, which caps round-trips, not spend.\n */\nexport type SpawnSubAgentSpec<TOutput = unknown> = {\n  /** Stable identifier for the spawned agent. */\n  name: string;\n  /** The model the sub-agent runs against. */\n  model: ModelContract;\n  /** The subtask instruction handed to the sub-agent's `execute()`. */\n  task: string;\n  /** Optional system prompt scoping the sub-agent's behavior. */\n  systemPrompt?: SystemPromptContract | string;\n  /** Tools the spawned agent may call inside its own loop (a fresh agent, so not shared with the caller). */\n  tools?: AgentToolEntry<unknown, unknown>[];\n  /** Per-spawn round-trip cap. Forwarded to the agent. Defaults to the agent default. */\n  maxTrips?: number;\n  /**\n   * Per-task budget. When set, the spawn runs under a `budget` middleware\n   * that aborts once a cap (`maxTokens` / `maxCostUSD`) is crossed — a\n   * spend ceiling scoped to this one subtask. Because each spawn is its\n   * own `agent()` instance, that ledger starts fresh per spawn.\n   */\n  budget?: BudgetOptions;\n  /** Structured-output schema validated into `result.data`. */\n  output?: StandardSchemaV1<TOutput>;\n  /** Cancellation handle threaded into the sub-agent run. */\n  signal?: AbortSignal;\n  /**\n   * Session identifier propagated onto the sub-agent's report tree so\n   * the spawned run groups under the parent's session in flat trace\n   * queries.\n   */\n  sessionId?: string;\n};\n\n/**\n * Build a fresh agent, run a single subtask through it once, and return\n * the unified {@link AgentResult}. Equivalent to\n * `agent({ ...spec, middleware: spec.budget && [budget(spec.budget)] }).execute(spec.task, { output, signal, sessionId })`.\n *\n * **Role.** A general-purpose \"build, run, discard\" primitive: a caller\n * (an agent tool, a workflow step, a planner step, a route callback, or\n * hand-rolled orchestration) hands a self-contained subtask to a\n * single-use agent created just for it, instead of reusing a long-lived\n * agent. The spawned `report` slots under the caller's\n * `report.children[]` like any executable, so cost and traces roll up\n * uniformly. It is not tied to any one primitive — it depends only on\n * `agent()` and the optional `budget` middleware.\n *\n * **What it is NOT.** Not a sandbox or a separate runtime. Each spawn is\n * a plain new `agent()` — its fresh conversation, own tools, and own\n * middleware state are ordinary new-instance behavior, not special\n * isolation (every `agent()` already has them). It is also a *narrower*\n * surface than `agent.execute`: one-shot, with no `history`,\n * `placeholders`, per-call event handlers, or `repair`. Reach for it when\n * you want a named single-use delegation with a per-task budget cap;\n * otherwise just construct an `agent()` and call it.\n *\n * Never throws on runtime failure — the agent surfaces failures on\n * `result.error` and a `\"failed\"` / `\"cancelled\"` report status.\n *\n * @example\n * const result = await spawnSubAgent({\n *   name: \"extract-entities\",\n *   model,\n *   task: \"Pull every company name from this article: ...\",\n *   budget: { maxCostUSD: 0.05 },\n *   output: z.object({ companies: z.array(z.string()) }),\n * });\n */\nexport async function spawnSubAgent<TOutput = unknown>(\n  spec: SpawnSubAgentSpec<TOutput>,\n): Promise<AgentResult<TOutput>> {\n  const subAgent = buildSubAgent<TOutput>(spec);\n\n  const options: AgentExecuteOptions<TOutput> = {};\n\n  if (spec.output !== undefined) {\n    options.output = spec.output;\n  }\n\n  if (spec.signal !== undefined) {\n    options.signal = spec.signal;\n  }\n\n  if (spec.sessionId !== undefined) {\n    options.sessionId = spec.sessionId;\n  }\n\n  return subAgent.execute(spec.task, options);\n}\n\n/**\n * Construct the fresh agent for one spawn. Attaches a `budget`\n * middleware only when a cap was requested, so the common no-budget case\n * is just a plain agent.\n */\nfunction buildSubAgent<TOutput>(spec: SpawnSubAgentSpec<TOutput>): AgentContract<TOutput> {\n  const middleware = spec.budget !== undefined ? [budget(spec.budget)] : undefined;\n\n  return agent<TOutput>({\n    name: spec.name,\n    model: spec.model,\n    systemPrompt: spec.systemPrompt,\n    tools: spec.tools,\n    maxTrips: spec.maxTrips,\n    output: spec.output,\n    middleware,\n  });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8FA,eAAsB,cACpB,MAC+B;CAC/B,MAAM,WAAW,cAAuB,IAAI;CAE5C,MAAM,UAAwC,CAAC;CAE/C,IAAI,KAAK,WAAW,QAClB,QAAQ,SAAS,KAAK;CAGxB,IAAI,KAAK,WAAW,QAClB,QAAQ,SAAS,KAAK;CAGxB,IAAI,KAAK,cAAc,QACrB,QAAQ,YAAY,KAAK;CAG3B,OAAO,SAAS,QAAQ,KAAK,MAAM,OAAO;AAC5C;;;;;;AAOA,SAAS,cAAuB,MAA0D;CACxF,MAAM,aAAa,KAAK,WAAW,SAAY,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI;CAEvE,OAAO,MAAe;EACpB,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,cAAc,KAAK;EACnB,OAAO,KAAK;EACZ,UAAU,KAAK;EACf,QAAQ,KAAK;EACb;CACF,CAAC;AACH"}