Signed-off-by: Casey Gowrie <ctgowrie@gmail.com>
3.9 KiB
issue, status, last_updated
| issue | status | last_updated |
|---|---|---|
| TBD | in-progress | 2026-09-17 |
Subagent tool projection
Summary
Separate executable child-agent registration from model-tool projection. A subagent remains addressable through ctx.agent(name, input) even when its derived model tool is disabled. This lets an authored workflow tool use JEV or another deterministic router to select specialists without exposing those specialists to the conversational model.
Authoring API
An agent controls its own derived tool with tool:
// agent/subagents/researcher/agent.ts
export default defineAgent({
description: "Investigate and explain ambiguous questions.",
model: "anthropic/claude-opus-4.8",
tool: false,
});
On the root agent, tool: false disables the built-in agent self-delegation tool. A same-named tool slot can make the same selection from the parent layer:
// agent/tools/researcher.ts
import { disableTool } from "eve/tools";
export default disableTool();
The second form removes the derived researcher tool but not the researcher child-agent node. An authored tool in the same slot may instead become the model-facing wrapper when the subagent sets tool: false.
Semantics
tooldefaults totruefor root, local, remote, workspace, and dynamically selected agents.- Root
tool: falseremoves the built-inagenttool unless an authoredagent/tools/agent.tsoverrides that slot. - Subagent
tool: falsesuppresses only its model-tool projection. Workflowctx.agent()continues to resolve the child from the complete registry. - A same-named
disableTool()suppresses a declared subagent's projection or the root built-inagenttool. - A same-named authored tool and subagent may coexist only when the subagent's tool projection is disabled. The authored tool owns the model name;
ctx.agent(name, input)owns the child-agent name. - Hidden subagents retain their description, execution, authorization, task lifecycle, tracing, limits, output schema, and continuation behavior.
- A nullish dynamic subagent selection remains unavailable to every caller.
tool: falseis visibility, not availability.
Runtime boundary
Each compiled agent node records its selected tools and source-composition decisions. Runtime graph construction derives disabled tool names from that existing composition, always registers every resolved subagent by name and node id, and prepares a subagent model tool only when the child has not set tool: false and the parent has not disabled the same-named tool slot. Workflow ctx.agent() resolves from the full registry rather than the prepared model-tool list.
Workflow metadata
A workflow tool receives ctx.agents, a replay-stable snapshot of effective declared-subagent descriptions keyed by path-derived name. The snapshot includes model-visible and hidden local, remote, and active dynamic subagents, but not the built-in root-copy agent target, model definitions, credentials, or callbacks. Workflow invocation remains separate:
const target = await chooseTarget(task, {
researcher: ctx.agents.researcher.description,
operator: ctx.agents.operator.description,
});
return ctx.agent(target, { message: task });
The owner snapshots metadata when it starts the workflow run. Older in-flight workflow payloads default to an empty metadata registry. ctx.agent() still validates availability at invocation time, so a dynamic agent that becomes unavailable after the snapshot cannot be invoked through stale metadata.
The provided agentRouter() workflow tool sends its input message and the complete ctx.agents description map to the default evaluation model (typesafe-ai/jev), then invokes the selected path-derived name. It forwards an optional output schema and rejects an empty declared-subagent map before evaluation. Authors use defineWorkflowTool directly when routing requires a subset, custom instructions, or a non-default evaluator.