What it can do
The tools the model is given, what each is good for, and the rules it has to follow to use them.
Every tool is offered to the model under a PascalCase name — Read, ListDirectory, SpawnAgent — and those are the names in the tables below and in the log. The dispatch additionally answers to a snake_case spelling of most of them (read_file, list_directory, request_permission) and to two names from other tool sets, Bash for Exec and multi_edit for Edit, so a model reaching for a habit rather than for the list still lands on the right tool instead of an error. Nothing advertises those aliases; they exist to absorb a mistake, not to be used.
Consecutive read-only calls — Read, Grep, Glob, ListDirectory, WebFetch, WebSearch, Skill — run together in one pass; anything that writes stays sequential and acts as a barrier for the calls around it, and results always come back in the order they were asked for.
Reading and searching
| Tool | What it does |
|---|---|
Read | Return a file with line numbers. 2000 lines at a time, single lines clipped at 2000 characters, binary files refused, and the answer says how many lines are left |
Grep | Search file contents by regular expression |
Glob | Find files by pattern, e.g. src/**/*.rs |
ListDirectory | List what is in a directory |
SearchSessions | Search what earlier sessions of this working directory said: a query, optionally one session name and a limit, answered with the session, the date, the role and the matching text in a little context |
SearchSessions is the uncurated memory underneath the memory files: the session logs are kept anyway, and they hold what was tried here last week, which command failed and how, and what you said about a file. It is a linear read of the session files whose name carries this working directory, so a session can never see what a session in another repository said, and it needs no permission rule because it reads nothing under the sandbox root. A Role::User line in a session file is not the same thing as a line you typed — it may be a compaction preamble, a heartbeat, a scheduled wake, or a message from another agent — so each of those is marked as what it is. A match is a memory of what was said then rather than proof that it is still true.
Grep answers with the list of matching files by default, which is the cheap answer to "where is this". output_mode switches it to content for the lines themselves — with -n for line numbers and -A, -B, -C for context — or to count for hits per file. It can be narrowed by glob or by type (rust, py, ts, and so on, an unknown name taken as a bare file extension), matched case-insensitively with -i, spread across line breaks with multiline, and cut short with head_limit.
Writing
| Tool | What it does |
|---|---|
Edit | Replace an exact string in a file. The string has to be unique unless replace_all is set |
Write | Replace a file's contents entirely, creating it if it does not exist |
CreateDirectory | Create a directory |
Remove | Remove a file or a directory |
A file has to have been read before Edit or an overwriting Write touches it, and it has to be read again once it changed on disk underneath — the model cannot replace text it has never seen. What counts as changed is a hash of the contents rather than the modification time, because two writes within the same second are ordinary for an agent and a one-second timestamp would miss them.
Running commands
Exec takes typed fields rather than a command line: program, arguments as an array of strings, sudo, and a timeout in milliseconds. There is no shell — no &&, no $(), no redirects, and nothing to smuggle through quoting. A pipeline is written as a stages list instead: a | b becomes two stages, each resolved against the permission engine on its own, and the stdout of one stage is piped into the stdin of the next inside the program, never through a shell. A stage that is denied cancels the whole pipeline and names the stage. Output is truncated when it is long, and a command that runs past its timeout is stopped. The same path is reachable from the chat as /execute, so you and the model share one vocabulary. Under all of it a kernel sandbox limits what an allowed program may write to the working directory, /tmp, the toolchain caches and the granted files; the permissions page says which backend does it and what stays outside its reach.
Reaching outside the project
| Tool | What it does |
|---|---|
WebFetch | Fetch an http or https URL and return its readable text, with HTML stripped to plain text |
WebSearch | Query DuckDuckGo's HTML endpoint and return title, URL, and snippet per hit. No API key needed |
Both reach outside the sandbox by design: the sandbox governs which files the agent may touch, not whether it may read the public web.
Keeping track of itself
| Tool | What it does |
|---|---|
TodoWrite | The model's own step list for a task, replaced whole on every call. The log line shows the progress and the step in flight, so a long task stays followable |
GoalProgress | Record one line on what advanced toward the standing goal, at the moment it happens. With met it proposes that the objective is reached — a claim for you to confirm, never a state change |
Remember | Write one memory file mid-turn: a global/<name>.md or project/<name>.md label and the whole file as content. An empty content deletes it, and an existing label is refused unless replace is passed. A rewrite whose file changed since the model last saw it is refused with the current text, so two sessions sharing a memory directory cannot overwrite each other unnoticed |
Role | List the roles this project offers, each with the first line of what it is for, or take one: that document goes into the session's own system prompt from that turn on, the way --role and /role put it there, and it survives a compaction. A coordinator uses it to move an agent that has drifted from its briefing, and an agent that switches its own role is told to say so in its answer |
CompactHistory | Condense the earlier part of the conversation into working notes, the same way /compact does, when the model notices its own context getting unwieldy. An optional reason is kept beside the notes. It refuses when the history is still too short to cut, and it is a third lever beside the automatic threshold and your own command rather than a replacement for either |
EditSkill | Rewrite an existing skill by name, when its instructions turn out to be wrong. It takes a name rather than a path and refuses one that is not already loaded, so it can never create a skill or write anywhere else; every call is snapshotted first, which is what makes /skill undo the way back |
Task | Read one task of the project queue by the name the open-task list gives it, or mark it done, which deletes the file. The queue lives in the config directory, outside the working directory, so the file tools cannot reach it and this is the only way in; a name carrying a path, a directory or an extension is refused. A task whose header carries needs user is not work for an agent: it is left out of the open-task list, reading it says so rather than handing over the body, and it stands in the inbox as a blocker until the user answers — the answer is written into the file under an ## Answer heading, the needs user line goes, and the task is back in the queue with the answer in it |
AgentInfo | Report program version, the model and provider this turn runs on, the models you configured, the working directory, the session's name and file, token usage so far, the files granted outside the sandbox, and the tool names |
RequestPermission | Ask you to add a permission rule, with the rule, its scope — this project or every directory — and one sentence of reasoning. Every call reaches you; no rule and no --allow-all can answer in your place, and it is the only way a rule reaches every directory |
RequestFileGrant | Ask you for read and write access to exactly one named file outside the working directory — a dotfile, a config file in your home directory. The path is absolute and canonicalized, a directory or a pattern is refused, the grant lasts for this session only and is never written to disk, and a background child is refused outright. See Permissions |
Asking you something
| Tool | What it does |
|---|---|
AskQuestions | Ask one or more questions in a single blocking form, answered before the turn goes on. Every question takes free text; options are optional, multi lets several be picked at once, and preview shows the composed answer for checking before it is sent |
AskInbox | Park one question in an inbox you answer whenever, even after the session ends. The turn continues at once; the answer comes back as a message while the session still runs, or lands as a task in the project queue once it is gone. The result confirms that the question is parked, never the answer. kind is question, blocker or note — a note wants no answer and closes once it has been read — and any other word is refused rather than quietly read as a question; priority orders the listing, higher first; task names a task file in the project queue, and an entry carrying one is answered by writing into that file, so the answer lands in the queue rather than in this conversation |
Wait | End the turn and have the loop hold the session until something happens rather than taking a turn every few minutes to ask whether it has. With agent the wait ends when that session stops running, checked by connecting to its socket at no model cost and given up after six hours; with question it ends when you answer something only you can decide, and nothing times that out. Exactly one of the two. See Working unattended |
Skills
Skill opens an installed skill by name and returns its full text, so the model can follow a skill it recognizes from the list in its system prompt rather than asking you to run the slash command. It takes a name and never a path, searches the same directories the list came from, and an optional file reaches that skill's own references/, scripts/, and assets/ entries, checked for containment. See Skills and packages.
Handing work to another agent
SpawnAgent gives a self-contained subtask to a child agent with the same tools, the same working directory and the same permission rules, but a conversation of its own. The child works until it can answer, and its final message is the entire tool result — the twenty files it read never enter your conversation, which is the point of it. A model argument picks a cheaper model for wide, dull searches; without it the child runs on the same model. A child cannot spawn children, it stops after twelve steps, and Esc interrupts it along with the turn that started it. Its tokens count as the session's, because it is the session's bill.
A spec argument names a role instead of describing it. A file under subagents/ beside the memory directories holds the standing instructions of a role — a reviewer, a counter, a release checker — and SpawnAgent with spec gives the child those instructions and treats the prompt as the task they apply to. Only one line per spec reaches the model's prompt, the name and its first line of purpose, so a shelf full of roles costs almost nothing to keep. /refine can write one from a delegation that worked, and because a spec is a memory scope it is snapshotted and reversible like every other memory file. A spec naming nothing is an error rather than a plain spawn: a child with no instructions answers anyway, which is exactly why that mistake has to be loud.
A fork argument starts the child from this conversation instead of from nothing. It inherits every completed turn above as its own history and the prompt becomes the next message in it, which is what makes “check what I just did” a sentence rather than a retelling. The inheritance is close to free: the request the fork sends opens with the same system block, the same tools and the same messages the parent just sent, so the provider answers it out of the cache it already holds and the fork pays only for its own work. The cut is a turn boundary, the same rule compaction follows, so a fork never begins between a tool call and its result; a conversation with no completed turn yet is an error rather than a child that quietly starts empty. What it inherits is context and never authority — permissions, file grants and the voice at the prompt work exactly as they do for any child, a background fork is refused a prompt like any background child, and its history stays its own: nothing the fork does is written back into the conversation it came from.
A child's tool calls appear in the log indented and dimmed, so you can see what it is doing without it being mistaken for the main conversation.
Running a script
RunScript runs a revolve-script program: a markdown document whose list items are commands and whose block quotes are the prompts those commands send. Its each puts one agent on every element of a list, and the answers stay inside the interpreter — you get back only what a show line reports. A script that reviews forty files and shows the count of failures costs the conversation one number instead of forty reviews. Children run in parallel, so a fan-out over fourteen files takes about as long as the slowest one.
Its glob, read, and save go through the same sandboxed file layer as the tools, and its ask through SpawnAgent, so a script reaches exactly what the agent may reach and nothing more.
Names outlive the call. Everything a script binds stays in the session's environment, and the tool result lists what is being held — the name, its type, its size, never its content — so a later script starts from those names instead of reading the same material again. The environment lives in the process, so a resumed session starts with none.
See The script language for every command, its argument order, and a worked example run against this project's own source.
Talking to another running session
ListAgents reports the detached sessions answering their socket right now: name, model, whether one is mid-turn, and the directory it works in. SendAgentMessage addresses one of those names. Without wait_seconds the call returns as soon as the message is delivered and any answer comes back later as a message of its own, so nothing can hang. With wait_seconds it blocks until the receiving agent finishes the turn the message started and hands back what it wrote, which is what a session with no socket of its own needs. The receiving side is told which of the two it is, so an agent being waited on answers in its final message instead of sending one that arrives after the waiting stopped.
StartAgent is how the model gets a peer rather than a child: it starts another agent as its own process, with the task as its first message. That agent outlives the turn that started it, keeps its own conversation and its own token bill, and answers to its name from then on — unlike SpawnAgent, whose child lives inside the turn. A directory other than this one becomes a sandbox this session cannot reach, so you are asked before anything is started and a refusal starts nothing; a worktree instead puts the new agent in .worktrees/<branch> of this same repository, which needs no approval because it never leaves it, and cleanup says how such a one-shot worker ends itself once its report is sent — delete frees the session, compact keeps it addressable and condenses its history. A role names a subagents/ document the new agent carries in its own system prompt, and an every gives it a cron line, which is how work that recurs gets a home that is not your conversation.
StopAgent ends a running agent by name, session and process. It is for one that is done, went down the wrong road, or is stuck in a turn nobody is reading. It stops a process rather than anything on disk — the history stays and the session can be started again — and it cannot stop the session it is called from. A message sent to an agent that is about to be stopped is wasted: it wakes that agent into a turn the stop then ends.
A message from another agent is text from outside, and it arrives labeled as exactly that: it names the sending session and states that the text is not the user's, grants no permission, confirms no goal, and runs no command. That is enforced rather than merely worded. A peer message travels on its own channel and never passes the point where a leading / would make it a command, so a peer cannot run a chat command, answer a permission prompt, confirm /goal done, cancel a turn, or stop the session.
Tools that appear only sometimes
EditorInfo — which documents are open, which pane is focused, what is selected — exists only when revolve is embedded in a program that answers it. The standalone binary's tool list does not have it. Tools from configured MCP servers join the list under <server>__<tool>, so two servers may each expose a search without colliding.
Every tool, as the model sees it
The table below is rendered from the tool definitions themselves rather than written beside them: the sentence is the one the model is given, and the arguments are the ones the schema declares, with their types and whether they have to be passed. A test regenerates it and fails when the committed file differs, so it cannot describe a tool the program no longer offers. Tools from MCP servers and the extension tools of a project join the list at runtime and stand in no table here.
| Tool | What the model is told it does | Arguments |
|---|---|---|
Read | Read a file's contents, prefixed with line numbers. Reads 2000 lines at a time; use offset/limit for more. Read a file before editing or overwriting it. | file_path string, requiredlimit integeroffset integer |
Grep | Search file contents by regular expression. Returns the matching file paths by default; ask for output_mode 'content' to see the lines themselves. | -A integer-B integer-C integer-i boolean-n booleanglob stringhead_limit integermultiline booleanoutput_mode stringpath stringpattern string, requiredtype string |
Glob | Find files by glob pattern. For instance 'src/**/*.rs'. | pattern string, required |
ListDirectory | List directory contents. | path string, required |
Write | Replace a file's entire contents, creating it if it is not there. An existing file has to be read first. Prefer Edit for changes. | content string, requiredfile_path string, required |
Edit | Replace an exact string in a file that was read before. old_string must be unique unless replace_all is set. | file_path string, requirednew_string string, requiredold_string string, requiredreplace_all boolean |
CreateDirectory | Create a directory. | path string, required |
Remove | Remove a file or directory. | path string, required |
Exec | Run a program through the permission rules, with no shell to interpret a pipe, a redirect or a substitution. Write the whole command line as `command`, the way you would type it: `cargo build --release`, or `a | b` for a pipeline, whose stages are piped inside this program rather than through a shell. Quotes and backslashes are honored, nothing else is: no redirection (`>`, `2>&1`, `<`), no substitution (`$(...)`, backticks), no variables — the tool already returns the output, so none of it is needed. Use `directory` instead of `cd`; with it, `git -C`, `cargo --manifest-path` and their kind are not needed either. `program`/`arguments`, or `stages` for a pipeline, are the structured form of the same thing. Each stage is resolved against the permission rules on its own, and a stage that is denied cancels the whole pipeline. Known commands run without prompting; unknown ones ask the user once. cargo and git subcommands are pre-allowed; others need permission. The command is stopped when it runs past its timeout, and long output is truncated. | arguments arraycommand stringdirectory stringprogram stringstages arraysudo booleantimeout integer |
WebFetch | Fetch a URL and return its readable text, HTML stripped to plain text. | url string, required |
WebSearch | Search the web and return the top results with title, URL and snippet. Use WebFetch to read one of them. | query string, required |
TodoWrite | Replace your todo list for this task. Send the full list every time: mark what is done as completed and keep exactly one item in_progress. Use it for work of several steps so the user can follow along. | todos array, required |
Skill | Read an installed skill in full, by the name the skill list gives it. Load one when a task matches its description; the text is the instructions you are then to follow. Pass 'file' to read one of the skill's own reference, script, or asset files that its text points at. | file stringname string, required |
EditSkill | Rewrite the body of an existing skill, by name. Use it to fix a skill whose instructions are wrong or out of date; the change is recorded so /skill undo can take it back. The name must match a loaded skill — this never creates one, that is what /skill does. The body is the whole document, front matter included. | content string, requiredname string, required |
Task | Read one task of the project queue, complete it, or write a new one. The queue lives in the config directory, outside the working directory, so the file tools cannot reach it and this is the only way in: 'read' returns the task's text, and 'done' deletes the file, which is how a finished task is marked off rather than ticked. It reaches that one directory and nothing else — a name carrying a path, a directory or an extension is refused. | action string, requiredname string, required |
AgentInfo | Report what this session is: model, provider, working directory, session name, token usage, and the tools you have. | none |
RequestPermission | Ask the user to add a permission rule, after one was denied or before doing something no rule covers. A rule names a tool plus a specifier — a path for file tools, a URL or domain for web tools, a program and arguments for Exec. The user answers every call; there is no rule that can approve this tool in advance, and editing a permission file yourself does nothing. Propose the narrowest rule that does the job. This is also how a rule reaches every directory: a permission prompt the user left to you writes nothing by itself, and the rule you propose here is what he reads before it is written. | reason string, requiredrule string, requiredscope string |
RequestFileGrant | Ask the user for read and write access to exactly one named file outside the working directory. For a dotfile or a config file in the user's home directory. The path must be absolute and name a single existing file, never a directory or a pattern. The user answers on the record through the permission prompt; a grant lasts only for this session and is never written to disk, is refused outright for a background child, and a path through .git is refused. Once granted, Read/Edit/Write and the rest of the file tools work on that path exactly as they do inside the sandbox. | path string, requiredreason string, required |
AskQuestions | Ask the user one or more questions in one blocking form, answered before the turn continues. Every question has a prompt and always a free-text answer the user types; options are optional — pass none at all for a free-text-only question. Pass multi true when the user may pick several options at once, and each option may carry extra context the user sees beside its label. Pass preview true on a question whose composed answer the user should be able to check before it is sent. The result lists, per question in order, the chosen option labels and the free text. | questions array, required |
AskInbox | Park one question in a non-blocking inbox the user answers whenever. It outlives this session and the machine's next reboot. Use it when you need a decision but must not stop working: the turn continues at once, and the answer comes back to this session as a message while it still runs, or lands as a task in the project queue once it is gone. The prompt is what the user reads; options are optional — omit them for a free-text-only question. Pass multi true when the user may pick several options, and each option may carry extra context. The result confirms the question is parked, not the answer. kind says what the entry is: question, blocker, or note for something the user only has to read, which wants no answer and closes once he has read it. priority orders the listing, higher first. task names a file in the project queue, and it changes where the answer goes: an entry carrying a task is answered by writing into that file rather than by messaging this session, so the answer lands in the queue and not in this conversation. | kind stringmulti booleanoptions arraypreview booleanpriority integerprompt string, requiredtask string |
EditorInfo | Report what the editor hosting you is showing. Only the host can answer this, and the answer is current at the moment of the call. | none |
SpawnAgent | Hand a self-contained subtask to a child agent that has your tools and your working directory, but its own conversation. It reads what it needs and answers once; you get that answer and nothing else, so the twenty files it read never enter your context. Worth it when finding out costs much more than the finding: which of these forty modules touches the parser, what this dependency does with our config, whether the test suite mentions a case anywhere. Not worth it for anything you can answer in one or two tool calls yourself — a child starts from nothing and has to rediscover what you already know. When several independent questions are open at once, call SpawnAgent once per question in the same message: they run side by side, so a dozen slow searches finish together instead of one after the other. Set fork when the situation is the context — check what I just did, take this thread further on a cheaper model. The child then starts from every completed turn of this conversation and your prompt is the next message in it, which costs almost nothing because the provider has that prefix cached from your own last request. It is still a child: its history is its own from there on, nothing it does enters yours, and it answers once. A fork inherits what you know and not what you may do — every permission is decided the way it always was. Give it the whole task in one prompt, including the part you think is obvious. Without fork it cannot see this conversation, and it can never ask. Name a cheaper model for wide, dull searches; leave the model out to run on the one you are on. A child cannot spawn children. A child is short-lived on purpose: it has twelve tool rounds and one answer, nobody can talk to it while it works, and it is gone once it has answered. Keep its task inside that. Work that needs a conversation, that outlives this turn, or that someone may want to steer belongs to start_agent instead, which makes a real session with a name, a socket and a history. Set background when the answer is not what your next step waits on — a long search you want running while you work elsewhere. You get the child's name at once instead of its answer, and the answer is prepended to a later turn of yours. A background child cannot ask the user anything: a command that would need a confirmation is refused rather than queued, and the child dies unheard if the session ends first. Leave background out whenever you need the answer in this round. | background booleanfork booleanmodel stringprompt string, requiredspec string |
RunScript | Run a script that puts many agents on one job at once. The script is markdown: list items are commands, and a block quote below a command is the prompt that command sends. ``` - files = glob src/**/*.rs - reviews = each files > Read {it} and answer PANIC or CLEAN, then the line number. - bad = keep reviews PANIC - total = count bad - show total ``` `each` asks one agent per element and collects the answers as a list. The answers stay in the interpreter: you get back only what a `show` line reports, so twenty reviews cost you one number if that is what you asked for. That is the whole point — use it when the answers are many and the conclusion is small. Names outlive the call. Every name a script binds is still bound the next time you run one, and the result lists what you are holding — the name, its type and its size, never its content. A later script starts from those names instead of globbing and reading the same material again, so the saving compounds across the conversation rather than ending with the call. Commands, one per line, name = command argument order: `glob <pattern>` — find files, e.g. `files = glob src/**/*.rs`. `list <text> <text> …` — write a list of literal strings down, e.g. `questions = list "What is 2+2?" "Capital of France?"`, which is how two independent questions become one fan-out without a file to glob. `read <path>` — read a file as text, e.g. `content = read README.md`. `lines <text>` — split a text into a list, one element per line, e.g. `rows = lines content`. `chunk <text> <n>` — split a text into pieces of n lines each, e.g. `pieces = chunk content 50`. `ask`, with a block quote below carrying the prompt — put one agent on it and return its answer, e.g. `reply = ask` then `> What is 2+2?`. Takes no arguments itself. `each <list>`, with a block quote below — one agent per element, collected as a list in order; `{it}` in the prompt is the current element, e.g. `answers = each files` then `> Read {it} and answer YES or NO.`. `keep <list> <text>` — keep the elements equal to that text, e.g. `yes = keep answers YES`. `drop <list> <text>` — the complement of `keep`, e.g. `no = drop answers YES`. `first <count> <list>` — the count comes before the list, e.g. `top = first 5 files`; the reverse order is refused. `count <list>` — how many elements, e.g. `total = count yes`. `show <name>` — put that value into the tool result; it is the only thing that leaves the interpreter, e.g. `show total`. `save <path> <name>` — write a file, e.g. `save "notes.md" content`. `model <name>` — switch which model the `ask`/`each` calls after this line run on, e.g. `model "haiku"`. `budget <count>` — cap how many agent calls the rest of the script may make, e.g. `budget 20`; a call past the cap answers with an error instead of running. Placeholders are {name} for a bound value and {it} for the current element. A wrong script is refused before the first agent runs, so a typo costs nothing. `chunk` plus `model` is the pattern worth knowing: a cheap model reads two hundred pieces, an expensive one reads their two hundred answers. | input stringsource string, required |
GoalProgress | Record a step forward on the standing goal shown in your system prompt, at the moment it happens rather than at the end of the turn. Set met=true to propose that the objective is reached: that is a claim for the user to confirm, and the goal keeps standing until they do. | met booleannote string, required |
Wait | End this turn and have the loop hold the session until what you named happens, instead of taking a turn every few minutes to ask whether it has. With `agent`, the wait ends when that session stops running; the loop checks by connecting to its socket, which costs no model call, and a name no running session answers to ends the wait at once, so waiting can fail rather than hang. With `question`, the wait ends when the user answers something only the user can decide — no turn is taken in between and nothing times it out, so use it when the answer is needed before the next step and park anything that can be answered later in the inbox instead. Give exactly one of the two. Waiting is not progress and a wait that ends has met no objective. | agent stringquestion string |
Remember | Write one memory file that every future session in this working directory loads into its system prompt. Use it the moment something is worth carrying past this conversation: a durable preference, a project fact that cost work to establish, a correction the user had to make twice, a convention the code does not show. Not for what this session is doing — the session file already holds that — and not for anything you could read again in a second from the repository. A memory that restates the code goes stale the moment the code changes, and every future session pays for it in context. Keep it short and write the whole file: this replaces the named file rather than appending to it. An empty content deletes the memory. A label that already exists is refused unless you pass replace, so decide whether you are adding a memory or rewriting one. | content string, requiredlabel string, requiredreplace boolean |
CompactHistory | Condense the earlier part of this conversation into working notes and carry on. Call this on noticing your own context is getting unwieldy, or — running as a coordinator watching several started agents — noticing a long conversation is worth condensing before it hits the automatic threshold. This is a third lever alongside the automatic threshold and the user's /compact, not a replacement for either. Refuses when the history is still too short to be worth compacting. | reason string |
ListAgents | List the agent sessions running on this machine right now: name, model, whether one is in the middle of a turn, and the directory it works in. These are the names SendAgentMessage accepts. A session that is not listed cannot be reached — there is no queue for one that is not running. | none |
SendAgentMessage | Send a message to another running agent, addressed by the name ListAgents reports. It arrives there as one message marked as coming from you and starts a turn; if that agent is busy, the message waits until its current turn ends. Use it to ask a peer what it knows about the part of the system it is working on, to tell it that something you both depend on has changed, or to answer a message it sent you. It is a colleague, not a subordinate: it can refuse, and it decides for itself what to do with what you write. Say who you are and what you need in the text itself — it sees nothing of this conversation. Without wait_seconds the tool returns as soon as the message is delivered, which never blocks you; the other agent's answer, if it sends one, arrives later as a message into a turn of yours. The receipt says which of the two happened: `delivered` means that agent was idle and takes the message up now, `queued` that it is in a turn and reads the message when that turn ends. With wait_seconds it blocks until that agent finishes the turn your message started and gives you what it wrote — the simpler shape when you need the answer now, and the wrong one when the other agent may be busy for a long while. To reach a repository you do not work in, address its one coordinator agent rather than a fresh one: check `list_agents` for a session in that directory, then the `repo-coordinators.md` memory for a recorded name, and only when neither has one start a new one and record it. | text string, requiredto string, requiredwait_seconds integer |
StartAgent | Start another agent as its own process, which keeps working after your turn ends and answers to its name from then on. Use it for work that is a job of its own rather than a question: something long, something that belongs to another repository, or something the user will want to talk to directly. It is not SpawnAgent — that one is a child inside your turn whose answer you wait for and whose tokens are yours. This one outlives you, has its own conversation and its own bill, and reaches you back with SendAgentMessage. The task you give it is the whole of what it knows, so write it as if to a stranger. Starting one in another directory hands it a sandbox you do not have, so the user is asked first and may refuse. A `worktree` gives it a fresh git worktree of this same repository instead, at .worktrees/<branch> — no approval needed, since it never leaves the sandbox, and it can read and delete task files the way a lane worker can. Give at most one of `directory` and `worktree`. When the work belongs to a foreign repository the user has named, reach that repository's one coordinator agent rather than starting a fresh one each time: check `list_agents` for a session already working in that directory, then the `repo-coordinators.md` memory for a recorded name, and only start a new one — and record it there — when neither has one. | cleanup stringdirectory stringevery stringmodel stringname stringrole stringtask string, requiredworktree string |
StopAgent | Stop another running agent by name, ending its session and its process. Use it to end an agent you started that is done, went down the wrong road, or is stuck in a turn nobody is reading. It stops a running process, not anything written to disk — a stopped session keeps its history and can be started again. The name it accepts is one ListAgents reports, and you cannot stop your own session with it. A message sent to an agent you are about to stop is wasted: it wakes that agent into a turn, and the stop ends its process without waiting for the turn to finish. Say what you have to say before the work, or not at all. | name string, required |
Role | List the roles this project offers, or put one into this session's own prompt from now on. Called without a name it lists the roles this project offers, each with the first line of what it is for. Called with one, that document goes into your own system prompt from this turn on, in place of the role you carry now, and it holds through a compaction the way the one you were started with does. Switching your own role is a change the user has to be able to see, so say in your answer that you took it and which one. | name string |
SearchSessions | Search what earlier sessions of this working directory said, by text. Reach for it before deriving again what an earlier session already found: what was tried in this directory last week, which command failed and how, what the user said about a file. A match is a memory of what was said then, not proof that it is still true — check the file before acting on it. Only the sessions of this working directory are searched, and a user line that was a compaction preamble, a heartbeat, a scheduled wake or a message from another agent is marked as such rather than passed off as something the user typed. | limit integerquery string, requiredsession string |
Turn budgets
A turn runs under a ceiling on three things: how many tool rounds it may take, how many output tokens it may spend, and how long it may run. The defaults — 300 rounds, a million output tokens, an hour — exist to catch a runaway loop and never fire in ordinary use. A tight budget is worth setting for a scripted run, which is what --budget rounds=8,seconds=120 is for; every key is optional and 0 turns that limit off.
The tokens a child agent spends count against the turn that spawned it. A fan-out of fourteen children can outspend its parent by an order of magnitude, so a ceiling counting only the parent's own tokens would not be a ceiling.
Two things happen as a budget runs low. The model is told in that round's tool results how much is left and that the turn will stop where it stands, so it can summarize rather than find out by being cut off. And when a budget is tight to begin with, the system prompt states all three ceilings and AgentInfo reports what has been spent.
A limit ends the turn after the round that reached it, never between a tool call and its result, and both you and the model are told which limit it was — in those words, because a stop that reads like a completion is a lie about the work. Reaching a limit says nothing about whether the task succeeded. The conversation stays usable: the history is valid, the session resumes, and the next message continues where the turn stopped.