Book a call
LESSON16mVERIFIED 2026-08-03 · CLAUDE CODE 2.1.193 · CODEX CLI 0.146.0 · ANTIGRAVITY CLI 1.1.10 · KIMI CODE CLI 0.31.1

Subagents are a config object now, not a trick

Delegation used to be a prompting trick. It is now a definition file you check into the repo — reviewable like any other config, and silently absent when a required field is missing.

The trick everyone tried first

We think that for every feature there's always an earlier workaround, here are three of them:

  • Running another session in a separate terminal and copying files in and the answers out by hand, which is actually isolated but then you become the transport layer

  • Asking LLM to act as multiple people debating about sth (which is like a committee), using a single model in a single context window with a single pool of attention just having a conversation with itself

  • A single big turn asking it to treat its review as sth separate from the implementation it's been working on, again a single model and a single context

We think that the second one is not satisfactory because it doesn't really provide isolation — you ask a single LLM to do a thing. It's like asking multiple people but actually still the same person. You just ask it to impersonate different people, it's not really isolated.

The last one doesn't work well either, for exactly the same reason — there's no isolation there too. In both cases it's the same LLM with the same context and the same set of assumptions which led to the bug in the first place. The first one, the separate terminal, actually does work; it just doesn't scale past about twice because the copy-paste is you.

We believe that in terms of parallelism we've all left the prompt world the day the first harness introduced an agents file (not to mention that we have a place to keep the agent definition there). It's not about concurrent things, it's about files on disk.

What the mechanism actually buys you

What this thing does is:

  • Provides a clean context window per subagent

  • Has its own system prompt and, in most of them, its own tool set

  • Limits the return channel

The first one is really important, all harnesses docs are aligned here. Anthropic: "Each subagent starts with a fresh, isolated context window. It doesn't see your conversation history, the skills you've already invoked, or the files Claude has already read". Cursor: "Subagents start with a clean context". Antigravity: "does not inherit the parent's existing conversation history (context window), starting with a clean slate".

That means that it's really isolated, the way you can't achieve in prompt land. For instance if you were to ask people for a review they might have some ideas about the outcome but are not part of the process so don't have any skin in the game.

The second thing is also great because thanks to the agents file we can provide it with its own system prompt and tool set (if harness supports it). For instance Claude Code, Antigravity and Kimi Code have an allowlist (Cursor only has a readonly flag) and Codex doesn't have per-tool control so they do it using a sandbox instead. We'd say that if your harness supports allowlists you should use them as it's the best way to make sure a subagent can't fix what it's supposed to examine.

And last but not least it limits the return channel. For instance here's a tool reference from Claude Code: "returns a single text result to the parent conversation. The parent doesn't see the subagent's intermediate tool calls or outputs, only that final result". Cursor says the same thing: it "returns a final message with its results". It's a trade-off as 20 instances of grep become a paragraph but that's both a benefit and a cost — whatever the subagent doesn't include in that message never reaches the parent's context.

The last point worth mentioning is that the actual transcript of the entire process is usually being saved on disk but not shown to you.

The part that changed: it is a file

Anyway, we've come to a point where agents are files. Every harness which supports it has a place in your project directory where you can put agent definitions. These are files which can be committed to the repository. Four out of five of them use Markdown with YAML frontmatter (frontmatter as config and body as system prompt), one uses TOML. None of them needs a wizard or any kind of account setup, no UI is required.

And there are multiple signs of actual convergence:

  • Anthropic removed their own agent creator in 2.1.198: "Removed the /agents wizard; ask Claude to create or manage subagents, or edit .claude/agents/ directly" — the vendor's own instruction is now to edit the file

  • Cursor loads directories from other vendors: .claude/agents/ and .codex/agents/ at both project and user level, alongside .cursor/agents/, all of them in the docs

  • Kimi Code loads a generic path that isn't connected with any specific harness: .agents/agents/ and ~/.agents/agents/, documented as the location that "stays under the real OS home so it can be shared across tools"

What's more, since it's a file, if a colleague creates a review agent it will be the same one as yours (they need to commit it). If you change how it works this will show up in PRs so the change itself is also up for review. If you change its behaviour you can always go to the history of this single file and see when it happened, you can even remove it completely — there's no dashboard keeping a stale copy still enabled.

Subagent with no file path is still a workaround.

The description field is the interface

The description is an interface. It's the only part of the definition that's not a piece of documentation but actual configuration — it's what the parent LLM consults in order to decide if it should delegate. For instance here's Antigravity docs: "description used by the planner to determine when to delegate tasks to this agent".

That means that if you give it a description like "Our code review agent" it won't work, you need to describe when it should be called in words that will match a real request (what are the conditions, what types of files, what stage of the work).

For example we've added three agents to .claude/agents/ in a throwaway repo and then asked Claude for a list of subagents:

TEXT
$ claude -p --model haiku "List the subagent types available to you right now, by name only, \
  one per line. Do not launch any of them."
bad-tool
claude
Explore
general-purpose
Plan
schema-reviewer
statusline-setup
  • schema-reviewer — correct definition, works

  • bad-tool — declared a tool that doesn't exist (Telepathy) next to it, still works

  • no-description — valid name, valid tool set, no description. Doesn't show up in the roster but also doesn't say anything, neither stderr nor stdout

The rule of thumb is that if your agent is not being called you most likely won't see an error (or even any output at all). If it doesn't work make sure it's been loaded first and then have a look at its system prompt.

IN YOUR HARNESS

In Claude Code

Subagents are defined in .claude/agents at project level and ~/.claude/agents at user level — Markdown files with YAML frontmatter, body is used as system prompt; name and description fields are mandatory:

MARKDOWN
---
name: schema-reviewer
description: Reviews database migrations for destructive changes. Use proactively when a migration file is added or changed.
tools: Read, Grep, Glob
model: haiku
---

You review database migrations for destructive changes.

It finds subagent definitions recursively so it works with nested subfolders too; what's more it uses the name field to identify a subagent, not the location of the file. What's more, when you run it from a project it finds every .claude/agents folder up the directory tree from cwd to the project root.

So when it comes to priority, these are the levels in descending order:

  • Managed settings

  • --agents CLI flag

  • .claude/agents

  • ~/.claude/agents

  • Plugins' agents directory

If there's a subagent defined at a higher-priority level, that one is used; so a project-level subagent beats a personal one. The thing is that if you have two files with the same name in the same directory tree it's not supported, because as the docs say, only one is loaded and which one depends on which order they are read by the filesystem.

The frontmatter supports multiple fields, here are the most valuable ones:

  • tools / disallowedTools — to limit the toolset; disallowedTools are checked first and then the rest is resolved using tools

  • model (defaults to inherit)

  • permissionMode

  • maxTurns — a hard cap

  • skills — to load the entire skills' bodies

  • isolation: worktree — to use a separate repo copy per run

The parent process passes the subagent to it using the Agent tool, which was called Task before 2.1.63 (and is still accessible via Task(...) alias). You can also address it by typing @ and selecting it or by using --agent <name> to run an entire session as this subagent or --agents '<json>' to set up a one-off for a single session.

It's important to be mindful that the behaviour of subagents might differ depending on what version you use:

  • At 2.1.198 they removed the /agents wizard, so running it will display a message saying to define it in .claude/agents; and also made subagents run in the background by default

  • That's why from now on they use all MCP tools but only a small subset of the built-ins (the docs say that the rest is stripped regardless if inherited or listed in tools, so you can end up with a different toolset for a subagent if you run it in foreground vs background)

  • It also means that listing a tool in tools doesn't mean it's available

  • But for 2.1.193 (which we used to test it), the /agents wizard was still there and the background-by-default change was in progress, so two people running the same definition a fortnight apart can end up with different toolsets

The conclusion is that if you find a subagent doesn't have a particular tool, check if it ran in the background before changing the definition.

In Codex CLI

The only exception from the above is Codex — agent definitions in TOML files rather than Markdown files. They are located at either ~/.codex/agents/ or .codex/agents/ depending on what level you define it on (user or repo) and there's only one agent per file like this:

TOML
name = "pr_explorer"
description = "Read-only codebase explorer for gathering evidence before changes are proposed."
model_reasoning_effort = "medium"
sandbox_mode = "read-only"
developer_instructions = """
Stay in exploration mode.
Trace the real execution path, cite files and symbols, and avoid proposing fixes unless the parent agent asks for them.
"""

There are three mandatory keys:

  • name — used to identify the agent, filename doesn't matter

  • description — for a little bit of context

  • developer_instructions — contains the system prompt instead of the markdown body like in other agents

You can define all the keys that you could define in config.toml file for the config, so anything like:

  • model

  • model_reasoning_effort

  • sandbox_mode

  • mcp_servers

  • skills.config

It's a configuration layer rather than a purpose-built manifest, and OpenAI say so themselves — that "the format may evolve".

There are three built-ins — default, worker and explorer which come preinstalled, if you create your own agent with the same name it will replace the built-in.

Instead of a single call to the agent there are five different tools:

  • spawn_agent

  • send_input

  • resume_agent

  • wait_agent

  • close_agent

This is behind the features.multi_agent flag which is stable and enabled by default, so you can just look at this list and understand what the model is — that a subagent is a long-running thread that you open and can feed input to, wait for and close. /agent and /subagents are not changing anything in this regard they just change which thread is in focus, they're not opening new ones.

To create a subagent you can just ask it in the prompt like:

  • Create two agents for me

  • Can we do it in parallel? etc

There's also an [agents] section in config.toml where you can define things like:

  • enabled — whether to enable the feature at all

  • max_concurrent_threads_per_session — how many threads a single session (an instance of codex) can run simultaneously

  • default_subagent_model

  • default_subagent_reasoning_effort

There are two common pitfalls:

  • The read-only sandbox_mode is just a default, Codex "reapplies the parent turn's live runtime overrides when it spawns a child" (including the possibly interactively-granted approval and sandbox settings) so if you relax your session the subagent will no longer be read-only

  • There's no tool allowlist per agent, it's done by setting sandbox_mode, choosing MCP servers to connect to or disabling skills. There's also no worktree per agent, which is why the docs push you toward read-heavy fan-out and warn to "Be more careful with parallel write-heavy workflows, because agents editing code at once can create conflicts and increase coordination overhead"

In Cursor

Definitions live in the following places in Cursor:

  • per project: .cursor/agents/

  • per user: ~/.cursor/agents/

They're Markdown files with YAML frontmatter.

Compatibility note: Cursor also reads the folders of other vendors (Claude and Codex) at both scopes:

  • per project: .claude/agents/, .codex/agents/

  • per user: ~/.claude/agents/, ~/.codex/agents/

If you have a duplicate name, files from .cursor/ will have the higher priority.

Here's an example of a definition file (for a verification subagent), which contains frontmatter and instructions for the LLM to check a change:

MARKDOWN
---
name: verifier
description: Confirms a change actually works before it is called done. Use after an implementation pass.
readonly: true
---

You verify claims about a change. Run the tests, read the diff, and report what you could not confirm.

All fields in the frontmatter are optional:

  • name — the name of the subagent, used when calling it

  • description — a description of the subagent, visible in the IDE and the CLI

  • model — the model the subagent should use (see below)

  • readonly — if set to true, the subagent runs "with restricted write permissions (no file edits, no state-changing shell commands)"

  • is_background — if set to true, the subagent is ran asynchronously in the background (see more in the history section below). If false — it's run synchronously

That readonly boolean is the whole tool-restriction story here — there's no allowlist per agent. Otherwise "subagents inherit all tools from the parent, including MCP tools from configured servers".

You can use bracketed parameters in the model field too, for example claude-opus-5 with the effort level set to high and the context size to 300k

YAML
model: claude-opus-5[effort=high,context=300k]

You can call the subagent by asking it about sth in natural language, or by calling it using / and its name inside the prompt:

TEXT
> /verifier confirm the auth flow is complete

The feature's history:

  • Implemented in Cursor 2.4 (22nd of January 2026)

  • Asynchronous execution was introduced in 2.5 (17th of February 2026) — before that "all subagents ran synchronously, blocking the parent agent until they complete"

  • That's why is_background is a newer thing

The docs say "You can use subagents in the editor, CLI, and Cloud Agents", but if you run cursor-agent --help on the build we checked (2026.07.23-e383d2b) there's no parameter or subcommand about it. Probably because there's nothing to pass — it's config-driven, so the files are the whole interface. We couldn't confirm that locally: a headless run in an empty directory stops on a "trust this workspace" prompt that only --trust, --yolo or -f clears, and we didn't want to hand an agent a trust flag just to check how the docs behave. So treat CLI pickup as documented but unverified.

In Antigravity CLI

Definitions are Markdown files with YAML frontmatter, so the structure can look like this:

  • .agents/agents/<name>.md

  • .agents/agents/<name>/agent.md

The thing is that the global agents folder is in ~/.gemini/config/agents/ (not in ~/.agents/ as one might think) and there's also a possibility that some of plugins come with their own agents located under plugins/<plugin_name>/agents/. So a definition could look like this:

MARKDOWN
---
name: schema-reviewer
description: Reviews database migrations for destructive changes. Delegate when a migration file changes.
tools:
  - view_file
  - grep_search
model: flash
subagent: true
mainAgent: false
---

You review database migrations for destructive changes.

As said, the most crucial part is the frontmatter with the name and description, then the rest is up to you. But there's a few things that are worth mentioning:

  • The two booleans — subagent and mainAgent — the first one tells Antigravity that the agent can be delegated to (so the primary agent may use invoke_subagent to pass some of the work to it) and the latter is about you being able to choose this agent as a primary one. Other harnesses can express both of those, they just do it elsewhere — through permission rules, or through a flag you pass when you start the session. Antigravity is the one that puts the toggles in the definition file itself, and they're independent, so an agent can be delegate-only.

  • The model is a tier — inherit, flash or pro — defining what kind of model this agent has.

  • commandExecutionPolicy is a setting that defines how Antigravity should run the shell for each agent — off, auto, eager or sandbox.

  • A subagent can have its own git worktree, instead of using the primary agent's directory.

The maximum depth of delegation is 10 levels.

You can set a primary agent by running the headless command with a flag like this:

BASH
agy -p "Review this function for edge cases." --agent schema-reviewer

When it comes to potential problems, we've found two:

  • There's an open issue on Google's side — it's in their known issues list with a fix promised in a later release: "Specifying an unmapped or misspelled tool name in the tools list may cause the subagent process to hang during execution." It won't throw an error, so the only thing you can do about it is not typing tool names but pasting them.

  • We've found this one — we had this setup in our test workspace: both supported layouts and added a definition in each of them, then ran agy agents and it returned no results; it was on version 1.1.9, later we updated to 1.1.10 (the CLI updated itself during the session) and still — nothing. What's more, we've also checked if there are any built-in agents and research, browser and self were missing as well so we assume that on these versions it returns sth else than agents that can be found by the CLI. We weren't able to find a solution.

So even if you run agy agents and it returns no results, don't panic — just try selecting the agent.

In Kimi Code CLI

This tool uses Markdown files with YAML frontmatter for definitions. This is also the tool that has the most number of places from which it will look for agents (directories). If the project has .kimi-code/agents/ or .agents/agents/ in it, it will be used. Or you can point to this directory from your home with the KIMI_CODE_HOME environment variable ($KIMI_CODE_HOME/agents/), by default it's ~/.kimi-code/agents/ and also ~/.agents/agents/. There are two paths under the home dir on purpose — the Kimi-specific one moves with KIMI_CODE_HOME, while the generic ~/.agents/agents/ "stays under the real OS home so it can be shared across tools". If you set the --agent-file option explicitly, then this file will be used. If there's no --agent-file specified, the project-level directory will be used, then these additional dirs, then the user-level dir, then the plugin-level dir, and finally the built-in dir.

But let's see an example of a definition:

MARKDOWN
---
name: schema-reviewer
description: Reviews database migrations for destructive changes.
whenToUse: When a migration file is added or changed.
tools:
  - Read
  - Grep
disallowedTools:
  - Bash
---

You review database migrations for destructive changes.

And then the body of the Markdown file. As you can see, we need to provide only description of an agent, everything else is optional. In terms of tool selection this tool is the most granular, if we were to compare it with the other tools. It uses two arrays: tools and disallowedTools. The first one works as an allow-list, for example you can list all the MCP tools in a glob notation like mcp__github__*, then the agent will be using only these tools. The disallowedTools array is being evaluated after the allow-list and it's used to omit some of the tools that are allowed but you don't want the agent to use. If you set the tools array to an empty one, it won't be using any tool. If you set it to *, it will use every tool. It also supports using multiple models — if you set the KIMI_CODE_EXPERIMENTAL_SECONDARY_MODEL=1 environment variable, you'll be able to choose between primary and secondary models with the model_preference property.

And here are the built-in agents:

  • coder

  • explore

  • plan

The best part of this tool is that every sub-agent gets "a fully independent context window".

It also ignores any properties it doesn't recognise from other tools, for example if you were to use Kimi Code CLI with a Claude Code file, the model property will be just ignored.

One thing that looks like the mechanism and isn't. Just want to clarify one thing — /swarm is not about defining agents. It's a flag that pre-approves using of the AgentSwarm tool which is used for running an array of items across a single prompt template. It can be used to run up to 128 subagents, waits for them to all finish, and then returns one report. This is a useful feature but it's not about defining agents. For ordinary delegation you use the Agent tool; for defining agents you create files as described above.

Verification caveat. Just wanted to say that we haven't actually used any of these things, we were just analysing the docs from Moonshot which are for Kimi Code CLI 0.31.1. The thing is that we have a different version of Python's kimi-cli installed on our machine — 1.48.0 — which is a separate program and its docs say it's retired in favour of Kimi Code CLI, so the folder structure is different.

What the isolation costs

It comes with a few costs:

  • The same clean context which is the main benefit is also why early attempts to use it weren't very effective. It's isolated so it doesn't know about previous conversation, the file you were debating for ten minutes, the agreed limitation, the solution you decided to not go for, and so on — it only knows about the brief

  • That's why the quality of the outcome largely depends on how good the brief is (that's why we've included a recipe about creating the brief in this chapter), if you feel like you'd need to communicate half of what happened during the session to be able to do sth useful with it — it's probably best to keep it inline

  • It also costs tokens, as OpenAI docs clearly say: "Because each subagent does its own model and tool work, subagent workflows consume more tokens than comparable single-agent runs"

  • This means every one of them pays for its own system prompt, reads its own files and rebuilds a context you already had — once per subagent

  • Concurrent things are not free

When not to reach for one

Before you decide to create an agent you should ask yourself these questions:

  1. Could someone with no context do it? If it's a thing that requires conversation history to make sense, the isolation is hurting so you should keep it inline

  2. Can I be happy with a single paragraph as an answer? That's what subagent's return channel looks like, so if the value of your task is in the process (like a refactor you want to watch) you'll get a paragraph

  3. Do I need it just because I want three things done in parallel? If the isolation itself is the goal, like in terms of verification or exploration, it's a valid reason — LLM-s assumptions are the main threat here so it makes sense. But if you just want to have three things done in parallel, it's not a good enough reason — it's a way to pay three times for one answer

THE FILE.claude/agents/schema-reviewer.md
MARKDOWN
---
name: schema-reviewer
description: Reviews database migrations for destructive changes. Use proactively when a migration file is added or changed, or when asked whether a schema change is safe to deploy.
tools: Read, Grep, Glob
model: haiku
---

You review database migrations for destructive changes. You do not edit anything.

Read the migration under review, plus the current schema if you can find it. Then report only:

1. Every column, table or index this drops or renames.
2. Every NOT NULL added to an existing column without a default.
3. Every type change that is not widening.
4. Whether the migration is reversible, and if not, why not.

Return a JSON object and nothing else:

{
  "destructive": true | false,
  "reversible": true | false,
  "findings": [
    { "kind": "drop" | "rename" | "not-null" | "type-change", "object": "<name>", "detail": "<one sentence>" }
  ],
  "unchecked": ["<anything you could not read or confirm>"]
}

If you could not find the current schema, say so in "unchecked" rather than guessing. An empty
"findings" list with a populated "unchecked" list is a valid and useful answer.
j / k to move between lessons