Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Busca de Ferramentas

Quando você tem muitos servidores MCP ou ferramentas de plugin fora do núcleo ligados a uma sessão, os schemas JSON delas podem consumir uma fatia grande da janela de contexto a cada turno — mesmo quando só algumas interessam para o que a pessoa de fato pediu.

A Busca de Ferramentas (Tool Search) é a camada opcional de divulgação progressiva do Hermes para esse problema. Quando ativa, as ferramentas de MCP e de plugin são substituídas, no array de ferramentas visível ao modelo, por três ferramentas-ponte, e o modelo carrega o schema de cada ferramenta específica sob demanda.

As ferramentas embutidas do Hermes nunca são adiadas

As ferramentas que formam o conjunto de capacidades do núcleo do Hermes (terminal, read_file, write_file, patch, search_files, todo, memory, browser_*, web_search, web_extract, clarify, execute_code, delegate_task, session_search e o resto de _HERMES_CORE_TOOLS) são sempre carregadas direto. Só as ferramentas de MCP e as de plugin fora do núcleo podem ser adiadas.

Como funciona​

Quando a Busca de Ferramentas ativa num turno, o modelo vê três ferramentas novas no lugar das adiadas:

tool_search(queries, limit?) — busca no catálogo de ferramentas adiadas (uma ou mais consultas)
tool_describe(names) — carrega os schemas completos de uma ou mais ferramentas
tool_call(name, arguments) — invoca uma ferramenta adiada

Uma interação típica é assim:

Modelo: tool_search(["create a github issue", "send a slack message"])
→ { results: [ { query: "create a github issue",
matches: ["mcp_github_create_issue", ...] },
{ query: "send a slack message",
matches: ["mcp_slack_post_message", ...] } ],
tools: { mcp_github_create_issue: { description: "...",
required: ["title"], ... },
mcp_slack_post_message: { ... } } }
Modelo: tool_describe(["mcp_github_create_issue", "mcp_slack_post_message"])
→ { tools: { mcp_github_create_issue: { parameters: { ... } },
mcp_slack_post_message: { parameters: { ... } } } }
Modelo: tool_call("mcp_github_create_issue", { title: "...", body: "..." })
→ { ok: true, issue_number: 42 }

Cada consulta de uma chamada de tool_search é buscada de forma independente no mesmo catálogo (o limit vale por consulta); os grupos de cada consulta trazem só nomes de ferramenta, enquanto o mapa tools compartilhado guarda uma vez a descrição e os nomes de parâmetro obrigatórios de cada ferramenta encontrada. As consultas passam por radicalização, então "issues" acha create_issue. Todo grupo de consulta que não devolve resultado inclui um resumo available_sources dos servidores conectados, para que uma falha léxica não seja confundida com capacidade inexistente. O tool_describe resolve todos os nomes pedidos numa chamada só; nomes desconhecidos são reportados em not_found sem derrubar o resto do lote.

Quando o modelo invoca o tool_call, o Hermes desembrulha a ponte e despacha a ferramenta subjacente exatamente como se o modelo a tivesse chamado direto. Hooks de pré-chamada, guardrails, pedidos de aprovação e hooks de pós-chamada rodam todos contra o nome real da ferramenta — não contra o tool_call. O feed de atividade da CLI e do gateway também desembrulha, então você vê a ferramenta subjacente, não a ponte.

Quando ela ativa?​

A Busca de Ferramentas usa divulgação em camadas: a presença de qualquer ferramenta adiável (de MCP ou de plugin) ativa a ponte; o que varia com o tamanho do catálogo é quanto dele continua visível, não se os schemas são adiados.

CamadaCondiçãoO que o modelo vê
0Nenhuma ferramenta de MCP ou de pluginToda ferramenta carregada de imediato, sem ponte. Passa direto.
1A listagem do catálogo adiado cabe no orçamentoPonte + um manifesto no estilo das skills com toda ferramenta adiada (nome + descrição curta, caindo para só os nomes quando estoura o orçamento). A degradação é por servidor: quando um servidor gigante (Cloudflare) está ligado ao lado de pequenos (Linear), os pequenos mantêm a listagem de cada ferramenta e só o gigante encolhe para uma linha de resumo.
2A listagem por ferramenta estoura o orçamento mesmo só com os nomes de todo servidor (por exemplo, a superfície plana de API da Cloudflare sozinha: cerca de 3.300 ferramentas cujos nomes dão uns 32 mil tokens)Ponte pelada + um resumo de uma linha por servidor (nome do servidor + quantidade de ferramentas), para que o modelo saiba quais domínios estão ao alcance; as ferramentas individuais só se descobrem pelo tool_search.

O orçamento da listagem é min(threshold_pct% do contexto, listing_max_tokens). A decisão é reavaliada toda vez que o array de ferramentas é montado, então acrescentar ou remover servidores MCP no meio da sessão move a sessão de camada na montagem seguinte.

Configuração​

tools:
tool_search:
enabled: auto # auto (padrão), on ou off
threshold_pct: 5 # orçamento da listagem como porcentagem do contexto
search_default_limit: 5
max_search_limit: 25
listing: auto # embute um manifesto agrupado de nome+descrição do catálogo
listing_max_tokens: 4000
ChavePadrãoSignificado
enabledautoauto/on ativam sempre que existe pelo menos uma ferramenta adiável; off desliga por completo (tudo fica carregado de imediato). Hoje o auto é um apelido de on — ele está reservado para um modo futuro que embute os schemas quando eles cabem no contexto e só adia quando não cabem. Fixe on ou off se quiser o comportamento de hoje garantido entre atualizações.
threshold_pct5Orçamento da listagem como porcentagem do tamanho de contexto do modelo ativo. Faixa de 0 a 100.
search_default_limit5Acertos devolvidos por consulta quando o modelo chama tool_search sem limit.
max_search_limit25Teto rígido que o modelo pode pedir pelo limit (por consulta). Faixa de 1 a 50.
listingautoEmbute na descrição da ponte tool_search um manifesto no estilo das skills com toda ferramenta adiada (nome + primeira frase da descrição, com no máximo 60 caracteres, agrupado por servidor MCP). O auto inclui quando cabe no orçamento (caindo para só os nomes e depois para o resumo por servidor da camada 2); on/off forçam um dos dois.
listing_max_tokens4000Teto absoluto da listagem embutida, seja qual for o tamanho do contexto. Faixa de 200 a 60000. Catálogos grandes degradam para só os nomes ou para resumos por servidor, mantendo os schemas completos disponíveis pela busca.

Os tetos de array por chamada são limites internos de segurança, não configuração. Chamadas acima do teto devolvem um erro para o modelo tentar de novo com um lote menor.

Por que a listagem existe​

Sem ela, as capacidades adiadas ficam invisíveis — a avaliação ao vivo mostrou modelos substituindo por ferramentas de núcleo visíveis (rodando gh no terminal em vez de buscar a ferramenta adiada do GitHub) ou declarando uma capacidade inexistente em vez de chamar o tool_search. A listagem aplica às ferramentas o padrão das skills: toda capacidade continua descobrível por nome o tempo todo, enquanto os schemas completos de parâmetro seguem adiados. Se o modelo vê o nome exato da ferramenta na listagem, ele pode pular o tool_search e ir direto ao tool_describe, economizando uma ida e volta.

Também dá para usar o formato booleano antigo:

tools:
tool_search: true # equivalente a {enabled: auto}

Quando NÃO usar​

A Busca de Ferramentas troca um custo fixo de tokens por turno (os três schemas das ferramentas-ponte mais a listagem do catálogo) e pelo menos uma ida e volta extra em ferramentas frias (descrever → chamar) pela economia nos schemas adiados. Na camada 1 a listagem mantém toda capacidade visível, então a ida e volta de descoberta em geral some — o modelo vai direto ao tool_describe. A avaliação ao vivo mostrou o modo de listagem empatando com o carregamento imediato em sucesso de tarefa, custando menos que a ponte pelada.

Se você quer o comportamento antigo, sempre imediato, para um conjunto pequeno de ferramentas, defina enabled: off.

Trocas que não desaparecem​

Elas vêm da invariante de integridade do cache de prompt — são inerentes a qualquer projeto de divulgação progressiva, não são específicas desta implementação:

  • Uma ida e volta extra em ferramentas frias. Na primeira vez que o modelo precisa de uma ferramenta adiada, ele gasta uma ou duas chamadas de modelo a mais para achar e carregar o schema. A economia de tokens do lado estático é real, mas parte dela é devolvida em tempo de execução.
  • Sem ganho de cache nos schemas adiados. Um resultado de tool_describe carregado entra no histórico da conversa (então ele é sim cacheado nos turnos seguintes), mas nunca se beneficia do prefixo de cache do prompt de sistema.
  • Dependência da qualidade do modelo. A Busca de Ferramentas pressupõe que o modelo consegue escrever uma consulta razoável para a ferramenta que quer. Modelos menores fazem isso pior; os números publicados pela Anthropic (de 49% para 74% no Opus 4 com e sem busca de ferramentas) mostram o ganho, mas também que uns 26 pontos de acurácia ainda são falha de recuperação.
  • Editar o conjunto de ferramentas invalida o cache. Acrescentar ou remover uma ferramenta no meio da sessão muda as descrições das ferramentas-ponte (que incluem a contagem de ferramentas adiadas) e o catálogo, então o cache de prompt é invalidado. É a mesma troca de qualquer edição de conjunto de ferramentas.

Detalhes de implementação​

  • Recuperação: BM25 sobre o nome tokenizado da ferramenta, o nome da fonte (o servidor MCP ou o conjunto de ferramentas de plugin a que ela pertence, para que buscar "linear" ache as ferramentas daquele servidor mesmo quando o nome de uma delas não carrega o serviço), a descrição e os nomes de parâmetro, com radicalização Snowball (em inglês) aplicada ao índice e à consulta, para que variantes morfológicas casem ("issues" acha create_issue). Recai para um casamento literal de substring no nome da ferramenta quando nenhum token da consulta casa com documento nenhum (por exemplo, buscar "hub" onde o token é github).
  • A execução em paralelo desembrulha a ponte. O planejador de lotes decide a simultaneidade pela ferramenta subjacente de um tool_call, e não pelo nome literal da ponte — então um servidor MCP que aderiu com supports_parallel_tool_calls: true mantém a simultaneidade quando as ferramentas dele são chamadas pela ponte, e as consultas de tool_search / tool_describe são agrupadas em paralelo como qualquer ferramenta somente leitura.
  • O catálogo não guarda estado entre turnos. Ele é remontado a partir da lista atual de definições de ferramenta a cada montagem — sem Map indexado por sessão. Isso evita a classe de bug em que um catálogo guardado sai de sincronia com o registro vivo de ferramentas.
  • O catálogo é limitado aos conjuntos de ferramentas da sessão. O tool_search, o tool_describe e o tool_call só enxergam e invocam ferramentas que a sessão de fato recebeu. Um subagente, um worker de kanban ou uma sessão de gateway restrita a um subconjunto de conjuntos de ferramentas não consegue usar a ponte para descobrir nem chamar uma ferramenta fora daquele subconjunto — o catálogo adiado é a fatia adiável dos conjuntos ligados e desligados da própria sessão, não o registro do processo inteiro.
  • Sem sandbox de JS. O Hermes usa o modo mais simples, de "ferramentas estruturadas" (buscar, descrever e chamar como funções comuns). O "modo de código" com sandbox de JS que algumas outras implementações oferecem é uma superfície enorme; nós pulamos.

Veja também​

  • tools/tool_search.py — a implementação
  • tests/tools/test_tool_search.py — a bateria de regressão
  • O PDF openclaw-tool-search-report, no PR original da implementação, com a pesquisa que moldou o projeto