Objetivo da Aula
Explicar por que expor todas as ferramentas disponíveis em toda chamada é uma escolha de arquitetura ruim, não um padrão neutro
Projetar um resolvedor condicional que decide, a cada turno, qual subconjunto de tools/skills é relevante
Diferenciar resolução por regra estática (declarativa) de resolução por relevância dinâmica (semântica)
Quantificar o custo de "poluição de ferramentas" na qualidade de decisão do modelo e no orçamento de tokens
Conectar o motor de resolução condicional com a montagem de contexto do capítulo 1.2 e o RBAC do capítulo 1.3
Por que isso importa
É tentador, ao construir um agente, simplesmente registrar todas as ferramentas disponíveis e deixar o modelo "escolher" a certa a cada turno. Funciona bem com cinco ferramentas. Começa a falhar visivelmente com trinta. Com cem ferramentas registradas, mesmo um modelo forte comete mais erros de seleção — chama a ferramenta errada, ignora a certa porque está "enterrada" entre opções irrelevantes, ou simplesmente consome uma fatia enorme da janela de contexto só descrevendo capacidades que nunca serão usadas naquele turno.
Isso não é uma limitação passageira de modelos atuais — é uma consequência estrutural de como a atenção de um LLM funciona sobre um conjunto de opções: mais opções irrelevantes no contexto significa mais ruído competindo com o sinal relevante. Um harness maduro não resolve isso pedindo para o modelo "ignorar o que não for relevante" — resolve não oferecendo, em primeiro lugar, o que não é relevante para aquele turno específico. Essa é a função do motor de resolução condicional: decidir, antes da chamada ao modelo, qual subconjunto de ferramentas e skills faz sentido no contexto operacional atual.
Impacto direto no seu trabalho: à medida que um sistema de IA corporativo cresce — mais integrações, mais skills, mais ferramentas internas — a pergunta de arquiteto muda de "que ferramentas o agente tem" para "como o agente descobre, a cada momento, apenas as ferramentas que importam agora". Sistemas que não resolvem essa pergunta de forma explícita acabam com agentes lentos, caros e com taxa de erro de seleção de ferramenta crescente conforme o catálogo de capacidades aumenta.
Conceitos Fundamentais
O custo real de expor tudo, sempre
Cada ferramenta registrada no contexto de uma chamada tem um custo em três dimensões, não apenas uma:
Custo 1: Tokens
Cada definição de ferramenta (nome, descrição, schema de
parâmetros) consome tokens da janela de contexto — mesmo
que a ferramenta nunca seja chamada naquele turno.
50 ferramentas × ~150 tokens de definição cada
= 7.500 tokens só de "catálogo", antes de qualquer
trabalho real começar.
Custo 2: Qualidade de decisão
Quanto mais opções semanticamente próximas o modelo
precisa distinguir, maior a chance de confundir uma com
outra (ex: "buscar_cliente" vs "buscar_cliente_v2" vs
"consultar_cadastro" — três ferramentas plausíveis para
o mesmo pedido, adicionadas em momentos diferentes do
projeto).
Custo 3: Superfície de risco
Toda ferramenta exposta é, potencialmente, uma ferramenta
que pode ser chamada — inclusive por manipulação via
prompt injection. Expor uma ferramenta de alto raio de
impacto (capítulo 1.3) em contextos onde ela não é
necessária aumenta a superfície de ataque sem benefício
operacional correspondente.Esses três custos compõem o argumento central deste capítulo: a lista de ferramentas disponíveis não deveria ser estática — deveria ser resolvida dinamicamente, a cada turno, como função do contexto operacional. Essa resolução é o "motor de resolução condicional" citado na ementa.
Fundamento: Superfície de Ataque
Em segurança de sistemas, "superfície de ataque" é o conjunto total de pontos por onde um sistema pode ser comprometido — quanto maior a superfície exposta, mais oportunidades para exploração, mesmo que a maior parte dela nunca seja usada de forma legítima. Aplicado a agentes de IA: cada ferramenta exposta ao modelo, mesmo uma que "nunca deveria ser chamada naquele contexto", é tecnicamente alcançável se o modelo for manipulado (por instrução ambígua, por conteúdo malicioso injetado via ferramenta de leitura) a chamá-la. Reduzir a superfície — expor só o necessário para a tarefa em curso — é uma mitigação de segurança tão real quanto uma mitigação de performance.
Duas estratégias de resolução
Existem, na prática, duas formas complementares de decidir qual subconjunto de ferramentas/skills expor a cada turno:
Estratégia A — Resolução por regra declarativa (estática)
Baseada em fatos conhecidos ANTES da chamada ao modelo:
papel do agente, tipo de tarefa, ambiente.
regras_de_resolucao:
- se papel == "agente-leitor-codigo":
ferramentas = [ler_arquivo, buscar_no_repo, listar_dir]
- se papel == "agente-revisor-pr":
ferramentas = [ler_arquivo, comentar_pr, rodar_testes]
- se tarefa.tipo == "migracao_de_dados":
ferramentas += [ler_schema_banco, gerar_script_migracao]
→ Determinístico, auditável, rápido (não depende de
nenhuma chamada extra ao modelo para decidir).
Estratégia B — Resolução por relevância dinâmica (semântica)
Baseada no conteúdo do pedido do turno atual, usando
busca semântica sobre um catálogo de ferramentas/skills
(mesma técnica de embeddings da Parte 2 deste livro).
pedido_do_usuario = "preciso enviar um relatório por email
para o time financeiro"
candidatos = buscar_ferramentas_similares(pedido_do_usuario,
catalogo_completo,
top_k=5)
→ candidatos: [enviar_email, gerar_relatorio_pdf,
listar_contatos_financeiro, ...]
→ Flexível, escala para catálogos grandes (centenas de
skills), mas introduz uma etapa probabilística extra
(a busca pode errar o top-k) antes mesmo da chamada
principal ao modelo.Na prática, sistemas maduros combinam as duas: a Estratégia A (regra declarativa) define o universo permitido pelo papel/RBAC — nunca é ultrapassada, é o teto de segurança. A Estratégia B (relevância dinâmica) opera dentro desse universo já filtrado, escolhendo o subconjunto mais provável de ser útil para o pedido específico. RBAC nunca é decidido por relevância semântica — seria delegar segurança a um componente probabilístico, violando o princípio do capítulo 1.1.
Aprofundamento Técnico
Arquitetura do resolvedor: onde ele se encaixa no fluxo
function turno_do_agente(estado, mensagem_usuario):
# Passo 1: universo permitido (RBAC — nunca varia por
# relevância, só por papel/contexto de risco — cap. 1.3)
universo_permitido = resolver_por_rbac(estado.papel,
estado.contexto_risco)
# Passo 2: dentro do universo permitido, resolver o
# subconjunto relevante para ESTE turno (motor de
# resolução condicional)
ferramentas_do_turno = resolver_condicional(
mensagem_usuario,
estado.tarefa_em_curso,
universo_permitido
)
# Passo 3: montar contexto (capítulo 1.2) já com o
# subconjunto de ferramentas resolvido, não o catálogo
# inteiro
contexto = montar_contexto(estado, mensagem_usuario,
ferramentas_do_turno)
resposta = chamar_llm(contexto, ferramentas_do_turno)
...Note a ordem: RBAC primeiro (teto de segurança, estático), resolução condicional depois (relevância, dentro do teto). Inverter essa ordem — resolver por relevância primeiro e checar RBAC só no momento de executar — ainda funciona para bloquear a execução indevida, mas expõe desnecessariamente, na definição de ferramentas do contexto, capacidades que o agente nunca poderia de fato usar naquele papel. É ineficiente e aumenta superfície de risco sem necessidade.
Skills como unidade de resolução, não só ferramentas individuais
À medida que o catálogo cresce, resolver ferramenta por ferramenta individualmente se torna menos prático que resolver por skill — um agrupamento coerente de ferramentas, contexto e instruções específicas para uma classe de tarefa (a Parte 4 deste livro aprofunda o design de skills modulares; aqui, o que importa é como elas entram na resolução condicional):
Sem agrupamento em skill (resolução granular, mais frágil):
candidatos = [ler_planilha, validar_formato_csv,
calcular_media, calcular_desvio_padrao,
gerar_grafico, exportar_pdf, ...]
→ o modelo precisa entender sozinho que essas 6
ferramentas soltas, juntas, resolvem "análise de
dados financeiros"
Com agrupamento em skill (resolução por pacote coerente):
skill_resolvida = "analise-financeira"
→ traz consigo: as ferramentas relevantes JÁ agrupadas,
MAIS instruções específicas de como combiná-las,
MAIS specs de formatação de saída esperada
→ o motor de resolução condicional decide "esta skill se
aplica" uma vez, em vez de decidir seis vezes se cada
ferramenta isolada se aplicaResolver por skill reduz a carga de decisão do modelo (uma decisão de "isso se aplica" em vez de N decisões de ferramenta individual) e mantém coerência: uma skill carrega junto o conhecimento de como combinar suas ferramentas, não apenas quais ferramentas existem.
Trade-off: resolução dinâmica tem custo de latência e pode errar
A Estratégia B (relevância dinâmica) não é gratuita: buscar candidatos por similaridade semântica adiciona uma chamada extra (a um índice vetorial, ou a um modelo de classificação leve) antes da chamada principal ao LLM — latência extra, e mais um componente probabilístico que pode errar o top-k e deixar de fora exatamente a ferramenta certa. Para catálogos pequenos (menos de ~15-20 ferramentas dentro do universo já filtrado por RBAC), resolução puramente estática por regra declarativa costuma ser suficiente e mais previsível — o custo de manter regras explícitas é menor que o custo de operar um sistema de busca semântica adicional. A resolução dinâmica se justifica quando o catálogo, mesmo após o filtro de RBAC, ainda é grande o suficiente para que "poluição de ferramentas" (Custo 2 da seção anterior) se torne o problema dominante. Escolher a estratégia certa é, como em todo o restante deste livro, uma questão de dimensionar a solução ao tamanho real do problema — não aplicar a técnica mais sofisticada disponível por padrão.
Padrões e Armadilhas
Padrões recomendados
Padrão 1: registre qual subconjunto de ferramentas foi resolvido em cada turno. Para depuração e auditoria, é tão importante saber "quais ferramentas o agente tinha disponíveis neste turno" quanto saber "qual ferramenta ele chamou". Sem esse registro, é impossível diferenciar, a posteriori, um erro de seleção (a ferramenta certa estava disponível e o modelo escolheu a errada) de um erro de resolução (a ferramenta certa nunca chegou a ser oferecida).
Padrão 2: trate a lista de ferramentas resolvida como parte do contrato de teste do agente. Assim como se testa se uma API retorna o schema esperado, é possível — e recomendável — escrever testes que verificam se, para um determinado papel e tipo de tarefa, o resolvedor condicional retorna exatamente o conjunto de ferramentas esperado. Isso transforma uma decisão que poderia ser invisível (por que essa ferramenta apareceu, ou não apareceu, neste contexto?) em algo verificável e regressível.
Padrão 3: prefira nomes de ferramentas distintos e específicos a nomes genéricos versionados. O exemplo "buscar_cliente" vs "buscar_cliente_v2" vs "consultar_cadastro" citado na seção anterior é sintoma de um problema de nomeação, não só de resolução. Ferramentas com nomes que descrevem claramente seu escopo específico (por exemplo, "buscar_cliente_por_cpf" vs "buscar_cliente_por_id_interno") reduzem ambiguidade tanto para o resolvedor automático quanto para quem lê o catálogo depois.
Armadilhas comuns
⚠️ Armadilha 1: usar resolução dinâmica (Estratégia B) para decidir o que é permitido. O que acontece: alguém implementa a busca por relevância semântica e, por conveniência de código, deixa que ela também filtre por permissão — misturando "o que é relevante" com "o que é permitido" no mesmo componente probabilístico. Isso viola a separação estabelecida no capítulo 1.1: permissão é uma decisão determinística, relevância pode ser probabilística, mas as duas nunca deveriam ser resolvidas pelo mesmo mecanismo. Versão correta: RBAC sempre roda antes e de forma independente, como filtro estático que define o teto; a resolução dinâmica só opera dentro desse teto.
⚠️ Armadilha 2: catálogo de ferramentas cresce sem que ninguém audite ferramentas obsoletas. O que acontece: ferramentas antigas, substituídas por versões melhores, continuam registradas no catálogo "por segurança", inflando o universo de candidatos tanto para resolução estática quanto dinâmica, sem trazer valor. Versão correta: um catálogo de ferramentas precisa de um processo de depreciação tão real quanto o de qualquer API interna — remover, não apenas parar de recomendar.
⚠️ Armadilha 3: assumir que resolução por skill elimina a necessidade de RBAC granular dentro da skill. O que acontece: uma skill é aprovada como um todo para um papel, mas internamente ela agrupa uma ferramenta de leitura inofensiva com outra de escrita de alto raio de impacto — e a aprovação do pacote acaba concedendo, sem revisão explícita, a permissão para a parte mais arriscada. Versão correta: RBAC continua sendo avaliado por ferramenta individual mesmo quando o agrupamento em skill simplifica a decisão de relevância; o agrupamento não substitui a granularidade da permissão.