Saltar al contenido principal
Versión: 0.16.0

Subagents

A subagent is a separate agent the main one delegates a task to with the Agent tool: its own prompt, its own tools, often a smaller model, and its own context. The main agent gets back only its final answer. Use them to keep noisy work (web searches, long reads) out of the main context, to use a cheaper model for simple jobs, or to give a narrow capability to a narrow agent.

Declaring subagents​

import type { AgentDefinition } from "@falkenslab/agent-kit";

const SUBAGENTS: Record<string, AgentDefinition> = {
"joke-finder": {
description: "Searches the web for short jokes about pirates, cats or sailors and returns candidates with their source.",
prompt: `Find on the web 2 or 3 short, clean jokes (about pirates, cats or sailors).
Use WebSearch (3 searches at most) and WebFetch only to open a page.
Return only a numbered list with each joke and the URL it comes from.`,
tools: ["WebSearch", "WebFetch"],
model: "haiku",
maxTurns: 8,
},
"joke-critic": {
description: "Scores a joke from 1 to 10 and suggests how to improve it. Uses no tools.",
prompt: "Score the joke you're given from 1 to 10 with one sentence of justification and, below 8, one improvement.",
tools: [],
model: "haiku",
maxTurns: 1,
},
};

const spec: AgentSpec<BaseSessionConfig> = {
buildSystemPrompt: () => `You tell jokes.

Your crew (subagents, launch them with the Agent tool):
- joke-finder: for a new or fresh joke, send it to find candidates on the web.
- joke-critic: before telling a joke the finder brought, pass it the best one; below 6, ask for another batch once.`,
buildMcpServers: () => ({}),
pluginRoots: () => [],
buildSubagents: () => ({ agents: SUBAGENTS, allowedSubagentTypes: Object.keys(SUBAGENTS) }),
};

AgentDefinition is the SDK's type (re-exported by the kit). Its most used fields:

FieldWhat it's for
descriptionWhen the main agent should use it. The main agent reads it in the Agent tool's description.
promptThe subagent's system prompt. It doesn't see the main agent's prompt or conversation, only the task the main agent writes.
toolsThe tools it may use. Each must also be in the session's tools (see below).
model"haiku", "sonnet", "opus", a full model id, or "inherit".
maxTurnsA cap on its turns.
mcpServersMCP servers only this subagent sees.
skillsSkills preloaded into its context.

Tell the main agent about its crew in the system prompt: when to use each one and what to do with the answer. The descriptions alone are often not enough for a consistent workflow.

The kit appends the reply language line to each subagent's prompt too.

What returning subagents changes​

When buildSubagents() returns something (not undefined):

  1. The session gets the Agent tool, to delegate, and Bash.
  2. agents is set to your definitions.
  3. Three PreToolUse hooks are registered, the subagent gates:
    • type gate: Agent may only spawn the types in allowedSubagentTypes;
    • Bash gate: Bash is denied to the main agent;
    • foreground gate: every allowed subagent runs in the foreground (run_in_background: false).

Return undefined for a configuration that doesn't need subagents, so neither tool is granted.

buildSubagents: (config) => (config.withResearch ? { agents: { researcher }, allowedSubagentTypes: ["researcher"] } : undefined),

Tools of a subagent​

A subagent can only use tools that exist in the session. The kit's session has WebFetch, WebSearch, the file tools (with a knowledge or sources folder), Skill (with plugins), Bash (with subagents) and every MCP tool from buildMcpServers().

  • Built-in tools: list them by name: tools: ["WebSearch", "WebFetch"]. A subagent with file tools is bound by the same file scope as the main agent.
  • MCP tools: list them by their full name: the kit's, tools: ["mcp__time__current_time"], or yours, tools: ["mcp__inventory__find_product"], registering the server in buildMcpServers().
  • No tools: tools: [] for a subagent that only thinks.
  • Bash: tools: ["Bash"]. Bash can reach any path and run anything the user can: keep it opt-in and prefer a tool that does exactly what's needed.
const stockClerk: AgentDefinition = {
description: "Looks up products in the inventory and reports their stock.",
prompt: "Find the products with find_product and answer with their name and stock, one per line.",
tools: ["mcp__inventory__find_product"], // a server of yours, from buildMcpServers()
model: "haiku",
maxTurns: 3,
};

const clockBoy: AgentDefinition = {
description: "Tells the date and time and works out how long until something.",
prompt: "Read the time with current_time and work out dates with date_math. Answer in one line.",
tools: ["mcp__time__current_time", "mcp__time__date_math"], // the kit's own
model: "haiku",
maxTurns: 3,
};

Subagents in the chat​

The Ink chat shows a subagent's work under the Agent call that started it: its tool calls (the latest five, dimmed) and its answer's first line when it finishes. The spinner shows what the subagent is doing on a second line (↳ Searching the web for "…"). In interactive mode, the subagent's tool calls go through the approval panel too.

The session log (session.log) and the console only record the main agent's actions.