workflows/options¶
Source: src/workflows/options.ts
What every combinator shares: the same options, under the same names, with the same defaults.
Combinators are functions, not classes. No inheritance, no global registry.
They compose because they all take a Result in and give a Result back.
offerBoth¶
function
export function offerBoth(first: ToolOffer | undefined, second: ToolOffer | undefined): ToolOffer | undefined { /* … */ }
Two offers as one: what first offers an agent, then what second does.
Whichever shape either answers in, the sum is asked for the id, because a list spread beside a function is how a swarm handed its members the board and would have thrown on a caller’s offer written the other way.
SpawnFn¶
type
export type SpawnFn = (agent: Agent, options: SpawnOptions) => Promise<Subagent>;
The spawn function a combinator uses. Injection point for tests.
ToolOffer¶
type
export type ToolOffer = (agent: Agent) => ToolDefinition[] | CustomToolsFor | undefined;
What a workflow offers each of its agents beyond their own tools.
A function of the agent, because the answer differs by agent: a reviewer is offered the verdict tool and the worker beside it is not. What it answers is {@link SpawnOptions.customTools}: a list, or a function of the id to come when a tool needs to know who holds it.
WorkflowOptions¶
type
export type WorkflowOptions = {
/** Absent, each agent's frontmatter decides, then `"task"`. Persistence is asked for, never assumed. */
lifetime?: Lifetime;
/** Propagated down to every `session.prompt()`, and closes open sessions. */
signal?: AbortSignal;
/**
* Deadline **per turn**, not for the whole workflow. No default.
*
* A chain of five steps with `timeoutMs: 60_000` can legitimately run for
* five minutes; what it cannot do is hang forever on one of them. See
* {@link AskOptions.timeoutMs} for why that guard is needed at all.
*/
timeoutMs?: number;
/** A single listener for the whole workflow. Compose with {@link combineReporters}. */
onEvent?: EventListener;
/** Report onto an existing bus instead of a private one - the extension's case. */
bus?: EventBus;
/** Working directory of every subagent. Defaults to the process's own. */
cwd?: string;
/** Where the session files live. Implied by `exportDir`; set it to move them. */
sessionDir?: string;
/**
* Where every subagent of this workflow writes its transcript when it
* closes. See {@link SpawnOptions.exportDir}: it implies a session
* directory, and it is opt-in.
*
* Because the pool closes in a `finally`, an interrupted workflow still
* exports what it managed to do.
*/
exportDir?: string;
/** Give every subagent of this workflow its own herdr split. Opt-in. */
openInHerdr?: boolean;
/**
* Model pattern for **every** subagent of this workflow.
*
* An override, like {@link SpawnOptions.model}, and for the same reason: it
* is what lets one workflow run against different models without touching an
* agent file. It beats every agent's frontmatter - a sweep that let a pinned
* agent through would measure a mixture.
*/
model?: string;
/** Defaults to the real {@link spawn}. */
spawn?: SpawnFn;
/**
* Tools combo defines, chosen per agent.
*
* A function rather than a list, because the answer differs by agent: a
* reviewer is offered the verdict tool and the worker beside it is not, and
* a collector shared between two agents could not say which of them spoke.
*
* Returning a {@link CustomToolsFor} instead of a list defers the choice one
* step further, to the moment the subagent's id exists - see
* {@link SpawnOptions.customTools}. The pool passes either through untouched:
* only a tool that spawns children needs the id, and nothing else should pay
* for it.
*/
customTools?: ToolOffer;
/**
* The subagent every subagent of this workflow hangs under.
*
* Set when a workflow is itself the work of a subagent, which today means
* `delegateTool`. It is what turns a flat list of measurements into a tree.
*/
parentId?: string;
};
Options common to every workflow - same names, same defaults, everywhere.