|
tools, mcp: a description is a hook, not a manual
With 24 tools in a profile the schemas are the largest fixed block of every
request, and they are paid for whether or not the tool is called. Eleven of
them carried a manual's worth of prose in their `description` — examples,
error tables, "common mistakes", the mechanics of the file areas. Reading
them against the manuals first, the manuals already held all of it, and
richer: this was duplication sitting in the one place the model cannot avoid
reading, not knowledge that had nowhere else to live. So the descriptions
became selection hooks — what the tool is for, when to pick it over its
neighbour, and the one rule that cannot wait — and the detail moved to
tool_manual("<tool>"), which costs nothing until the tool is actually in
play.
filesystem, spawn_agent, schedule_recall, manage_recall, scratchpad, plan,
share_file, content_publish, reflect, todo and peer. Descriptions drop from
18.4 KB to 11.5 KB, those tools' schemas from 25.5 KB to 16.8 KB, and a
profile's whole native toolset from 38.3 KB to 29.6 KB (server_admin,
developer; secretary 33.7 → 25.0, navi_code 32.9 → 25.9, tool_developer
37.9 → 29.2, modeler_3d 33.4 → 24.8). Stated as a budget rather than a byte
count: roughly 4k tokens of the model's window per request, back.
Two things were deliberately not shortened. The filesystem edit ladder
(`edit` → `edit_lines` → `smart_edit`, last resort, costs an LLM call) and
todo's mandatory `validation` on `done` both exist to prevent an extra
round trip; a shorter description there would trade tokens for turns. What
todo lost is the prose around the rule, not the rule. `enabled.json` was
left alone too: weather, gmail and get_current_datetime are opt-in and the
DB shows 12, 16 and 40 calls, so they are opt-in tools that are actually
used.
peer had no manual at all, which is how this surfaced: its description was
the only documentation the tool had. manuals/peer.md is now written from
the tool and its /peer route — the ask/status/list actions, the fact that
the hive is only a phone book and the question travels peer-to-peer, the
one-concurrent-answer semaphore, the two independent recursion guards, and
the six error codes.
The MCP server instructions leave the system prompt the same way. They were
8 KB of always-present prose per request, most of it workflow detail the
model only needs when it is about to use that server. Each server now
contributes one line — a new optional `summary` field in mcp_servers.d/*.json,
defaulting to the first sentence of its `instructions` — and
tool_manual("<server>") returns the full text plus the tool names the server
declares. server_admin's MCP block goes from 8.3 KB to 1.3 KB, secretary's
from 8.1 to 1.2. tool_manual learned to answer for a server (a tool name
still wins over a server of the same name, and dash/underscore spelling is
tolerated), and the index names the servers alongside the tools.
One judgement call worth recording: gnexus-book's and navi-web's
instructions end in an absolute "NEVER bypass these tools with filesystem,
terminal or code_exec" rule. Moving that on demand would have been a
behavioural regression dressed as a token saving, so those two `summary`
fields carry the prohibition verbatim alongside the hook, and it stays
always visible.
docs/tools.md gains a section on the split (a description is paid for every
request, a manual only when the tool is used), which is where the next
person will look before trimming a description back into a manual.
Full suite green (1577 passed, 1 skipped). No frontend change and no new
dependency, so the deploy is a pull and a restart.
|
|---|
|
|
| docs/api.md |
|---|
| docs/mechanics.md |
|---|
| docs/tools.md |
|---|
| manuals/filesystem.md |
|---|
| manuals/peer.md 0 → 100644 |
|---|
| manuals/spawn_agent.md |
|---|
| mcp_servers.d/gnexus-book.json |
|---|
| mcp_servers.d/navi-web.json |
|---|
| mcp_servers.d/navi_ui.json |
|---|
| navi/core/context_builder.py |
|---|
| navi/mcp/config.py |
|---|
| navi/mcp/manager.py |
|---|
| navi/tools/content_publish.py |
|---|
| navi/tools/filesystem.py |
|---|
| navi/tools/manage_recall.py |
|---|
| navi/tools/peer.py |
|---|
| navi/tools/plan.py |
|---|
| navi/tools/reflect.py |
|---|
| navi/tools/schedule_recall.py |
|---|
| navi/tools/scratchpad.py |
|---|
| navi/tools/share_file.py |
|---|
| navi/tools/spawn_agent.py |
|---|
| navi/tools/todo.py |
|---|
| navi/tools/tool_manual.py |
|---|
| tests/unit/core/test_context_builder.py |
|---|
| tests/unit/test_mcp.py |
|---|
| tests/unit/tools/test_manual_drift.py |
|---|
| tests/unit/tools/test_spawn_agent.py |
|---|
| tests/unit/tools/test_tool_manual.py |
|---|