/** * Letting a subagent have subagents of its own. * * An agent whose `tools:` names `subagent` is handed this, and can then split * its task across children of its own. Nothing else changes: the tool is built * here and passed through `SpawnOptions.customTools`, so `spawn` never learns * what a roster is. * * **This is one of the three exceptions to "a subagent inherits nothing"**, * beside `situate()` and `skills:`. Granting it is not inheritance either: the * tool comes from combo rather than from the user's machine, the roster is the * one the caller chose, and an agent that does not name it in its own file * cannot have it. What an agent can do stays readable in its definition, which * is the part of the invariant that was ever load-bearing. * * The depth guard ships with the feature rather than after it. Delegation that * can go on forever is a bill discovered afterwards, and the bound is carried in * a closure rather than read from anywhere: an ambient variable is how the model * hole in invariant 5 existed, and nothing here reads the environment. */ import type { Agent } from "./agent.ts"; import { type ToolDefinition } from "./session.ts"; import type { WorkflowOptions } from "./workflows/options.ts"; /** The name an agent writes in its `tools:` to be allowed children of its own. */ export declare const SUBAGENT_TOOL = "subagent"; /** * How deep delegation goes by default: the session, a child, a grandchild. * * Two is where a split stops paying. A grandchild has been handed one slice of * one slice, and rarely knows enough about the whole to divide it usefully - it * spends a turn deciding that instead of reading. */ export declare const MAX_DEPTH = 2; /** Who a child may delegate to, how deep, and what its own children inherit. */ export type DelegateOptions = Omit & { /** Branches at once, when the holder's definition does not say. */ concurrency?: number; /** The roster a child may name. A name not on it is refused, never guessed. */ agents: readonly Agent[]; /** * The agent being handed this tool. * * Its `concurrency:` decides how many children it runs at once. Passing it is * what lets that number live in the agent's own file rather than in every * call site, and a child that delegates in turn is read the same way. */ holder?: Agent; /** How many levels of delegation are allowed. Defaults to {@link MAX_DEPTH}. */ maxDepth?: number; /** The depth of whoever is being handed this tool. The first call is 1. */ depth?: number; /** * The id of the subagent holding this tool, so its children can name it. * * Absent at the top level only when nobody could say: the holder's id is * minted by `spawn`, so a caller building this tool by hand takes it from * `SpawnOptions.customTools` in its function form. Without it the children * are still spawned and still measured - they simply read as roots, which * is a measurement that has lost a fact rather than a run that failed. */ parentId?: string; }; /** Whether an agent's definition asks to be allowed children of its own. */ export declare function declaresDelegate(tools: readonly string[] | undefined): boolean; /** * Builds the `subagent` tool for an agent at a given depth. * * Pass it through `SpawnOptions.customTools`. An agent whose `tools:` does not * name `subagent` will not be given it by pi, so offering it costs nothing. * * At the bound the tool is still handed over and **refuses when called**, saying * how deep it is and how deep it may go. Withholding it instead would leave a * model calling a tool that does not exist, getting "unknown tool" back, and * trying again - which is the runaway turn `timeoutMs` exists to survive rather * than a thing to cause on purpose. */ export declare function delegateTool(options: DelegateOptions): ToolDefinition; //# sourceMappingURL=delegate.d.ts.map