# Built-in Tools

28 tools always register on every OS, `public_api_list` among them (a built-in since v1.3.2, formerly the API tool `api_public_api_list`); six more appear only when their prerequisite exists (`generate_audio`, `generate_image`, `list_chatbot`, `send_to_chatbot`, `background_command` and `background_subagents`) — 34 built-in tools in total. `run_command_background` was renamed `background_command` (Removed in v1.3.2). `pkg_manage` was Removed in v1.3.2; use `run_command` with argv `['sudo', ...]` or `sandbox: false` instead. `run_websocket` was Removed in v1.3.2, with no replacement tool. `find_note` was removed in v1.0.23 together with operator notes; standing instructions for a session belong in its role (`/role`). Tools that cover several related actions take a `mode` argument rather than splitting into separate names — `edit_file` replaces the former `write_file` / `patch_file` / `remove_file` / `restore_file`, `find_files` replaces `list_files` / `glob_files` / `search_files`, and so on.

Since v1.2.0 a run no longer sends every schema up front. For every provider except `claude-code`, the tools array holds only `find_tools`, `run_tool`, `reasoning_guide`, `write_todo`, `chat_history`, `ask_user` and `write_result` (plus any client tools; `reasoning_guide` joined the fixed set in v1.2.1, `write_todo` in v1.2.3, the last three in v1.3.5); every other tool — built-in, `script_*`, `ext_*`, `mcp__*` — is listed by name in the per-turn context (`Tools (call through run_tool; ...): ...`; since v1.3.7 MCP tools are grouped by server as `mcp__<server>__{a, b}`). The model fetches a schema with `find_tools(names=["NAME", ...])`, which returns it as tool output, then calls the tool as `run_tool(name, args)`; the runtime unpacks that into the inner tool, so confirmation, boundary checks and argument validation still apply by the real name. A direct call to a listed tool is refused with a pointer to `run_tool`, a `run_tool` call made before the schema was fetched returns the schema and asks for a re-call, and a name that is not registered never runs. Keeping the tools array fixed keeps the provider prompt cache hitting. The `AlwaysLoad` flag was removed; use `find_tools` to load a schema (Removed in v1.2.0). The `claude-code` provider (available whenever the local `claude` binary is found) gets every tool except `run_tool` and calls them by name, but receives only the names: a call made before `find_tools` fetched that tool's schema is not run and returns the schema instead.

## Conditional registration

These are excluded from a run while their prerequisite is missing; the LLM does not see them then.

| Tool | Concurrent | Description |
|---|---|---|
| `generate_audio` | | Speaks text with the configured text-to-speech model and writes the file to the output directory (`output_dir`, else `~/Downloads`, else `~/.config/agenvoy/download/`); returns the saved path, not the audio data. Since v1.0.13 the request asks the provider for `opus` and the extension follows the returned MIME type (`.ogg` for opus/ogg, `.mp3`, `.aac`, `.flac`, `.wav` as a fallback) — a `.ogg` / `.oga` / `.opus` result attached to a Telegram chat is delivered as a voice note rather than a document. `voice` picks a provider voice (`alloy` for OpenAI, `Kore` for Gemini), blank uses the provider default. 5 min cap. *(excluded while no text-to-speech model is selected — set it with `/model tts` or `POST /v1/model` `{tts}`)* |
| `generate_image` | | Text to image, written to disk; also handles edits when a reference image is given. Returns the saved path, not the image data. 15 min cap. *(excluded while the image generator is off — set it with `/model` or `POST /v1/model` `{image}`. Since v1.0.13 the setting names an image model as `provider@model`, probed from each credentialed provider with an image-only filter and cached for 15 minutes since v1.0.18; `codex` remains a bare provider name, and a bare provider name saved by an earlier version still resolves)* |
| `list_chatbot` | | List authorized chats for the specified platform (`platform=telegram` or `platform=discord`). *(registered at daemon start only when `telegram_enabled` / `discord_enabled` is set and the bot token is in the keychain, and excluded from a run while neither platform qualifies)* |
| `send_to_chatbot` | | Send a formatted message to an authorized chat by `target_id`. Telegram: HTML + transient client. Discord: markdown + transient client. Platform formatting rules live in the channel system prompts, not in a tool |
| `background_command` | | Starts one command in the background and returns a task id at once; its output is reported when it exits, and also whenever a new output line hits an error keyword while the command keeps running; legs started in the same turn form one group with `objective` and `next` (v1.3.8). Runs file watchers and jobs likely over 5 minutes; details on the Execution Tools page. *(excluded unless the request comes from the TUI — `cli-` origin with no deliver target; since v1.3.2 no longer tied to a decision model)* |
| `background_subagents` | ✓ | Starts a subagent leg in the background and returns a task id at once; its saved report path is reported when it finishes, delivered like `background_command`'s. Details on the Coordination Tools page. *(excluded unless the request comes from the TUI — `cli-` origin with no deliver target)* |

## Dynamic tool groups

Beyond the built-in registry, three prefixes resolve at call time:

| Prefix | Source |
|---|---|
| `script_*` | Generated script tools under the script-tool directory — `script.py` executed in the sandbox |
| `ext_*` | Extension tools, script backed |
| `mcp__*` | Tools exposed by connected MCP servers |

User-defined API tools (`api_*`) were Removed in v1.3.2: their JSON files are no longer loaded and each leftover file is skipped with an `[Invalid] api tool` warning in the log; call an endpoint with `http_request`, or build a script tool.

RAG reaches the agent this way rather than as a built-in: KuraDB is registered as an ordinary MCP server, so its `list_rag` / `search_rag` tools arrive under the `mcp__` prefix and disappear entirely when it is unregistered or disconnected.
