O problema com a chamada tradicional de ferramentas
Quando um Modelo de Linguagem Grande (LLM — Large Language Model) precisa consultar ferramentas externas, o fluxo convencional funciona assim: o modelo chama uma ferramenta, aguarda o resultado, raciocina sobre ele, chama a próxima ferramenta e repete o ciclo. Para tarefas que envolvem múltiplas chamadas, esse padrão gera latência e consumo de tokens que se acumulam rapidamente.
Imagine a pergunta: “Quais membros do time de engenharia ultrapassaram o orçamento de viagens no terceiro trimestre?” Sem PTC, o modelo precisaria chamar uma ferramenta para listar os 20 membros do time, depois chamar outra ferramenta 20 vezes para buscar os registros de despesas de cada um, receber mais de 2.000 linhas de dados na janela de contexto e, só então, tentar filtrar e comparar tudo em linguagem natural. Cada chamada exige um ciclo completo de inferência do modelo.
Esse processo cria três problemas que se somam:
- Consumo de tokens: todos os resultados intermediários — inclusive os milhares de registros que o modelo vai descartar — passam pela janela de contexto.
- Latência: 20 chamadas sequenciais significam 20 ciclos de inferência.
- Precisão: pedir a um modelo de linguagem que filtre, agregue e compare milhares de registros em linguagem natural é uma fonte de erros. Algumas linhas de Python fariam isso com exatidão.

Como a Chamada Programática de Ferramentas (PTC) resolve isso
A Chamada Programática de Ferramentas (PTC — Programmatic Tool Calling) inverte o padrão. Em vez de orquestrar chamadas uma a uma, o modelo gera um único bloco de código Python que coordena todas as ferramentas, processa os resultados e retorna apenas a saída final para o contexto. O modelo é amostrado uma vez para produzir o código; a execução fica por conta do ambiente sandbox.

No mesmo exemplo de auditoria de despesas, o código gerado pelo modelo com PTC ativado faz duas coisas importantes. Primeiro, usa asyncio.gather() para buscar os registros de todos os 20 funcionários em paralelo, em vez de sequencialmente. Segundo, toda a filtragem, agregação e comparação de orçamentos acontece em Python — não em linguagem natural. Apenas a saída do print() final volta ao contexto do modelo. Os mais de 2.000 registros brutos nunca chegam a tocá-lo.
import asyncio
import json
# Step 1: Get team members
team_json = await get_team_members(department="engineering")
team = json.loads(team_json)
# Step 2: Fetch all expense records in parallel
expense_tasks = [
get_expenses(employee_id=m["id"], quarter="Q3")
for m in team
]
expenses_results = await asyncio.gather(*expense_tasks)
# Step 3: Filter and check budgets
exceeded = []
for member, exp_json in zip(team, expenses_results):
expenses = json.loads(exp_json)
total_travel = sum(
e["amount"] for e in expenses
if e["category"] == "travel" and e["status"] == "approved"
)
if total_travel > 5000:
budget_json = await get_custom_budget(user_id=member["id"])
budget = json.loads(budget_json)
limit = budget["budget_limit"]
if total_travel > limit:
exceeded.append({
"name": member["name"],
"spent": total_travel,
"limit": limit,
"exceeded_by": total_travel - limit
})
# Step 4: Only the summary enters the model's context
print(f"{len(exceeded)} members exceeded budget:")
print(json.dumps(exceeded, indent=2))
O modelo é amostrado apenas duas vezes no total: uma para gerar o código e outra para interpretar o resultado final. Tudo entre esses dois momentos — chamadas de ferramentas, processamento de dados, filtragem — acontece dentro do container, sem inferência adicional.
O PTC é especialmente eficaz para processamento de grandes volumes de dados, cálculos numéricos precisos, orquestração de processos em múltiplas etapas e cenários sensíveis à privacidade, onde dados brutos não devem entrar no contexto do modelo.
Três formas de implementar PTC no Amazon Bedrock
A AWS descreve três caminhos para implementar PTC no Amazon Bedrock, cada um adequado a um perfil diferente de equipe.
Parte 1: PTC auto-hospedado com Amazon ECS e Docker
Para equipes que precisam de controle total, a abordagem auto-hospedada usa dois componentes principais: um orquestrador (rodando em uma task do Amazon Elastic Container Service — ECS, em uma função AWS Lambda ou em outra unidade de computação) e um sandbox Docker isolado que executa o código Python gerado pelo modelo.

A ideia central é simples: em vez de passar as definições de ferramentas no parâmetro tool_config, elas são injetadas no system prompt, e o modelo recebe instrução para escrever código Python que orquestre essas ferramentas. O código gerado roda no sandbox Docker. O orquestrador atua como plano de controle, interceptando chamadas de ferramentas via Comunicação entre Processos (IPC — Inter-Process Communication), executando-as externamente e injetando os resultados de volta no sandbox.

O sistema usa uma arquitetura de duplo processo. O orquestrador inicia um container Docker para cada requisição de execução de código. A comunicação acontece via fluxos de entrada e saída padrão: o container escreve requisições de chamada de ferramentas no stderr, e o orquestrador injeta os resultados via stdin. Para demarcar os diferentes tipos de mensagem no fluxo de texto, o sistema define marcadores de limite como __PTC_TOOL_CALL__, __PTC_END_CALL__ e __PTC_OUTPUT__.
O container Docker roda com isolamento rígido: sem acesso à rede, sistema de arquivos somente leitura, usuário não-root, capacidades Linux removidas e limites de memória e CPU aplicados. O código gerado pelo modelo não consegue escapar do sandbox, persistir dados ou consumir recursos excessivos.
docker run --rm \
--network none \
--read-only \
--tmpfs /tmp:size=64m \
--user sandbox \
--cap-drop ALL \
--memory 256m \
--cpus 0.5 \
-v /path/to/code.py:/sandbox/user_code.py:ro \
ptc-sandbox
O loop do orquestrador envia a consulta do usuário ao Amazon Bedrock, extrai o código gerado pelo modelo do bloco tool_use da resposta, executa no sandbox Docker e devolve a saída como tool_result. O modelo então produz a resposta final legível para humanos.
Parte 2: PTC gerenciado com Amazon Bedrock AgentCore Code Interpreter
Para equipes que preferem não gerenciar containers Docker e infraestrutura de ECS, o Amazon Bedrock AgentCore oferece um Code Interpreter gerenciado que implementa o mesmo padrão PTC. O modelo escreve código, um sandbox gerenciado o executa e apenas o resultado final retorna ao contexto do modelo.

A diferença principal em relação à abordagem auto-hospedada é que as ferramentas são pré-carregadas na sessão do sandbox em vez de serem despachadas de volta ao cliente via IPC. Inicia-se uma sessão do Code Interpreter, as definições das funções de ferramentas são injetadas como código Python e, então, o modelo gera código que chama essas funções diretamente. O AgentCore usa o cliente boto3 bedrock-agentcore.
A comparação entre as duas abordagens:
- Auto-hospedado (ECS + Docker): você gerencia a infraestrutura, tem controle total sobre o sandbox, pode instalar pacotes Python específicos e configurar políticas de segurança personalizadas. A execução das ferramentas acontece no lado do cliente via IPC.
- AgentCore (gerenciado): infraestrutura totalmente gerenciada, ambiente de execução padrão, ferramentas executadas dentro do próprio sandbox. Recomendado para quem quer os benefícios de economia de tokens e precisão do PTC sem o custo operacional de manter containers.
Parte 3: Compatibilidade com o SDK da Anthropic via proxy
Para equipes que preferem a experiência de desenvolvimento do SDK da Anthropic e querem usar o Amazon Bedrock como backend, é possível construir um proxy leve de tradução de API que fica entre o SDK da Anthropic e o Amazon Bedrock.

O proxy é implantado no Amazon ECS e traduz chamadas da API da Anthropic para chamadas InvokeModel do Amazon Bedrock. Ele também gerencia o ciclo de vida do sandbox Docker e o protocolo PTC completo de forma transparente. Para migrar, basta alterar o base_url para apontar para o proxy:
import anthropic
# Point the Anthropic SDK at the proxy deployed on ECS.
# The proxy translates these calls to Bedrock InvokeModel under the hood.
client = anthropic.Anthropic(
api_key="your-proxy-api-key", # API key configured in the proxy
base_url="http://your-proxy-url.com" # Your proxy's ECS endpoint
)
Essa abordagem é recomendada para equipes que preferem a interface do SDK da Anthropic enquanto rodam inferência no Amazon Bedrock e se beneficiam de estar dentro da própria conta AWS.
Resultados experimentais
Para validar a solução auto-hospedada, a AWS executou a mesma tarefa de auditoria de despesas em múltiplos modelos disponíveis no Amazon Bedrock. O cenário usou oito membros de um time de engenharia, com 20 a 50 registros de despesas por pessoa por trimestre (cada um com mais de 15 campos) e regras de orçamento com limite padrão de US$ 5.000 e exceções personalizadas para cargos sênior.
A resposta correta esperada era:
- Alice Chen: orçamento US$ 5.000, gasto US$ 9.876,54, excedeu em +US$ 4.876,54
- Emma Johnson: orçamento US$ 5.000, gasto US$ 5.266,02, excedeu em +US$ 266,02
- Grace Taylor: orçamento US$ 5.000, gasto US$ 6.474,46, excedeu em +US$ 1.474,46
Os resultados comparativos entre modo PTC e modo tradicional:
- Claude Sonnet 4.6 (adaptive thinking): 12.739 tokens (PTC) vs. 128.043 (sem PTC) — redução de 90,1%. Correto em ambos os modos.
- Claude Opus 4.6 (adaptive thinking): 13.043 vs. 126.152 — redução de 89,7%. Correto em ambos.
- Qwen3-Coder-480B: 34.159 vs. 305.114 — redução de 88,8%. Correto apenas com PTC.
- Qwen3-Next-80B: 28.878 vs. 233.332 — redução de 87,6%. Correto apenas com PTC.
- DeepSeek V3.2 (thinking): 19.543 vs. 245.967 — redução de 92,1%. Correto apenas com PTC.
- MiniMax M2.1 (thinking): 11.787 vs. 101.990 — redução de 88,4%. Correto apenas com PTC.
- Kimi 2.5 (thinking): 10.875 vs. 148.085 — redução de 92,7%. Correto apenas com PTC.
- GLM 4.7 (thinking): 11.550 vs. 115.829 — redução de 90,0%. Correto apenas com PTC.
Os principais achados são três. O consumo de tokens caiu entre 87% e 92% em todos os modelos no modo PTC — em vez de centenas de milhares de tokens fluindo pela janela de contexto, apenas o código e o resumo final chegam ao modelo. A precisão melhorou significativamente: no modo PTC, todos os oito modelos produziram a resposta correta; sem PTC, apenas os modelos Claude acertaram. A compatibilidade entre modelos foi confirmada — Claude, Qwen, DeepSeek, MiniMax, Kimi e GLM alcançaram resultados corretos no modo PTC, demonstrando que o padrão funciona em famílias de modelos diversas.
Análise de custos
Tomando o Claude Sonnet como exemplo, com redução de aproximadamente 90% no consumo de tokens e precificação de US$ 3/US$ 15 por milhão de tokens de entrada/saída, a projeção para 1.000 execuções diárias da tarefa de auditoria em ambiente de produção seria:
- Custo diário estimado sem PTC: ~US$ 520
- Custo diário estimado com PTC: ~US$ 52
- Custo mensal sem PTC: ~US$ 15.600
- Custo mensal com PTC: ~US$ 1.560
- Economia mensal estimada: ~US$ 14.040 (90%)
Os valores variam conforme a complexidade da tarefa e o volume de dados, mas o padrão é consistente: o PTC reduz custos em proporção à quantidade de dados intermediários que mantém fora da janela de contexto.
Conclusão
A Chamada Programática de Ferramentas representa uma mudança na forma como agentes de IA interagem com ferramentas — de invocações conversacionais uma a uma para execução paralela e filtrada orquestrada por código. As três abordagens apresentadas pela AWS são agnósticas em relação ao modelo, implantadas de forma privada dentro da conta AWS do usuário e extensíveis a novos modelos à medida que ficam disponíveis no Amazon Bedrock.
Para quem quiser explorar mais, a AWS disponibiliza a documentação oficial de PTC da Anthropic, o repositório de exemplos no GitHub com o padrão PTC, a documentação do AgentCore Code Interpreter e o repositório do proxy Anthropic-Bedrock.
Fonte
Implementing programmatic tool calling on Amazon Bedrock (https://aws.amazon.com/blogs/machine-learning/implementing-programmatic-tool-calling-on-amazon-bedrock/)
Leave a Reply