| 1 | # Tool surface |
| 2 | |
| 3 | Why these specific tools, in this groupings, and how each one is meant to be |
| 4 | chosen over the available shell equivalent. Companion to `crates/tui/src/prompts/agent.txt`. |
| 5 | |
| 6 | ## Design stance |
| 7 | |
| 8 | - **Dedicated tools over `exec_shell` whenever the dedicated tool returns |
| 9 | structured output.** Bash escaping is error-prone and platform behavior |
| 10 | varies (GNU vs BSD `grep`, `rg` is not always installed). Structured |
| 11 | output also frees the model from re-parsing free-form text. |
| 12 | - **`exec_shell` for everything else.** Build, test, format, lint, ad-hoc |
| 13 | commands, anything platform-specific. We don't try to wrap the long tail. |
| 14 | - **Drop tools that don't beat their shell equivalent.** Two-tool aliases |
| 15 | for the same backing operation are a model trap — the LLM will alternate |
| 16 | between them and the cache hit rate suffers. |
| 17 | |
| 18 | ## Current surface (v0.7.5) |
| 19 | |
| 20 | ### File operations |
| 21 | |
| 22 | | Tool | Niche | |
| 23 | |---|---| |
| 24 | | `read_file` | Read a UTF-8 file. PDFs auto-extracted via `pdftotext` (poppler) when available; `pages: "1-5"` slices large docs. | |
| 25 | | `list_dir` | Structured, gitignore-aware listing. Preferred over `exec_shell("ls")`. | |
| 26 | | `write_file` | Create or overwrite a file. | |
| 27 | | `edit_file` | Search-and-replace inside a single file. Cheaper than a full rewrite. | |
| 28 | | `apply_patch` | Apply a unified diff. The right tool for multi-hunk edits. | |
| 29 | |
| 30 | ### Search |
| 31 | |
| 32 | | Tool | Niche | |
| 33 | |---|---| |
| 34 | | `grep_files` | Regex search file contents within the workspace; structured matches + context lines. Pure-Rust (`regex` crate), no `rg`/`grep` shell-out. | |
| 35 | | `file_search` | Fuzzy-match filenames (not contents). Use when you know roughly the name. | |
| 36 | | `web_search` | DuckDuckGo (with Bing fallback); ranked snippets + `ref_id` for citation. | |
| 37 | | `fetch_url` | Direct HTTP GET on a known URL. Faster than `web_search` when the link is already known. HTML stripped to text by default. | |
| 38 | |
| 39 | ### Shell |
| 40 | |
| 41 | | Tool | Niche | |
| 42 | |---|---| |
| 43 | | `exec_shell` | Run a shell command. Foreground runs are cancellable, but use them only for bounded commands; timeout kills the process and returns a background-rerun hint. | |
| 44 | | `exec_shell_wait` | Poll a background task for incremental output. Canceling the turn stops waiting without killing the task. | |
| 45 | | `exec_shell_interact` | Send stdin to a running background task and read incremental output. | |
| 46 | | `exec_shell_cancel` | Cancel one running background shell task by id, or all running background shell tasks when explicitly requested. | |
| 47 | | `task_shell_start` | Start a long-running command in the background and return immediately. Preferred over foreground shell for diagnostics, tests, searches, and servers that may run for minutes. | |
| 48 | | `task_shell_wait` | Poll a background command. If `gate` is supplied after completion, record structured gate evidence on the active durable task. | |
| 49 | |
| 50 | When a foreground shell command times out, the process is not continued |
| 51 | silently. The tool result tells the model to rerun long work with |
| 52 | `task_shell_start` or `exec_shell` with `background = true`, then poll with |
| 53 | `task_shell_wait` or `exec_shell_wait`. |
| 54 | |
| 55 | Interactive shell jobs are also visible through `/jobs`. The TUI job center is |
| 56 | fed by the same shell manager as `exec_shell`/`task_shell_start`, and shows the |
| 57 | command, cwd, elapsed time, status, output tail, process-local shell id, and |
| 58 | linked durable task id when available. `/jobs show`, `/jobs poll`, `/jobs wait`, |
| 59 | `/jobs stdin`, and `/jobs cancel` provide inspect, polling, stdin, and cancel |
| 60 | controls for live jobs. Jobs are process-local; after restart, live process |
| 61 | state is not reattached, and any remembered detached entries must be marked |
| 62 | stale rather than presented as live processes. |
| 63 | |
| 64 | ### MCP manager and palette discovery |
| 65 | |
| 66 | MCP server configuration is surfaced in the TUI through `/mcp` and the |
| 67 | `mcp_config_path` row in `/config`. `/mcp` shows the resolved config path, |
| 68 | server enabled/disabled state, transport, command or URL, timeouts, connection |
| 69 | errors, and discovered tools/resources/prompts. It supports narrow manager |
| 70 | actions for init, add, enable, disable, remove, validate, and reload/reconnect. |
| 71 | Config edits are written immediately, but the model-visible MCP tool pool is |
| 72 | restart-required after edits. |
| 73 | |
| 74 | The command palette includes MCP entries grouped by server. Disabled and failed |
| 75 | servers stay visible, and discovered tools/prompts use the runtime names shown |
| 76 | to the model, such as `mcp_<server>_<tool>`. |
| 77 | |
| 78 | ### Git / diagnostics / testing |
| 79 | |
| 80 | | Tool | Niche | |
| 81 | |---|---| |
| 82 | | `git_status` | Inspect repo status without running shell. | |
| 83 | | `git_diff` | Inspect working-tree or staged diffs. | |
| 84 | | `diagnostics` | Workspace, git, sandbox, and toolchain info in one call. | |
| 85 | | `run_tests` | `cargo test` with optional args. | |
| 86 | |
| 87 | ### Task management and durable work |
| 88 | |
| 89 | | Tool | Niche | |
| 90 | |---|---| |
| 91 | | `update_plan` | Structured checklist for complex multi-step work. | |
| 92 | | `task_create` | Create/enqueue a durable background task through `TaskManager`. This is the real executable work object for long-running agent work. | |
| 93 | | `task_list` | List durable tasks with status and linked runtime ids. | |
| 94 | | `task_read` | Read durable task detail: thread/turn linkage, timeline, checklist, gates, artifacts, PR attempts, GitHub events. | |
| 95 | | `task_cancel` | Cancel a queued or running durable task. Approval-required. | |
| 96 | | `checklist_write` | Granular progress under the active thread/task. Checklist state is subordinate to the durable task. | |
| 97 | | `checklist_add` / `checklist_update` / `checklist_list` | Single-item checklist operations. | |
| 98 | | `todo_write` / `todo_add` / `todo_update` / `todo_list` | Compatibility aliases for the checklist tools. Existing sessions keep working, but new prompts should use `checklist_*`. | |
| 99 | | `note` | One-off important fact for later. | |
| 100 | |
| 101 | ### Verification gates and artifacts |
| 102 | |
| 103 | | Tool | Niche | |
| 104 | |---|---| |
| 105 | | `task_gate_run` | Run an approved verification command and attach structured evidence to the active durable task: command, cwd, exit code, duration, classification, summary, and log artifact. | |
| 106 | |
| 107 | Large logs and command outputs should be artifacts with compact summaries in the transcript. `task_gate_run` handles this automatically for active durable tasks. |
| 108 | |
| 109 | ### GitHub context and guarded writes |
| 110 | |
| 111 | | Tool | Niche | |
| 112 | |---|---| |
| 113 | | `github_issue_context` | Read-only issue context via `gh issue view`; large bodies become task artifacts when possible. | |
| 114 | | `github_pr_context` | Read-only PR context via `gh pr view`; optional diff capture via `gh pr diff --patch`; large bodies/diffs become task artifacts when possible. | |
| 115 | | `github_comment` | Approval-required issue/PR comment with structured evidence. | |
| 116 | | `github_close_issue` | Approval-required issue closure. Requires non-empty acceptance criteria and evidence; refuses dirty worktrees unless explicitly allowed. Never close an issue merely because an agent is stopping. | |
| 117 | |
| 118 | ### PR attempts |
| 119 | |
| 120 | | Tool | Niche | |
| 121 | |---|---| |
| 122 | | `pr_attempt_record` | Capture the current git diff as attempt metadata plus a patch artifact on a durable task. | |
| 123 | | `pr_attempt_list` | List attempts recorded on a task. | |
| 124 | | `pr_attempt_read` | Inspect one recorded attempt and its artifact reference. | |
| 125 | | `pr_attempt_preflight` | Run `git apply --check` against an attempt patch. No worktree mutation. | |
| 126 | |
| 127 | ### Automations |
| 128 | |
| 129 | | Tool | Niche | |
| 130 | |---|---| |
| 131 | | `automation_create` | Create a scheduled automation. Approval-required. | |
| 132 | | `automation_list` / `automation_read` | Inspect durable automations and recent runs. | |
| 133 | | `automation_update` | Update prompt, schedule, cwds, or status. Approval-required. | |
| 134 | | `automation_pause` / `automation_resume` / `automation_delete` | Lifecycle controls. Approval-required. | |
| 135 | | `automation_run` | Run an automation now; the run enqueues a normal durable task. Approval-required. | |
| 136 | |
| 137 | ### Sub-agents |
| 138 | |
| 139 | `agent_spawn` plus the supporting tools (`agent_result` / `wait` / `send_input` / |
| 140 | `agent_assign` / `agent_cancel` / `resume_agent` / `agent_list`). |
| 141 | See `agent.txt` for the delegation protocol and |
| 142 | [`SUBAGENTS.md`](SUBAGENTS.md) for the role taxonomy |
| 143 | (`general` / `explore` / `plan` / `review` / `implementer` / |
| 144 | `verifier` / `custom`). |
| 145 | |
| 146 | ### Parallel fan-out: cost-class caps |
| 147 | |
| 148 | Two tools offer parallel fan-out with different concurrency limits that |
| 149 | reflect very different cost classes: |
| 150 | |
| 151 | | Tool | What each child does | Wall-clock | Token cost | Cap | |
| 152 | |---|---|---|---|---| |
| 153 | | `agent_spawn` | Full sub-agent loop (planning, tool calls, multi-turn streaming, can spawn children) | minutes | thousands of tokens | 10 in flight by default (`[subagents].max_concurrent`, hard ceiling 20) | |
| 154 | | `rlm` helper `llm_query_batched` | One-shot non-streaming Chat Completions calls pinned to `deepseek-v4-flash` | seconds | ~hundreds of tokens | 16 per call | |
| 155 | |
| 156 | The caps appear in each tool's description and error messages so the model |
| 157 | (and the user) can choose the right tool for the job. If one sub-agent is |
| 158 | enough but you need parallel lookups, prefer `rlm` with `llm_query_batched`; if each task needs |
| 159 | its own tool-carrying agent loop, use `agent_spawn` (and cancel completed |
| 160 | ones to free slots). |
| 161 | |
| 162 | ## Recently consolidated (v0.5.1) |
| 163 | |
| 164 | Removed from the prompt as duplicates of equivalent tools (the underlying |
| 165 | dispatchers still resolve them, so existing sessions don't break — they just |
| 166 | no longer pollute the model's tool list): |
| 167 | |
| 168 | - `spawn_agent` → use `agent_spawn`. |
| 169 | - `close_agent` → use `agent_cancel`. |
| 170 | - `assign_agent` → use `agent_assign`. |
| 171 | |
| 172 | ## Deprecation schedule (v0.6.2 → v0.8.0) |
| 173 | |
| 174 | The alias tools below still execute successfully but now attach a |
| 175 | `_deprecation` block to every result they return. Models should migrate to |
| 176 | the canonical name before v0.8.0, when the aliases will be removed. |
| 177 | |
| 178 | | Deprecated alias | Canonical name | Warning since | Removal | |
| 179 | |---|---|---|---| |
| 180 | | `spawn_agent` | `agent_spawn` | v0.6.2 | v0.8.0 | |
| 181 | | `delegate_to_agent` | `agent_spawn` | v0.6.2 | v0.8.0 | |
| 182 | | `close_agent` | `agent_cancel` | v0.6.2 | v0.8.0 | |
| 183 | | `send_input` | `agent_send_input` | v0.6.2 | v0.8.0 | |
| 184 | |
| 185 | The `_deprecation` block shape: |
| 186 | |
| 187 | ```json |
| 188 | { |
| 189 | "_deprecation": { |
| 190 | "this_tool": "spawn_agent", |
| 191 | "use_instead": "agent_spawn", |
| 192 | "removed_in": "0.8.0", |
| 193 | "message": "Tool 'spawn_agent' is deprecated; switch to 'agent_spawn' before v0.8.0." |
| 194 | } |
| 195 | } |
| 196 | ``` |
| 197 | |
| 198 | This block is merged into the tool result's `metadata` object alongside any |
| 199 | other metadata keys (e.g. `status`, `timed_out`) so it does not displace |
| 200 | existing metadata. A one-line deprecation warning is also emitted to the |
| 201 | audit log at `tracing::warn` level every time an alias is invoked. |
| 202 | |
| 203 | ## Why we don't ship a single `bash` tool |
| 204 | |
| 205 | Single-`bash` agents (Claude Code's design) are powerful but hand the model |
| 206 | all the foot-guns of shell scripting: quoting, platform divergence, |
| 207 | side-effects from misread cwd, `cd` not persisting between calls, etc. Our |
| 208 | file tools are also significantly cheaper to render in the transcript |
| 209 | (structured JSON-shaped output collapses better than `ls -la` walls of text). |
| 210 | |
| 211 | The model can always fall back to `exec_shell` when something is missing. |
| 212 | The dedicated tools just take the common 80% off the shell escape-hatch. |
| 213 |