# Auto-Built AI Tools

Agenvoy supports three ways to add tools beyond the built-in set: auto-generation from a capability gap, script tools, and MCP tools. User-defined API tools were Removed in v1.3.2 (see below). Tools installed by an extension land under `~/.config/agenvoy/tools/.extension/` and register with the `ext_` prefix; since v1.3.2 they come only from scripts.

## Auto-generation (Capability Gap)

When a user request needs live external data (weather, currency, stock, geocoding, translation, etc.) and no existing tool covers it, the agent looks up a keyless public API and calls it directly, and creates a script tool on the spot only when no listed API fits, then runs it to answer. No programming required. Since v1.3.1, with a decision model set, each turn first asks it whether the request needs a capability no available tool name covers — general tools such as `http_request`, `run_command`, `fetch_page` or `search_web` do not count for recurring live data; when it answers missing with confidence 0.7 or higher, the turn context carries a `Tool gap` line telling the agent to call `reasoning_guide(topics=["tool_generate"])` before any other tool. The check is skipped when `reasoning_guide` or `edit_tool` is excluded.

`reasoning_guide(topics=[tool_generate])` carries the build contract (since v1.0.26 the tool takes a `topics` array, so several guides load in one call; it took a single `topic` before); the same text is exposed to external agents through the MCP server as `tool_generate_guide`. The sequence:

| Step | Action |
|---|---|
| 1. Find an API | `public_api_list()` for the category names → pick up to 3 relevant categories → `public_api_list(category)` for each; every listed API is keyless, prefer HTTPS |
| 2. A fitting API exists | `fetch_page` the candidate's docs URL for base URL, endpoint, parameters and response shape → `http_request` (as many calls as the answer needs) → answer. No tool is built; the same flow repeats next time |
| 3. Build a script tool | Only outside the public list: a user-supplied API that needs a key (`get_key()` inside the sandbox keeps it out of the conversation, which `http_request` headers do not), or an answer Python (stdlib, a public data file, a library) can produce. `edit_tool(mode=write)` with `tag=json` + `tag=script` |
| 4. Verify | `test_tool` runs `script.py` in the sandbox; failures are fixed with `edit_tool(mode=patch)` and re-tested (at most 3 retries) |
| 5. Answer | Call the new tool and answer from its output; with no API and no Python route, fall back to `search_web` / `fetch_page` and say where the data came from |

Before v1.3.2 step 1 called the API tool `api_public_api_list(type=category)` and step 2 could pick a declarative API tool (`tag=api`) for a single REST endpoint; both were Removed in v1.3.2.

After creation, the tool persists under `~/.config/agenvoy/tools/script/<name>/` and is available in all future sessions and to every connected MCP agent. Credentials are never hardcoded: the naming convention is `{BRAND}_API_KEY`, captured with `store_secret`. The local key lookup endpoint `GET /v1/key?key=<KEY_NAME>` was removed in v1.0.23: a script tool now reads the key itself (the guide's `get_key()` helper) in the order OS keychain (service `agenvoy`) → `~/.config/agenvoy/.secrets` on Linux → the environment variable of the same name.

Key constraints:
- Since v1.3.2 a keyless public API is answered with `http_request` directly and no tool is saved; the former rule that every data request must be answered by a reusable tool on disk was Removed in v1.3.2. A tool is written only on the script-tool path (step 3). One-off verification or debugging (probing an endpoint, a parameter or a flag) runs inline through `run_command` and saves no tool
- `fetch_page` reads the API documentation; it fetches answer data only in the fallback where no API and no Python route exist, together with `search_web`, naming the source
- Names are `snake_case` verb + noun (`fetch_weather`, `calculate_rsi`) with no prefix — the runtime adds `script_`

## Script tools (`script_*`)

Put a `tool.json` descriptor and a `script.py` (Python) or `script.js` (JavaScript) under `~/.config/agenvoy/tools/script/<name>/`, or the project-local `<cwd>/.config/agenvoy/tools/script/<name>/`. Agenvoy auto-registers it as `script_<name>`. The former `extensions/scripts/<name>/` + `run.py` layout is not scanned; extension-installed scripts under `tools/.extension/script/` register as `ext_<name>`.

```
~/.config/agenvoy/tools/script/my_tool/
├── tool.json     # name, description, parameter schema
└── script.py     # actual script (or script.js)
```

## API tools (`api_*`)

User-defined API tools were Removed in v1.3.2; call the endpoint with `http_request`, or rewrite it as a script tool. JSON descriptors under `~/.config/agenvoy/tools/api/`, the project-local `<cwd>/.config/agenvoy/tools/api/` and `tools/.extension/api/` are no longer loaded: each leftover `.json` file is skipped with an `[Invalid] api tool` warning in the log. The built-in `extensions/apis/` set is gone as well; its `api_public_api_list` became the built-in tool `public_api_list` — with no `category` it returns the category names, with `category` (case-insensitive) each keyless API in it with name, description, HTTPS flag and docs URL. `http_request` runs a `GET` without confirmation; other methods go through the confirm gate.

## MCP tools (`mcp__*`)

Tools exposed by an MCP server are auto-registered as `mcp__<server>__<tool>`. Since v1.3.7 the per-turn `Tools` list groups them by server as `mcp__<server>__{a, b}`, while `find_tools` and `run_tool` still take the full name, and the instructions a server sends are rendered inside the main system prompt rather than as a second system message. MCP tool output is capped at **1 MiB** per call to keep tool results within provider limits.
