Hermes Agent Ships Progressive Tool Disclosure - 80 Tools, ~300 Token Overhead

Every tool you attach to an AI agent consumes context. Its name, description, and JSON parameter schema sit in the model's system prompt on every turn. Most turns, the model uses none of them. The schemas are dead weight - context tokens burned for tools that never fire.
Leo Ge runs GBrain with 80+ MCP tools. Before May 29, all 80 schemas loaded into every turn's tools array regardless of what the user asked. That changed with PR #34493, which shipped progressive tool disclosure into Hermes Agent.
The core idea: MCP and non-core plugin tools hide behind three bridge tools until the model needs them. Core Hermes tools - terminal, read_file, write_file, patch, browser_*, web_search, and similar - never defer. Only the long tail of MCP servers and community plugins gets gated.
How It Works
When tool search activates, the model sees three bridge tools instead of the deferred catalog:
tool_search(query, limit?)- BM25 search over deferred tool names and descriptionstool_describe(name)- load one tool's full JSON schema into the conversationtool_call(name, arguments)- invoke the deferred tool, unwrapped to the underlying name
A typical interaction:
Model: tool_search("create a github issue")
→ { matches: [{ name: "mcp_github_create_issue", ... }, ...] }
Model: tool_describe("mcp_github_create_issue")
→ { parameters: { type: "object", properties: { ... } } }
Model: tool_call("mcp_github_create_issue", { title: "...", body: "..." })
→ { ok: true, issue_number: 42 }
When tool_call fires, Hermes unwraps the bridge and dispatches the underlying tool. All existing guardrails - pre/post hooks, approval prompts, tool-result truncation - run against the real tool name, not tool_call. The CLI activity feed and gateway trajectory display the underlying name too.
The activation threshold defaults to 10% of the active model's context window. Below that, the tools array passes through unchanged. This means sessions with a few MCP tools never activate tool search. Sessions with 15+ tools will.
For a 128K context window at 10% threshold (12,800 tokens), 80 GBrain tools averaging ~250 tokens per schema (20,000 tokens total) triggers activation every time. Once active, the bridge tools add approximately 300 tokens of fixed overhead to the tools array. The remaining ~19,700 tokens of deferred schema are pulled in only when needed.
Retrieval uses BM25 over tokenized tool names, descriptions, and parameter names. A literal substring fallback catches the edge case where BM25 returns no positive-score hits - for example, searching "github" against a catalog where every tool name contains the term, which produces zero-IDF scores.
Scoped Enforcement
The original implementation draft had a security gap that the review caught. The bridge dispatch originally read from the global tool registry with no toolset scope. In a restricted session - a subagent, kanban worker, or gateway session limited to specific toolsets - the model could both search and call tools it was never granted.
The merged version added three enforcement layers:
| Check | Before | After |
|---|---|---|
| tool_search (scoped) | total_available: 26 (whole registry) | 20 (scoped to mcp-github) |
| tool_call (out-of-scope) | ok: true (ran anyway) | rejected: "not available in this session" |
| tool_call (in-scope) | ran normally | ran normally |
| _last_resolved_tool_names leak | 20 → 51 (leaked terminal) | 20 → 20 (no leak) |
The fix scopes get_tool_definitions to the session's enabled and disabled toolsets, adds a defense-in-depth gate that rejects any tool_call targeting a name outside the scoped deferrable catalog, and enforces the same scope in tool_executor's unwrap path.
Accuracy Trade-offs
Tool search replaces a fixed context cost with a retrieval task. The model must write a search query that matches the tool it intends to call, which is not always reliable.
Anthropic published numbers from their own progressive disclosure implementation on Opus 4, which the Hermes docs reference: tool call accuracy went from 49% without tool search to 74% with it. That is a 25 percentage point improvement, but also leaves 26% of attempts in retrieval failure - the wrong tool returned, which the model must correct over additional turns.
Smaller models perform worse at the search-to-target mapping. The BM25 fallback to literal substring matching mitigates the worst cases, but model quality remains the binding constraint.
Configuration
Tool search runs in auto mode by default. Three modes exist:
tools:
tool_search:
enabled: auto # auto, on, or off
threshold_pct: 10 # activates when deferrable schemas exceed this % of context
search_default_limit: 5
max_search_limit: 20
Set to on to always activate (as long as at least one deferrable tool exists). Set to off to disable entirely. The bridge schemas cost approximately 300 tokens regardless of catalog size, so forcing on with a small toolset is net-negative - auto is the right default for most deployments.
What Ships Next
An open follow-up PR (#35457) adds an optional embedding reranker to the BM25 retrieval pipeline, replacing the statistical ranking with semantic similarity for better query-to-tool matching on ambiguous searches. The catalog is stateless across turns by design - it rebuilds from the current tool-defs list on every assembly, avoiding the OpenClaw regression where a session-keyed catalog drifted out of sync with the live registry.
Bkash Josi framed the goal in a May 30 post: "500 tools should feel like 5." The architecture is there. The retrieval quality determines how close it gets.
[^1]: Leo Ge. "Huge thanks to the Hermes Agent team for shipping Tool Search." X. May 30, 2026. [^2]: NousResearch. "feat(tools): progressive tool disclosure for MCP and plugin tools (scoped)." GitHub. May 29, 2026. [^3]: NousResearch. "Tool Search documentation." Hermes Agent docs. [^4]: Bkash Josi. "The dirty secret of AI agents: every new tool usually makes the agent a little worse." X. May 30, 2026. [^5]: NousResearch. "feat(tool_search): optional embedding reranker for progressive tool disclosure." GitHub.