Introdução a Agentes
Ferramentas (Tools)
Permitir que a IA consulte pedidos, estoque ou FAQ via funções que seu código executa.
Nesta aula você vai
- Definir schema de tool e implementar executor seguro
- Usar function calling ou JSON estruturado
- Validar argumentos antes de chamar APIs internas
Ferramentas (Tools)
Objetivos
- Permitir que IA execute ações controladas por você
- Nunca deixar o modelo acessar banco diretamente
O modelo pede — você executa
Essa é a regra de segurança mais importante deste módulo:
O LLM sugere a ação. O seu código valida, executa e devolve o resultado.
Sem essa camada, você teria que dar ao modelo credencial de banco — absurdo. Com tools, o modelo fala em linguagem natural; seu backend traduz em chamada segura à API interna.
LLM sugere tool + args → SEU código valida → SEU código executa → resultado volta ao LLM
Analogia: o LLM é o estagiário que preenche o formulário; você é o gerente que assina e aperta o botão no sistema.
Definição de tools (OpenAI function calling)
const tools = [
{
type: 'function',
function: {
name: 'buscar_pedido',
description: 'Retorna status de entrega de um pedido pelo ID numérico',
parameters: {
type: 'object',
properties: {
pedido_id: { type: 'string', description: 'Ex: 8842' },
},
required: ['pedido_id'],
},
},
},
];
A description importa — o modelo usa para decidir quando chamar a função. Seja claro e específico.
Executor seguro
async function executeTool(name, args, userId) {
if (name === 'buscar_pedido') {
const id = String(args.pedido_id).replace(/\D/g, '');
if (!id) throw new Error('ID inválido');
// Autorização: pedido pertence ao userId?
return await orderService.getStatus(id, userId);
}
throw new Error(`Tool desconhecida: ${name}`);
}
Cenários que o executor deve bloquear:
Pedido de outro cliente (sem autorização)
ID malformado ou injection em string
Tool que não existe no allowlist
Loop agente (simplificado)
async function runAgent(userMessage, history) {
let messages = [...history, { role: 'user', content: userMessage }];
for (let step = 0; step < 3; step++) {
const response = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages,
tools,
tool_choice: 'auto',
});
const msg = response.choices[0].message;
if (msg.tool_calls?.length) {
messages.push(msg);
for (const call of msg.tool_calls) {
const args = JSON.parse(call.function.arguments);
const result = await executeTool(call.function.name, args, userId);
messages.push({
role: 'tool',
tool_call_id: call.id,
content: JSON.stringify(result),
});
}
continue; // LLM formata resposta com dados reais
}
return msg.content; // resposta final
}
return 'Não consegui concluir a solicitação.';
}
Conversa completa:
Usuário: "Status do 8842?"
LLM: [tool_call: buscar_pedido(8842)]
Código:{ status: "shipped", tracking: "BR123" }
LLM: "Seu pedido 8842 foi enviado. Rastreio: BR123."
Alternativa sem function calling: JSON manual
Peça no system prompt:
Se precisar buscar pedido, responda SOMENTE:
{"action":"buscar_pedido","pedido_id":"123"}
Caso contrário, responda texto normal ao usuário.
Seu código detecta JSON → executa → segunda chamada com resultado. Mais frágil (modelo pode misturar texto e JSON), mais portável entre provedores.
Tools comuns para negócio
| Tool | Função |
|---|---|
buscar_pedido(id) |
Status, rastreio |
listar_produtos(q) |
Catálogo |
buscar_faq(q) |
Artigos de ajuda |
criar_ticket(texto) |
Escala humano |
Comece com uma. Três tools instáveis são piores que uma confiável.
Segurança
- Allowlist de tools por produto
- Timeout por execução (5s)
- Log de toda tool call com args (sem dados sensíveis em log público)
- Rate limit por tool (busca pedido ≠ disparar e-mail)
Resumo
- Tool = função sua exposta ao LLM via schema
- LLM escolhe tool; código executa e valida
- Function calling nativo reduz parsing manual
- Uma tool bem feita > dez tools instáveis
Tools definidas — falta enxergar o fluxo inteiro de ponta a ponta. Na próxima aula percorremos o caso "Meu pedido já saiu?" passo a passo.