O que é AI Agent? Explicação detalhada com exemplos em Java
1. Visão Geral
“AI Agent” é uma palavra-chave que aparece por toda parte, mas a definição costuma ser vaga: há quem chame todo chatbot de agent, há quem considere apenas sistemas complexos de múltiplas etapas como um agent de verdade. Este artigo explica claramente o que é AI Agent, os componentes obrigatórios que precisa ter e o mecanismo de loop por trás disso. Após ler, você será capaz de construir um agent minimal em Java puro para entender como funciona no interior, depois evoluir para uma versão usando LLM de verdade com Spring AI.
2. O que é AI Agent?
Definição sucinta: AI Agent é um sistema que usa LLM como cérebro para tomar decisões automaticamente sobre ações, visando alcançar um objetivo, em vez de apenas responder uma pergunta e parar.
Diferença com chatbot comum:
| Característica | Chatbot comum | AI Agent |
|---|---|---|
| Processamentos | 1 iteração: pergunta → resposta | Múltiplas etapas: observar → raciocinar → agir → repetir |
| Chama tools/APIs? | Geralmente não | Sim, decide automaticamente qual tool chamar |
| Tem objetivo de longo prazo? | Não | Sim, o agent quebra o trabalho em partes para alcançar o objetivo |
| Exemplo | “Como está o tempo em Hanói?” → responde com texto descritivo | “Reserve o voo mais barato de Hanói para Ho Chi Minh City amanhã” → encontra passagens, compara preços, reserva, confirma automaticamente |
Em outras palavras, LLM é apenas um “cérebro linguístico” que sabe gerar texto. Agent transforma esse cérebro em uma entidade que pode agir no mundo real (chamar APIs, ler arquivos, consultar banco de dados) e repetir automaticamente o processo de raciocínio até terminar a tarefa.
3. Componentes essenciais de um AI Agent
Um agent mínimo precisa de 4 componentes. Se faltar um destes, o sistema é apenas um chatbot “disfarçado” de agent.
3.1. LLM – cérebro de raciocínio
LLM recebe um prompt (consistindo de objetivo, histórico, lista de tools disponíveis) e gera a próxima decisão: responder diretamente ou chamar qual tool, com quais parâmetros.
3.2. Tool (function calling) – braço de ação do agent
Tool é uma função específica que o agent pode chamar: pesquisar pedido, chamar API de clima, consultar banco de dados. Esta é a parte que transforma o agent de “saber falar” para “saber fazer”.
public interface Tool {
String name();
boolean canHandle(String input);
String execute(String input);
}
canHandle verifica se esta tool pode processar a entrada atual; execute executa a ação e retorna o resultado (observation).
3.3. Memory – memória
O agent precisa se lembrar do que fez no passo anterior (histórico de conversa, resultados de tools chamadas) para evitar repetir ações inúteis. Memory pode ser simples, como uma List<String> que armazena logs de etapas, ou mais complexo, como um vector store para recuperar informações relevantes.
3.4. Control loop – loop de controle
Esta é a parte “motor” que executa todo o processo: itera por etapas Thought → Action → Observation até alcançar o objetivo ou esgotar o número de etapas permitidas. A próxima seção aprofundará este mecanismo.
4. Vòng lặp ReAct: como o agent “pensa e depois age”
ReAct (Reasoning + Acting) é o modelo de loop mais comum para agents:
- Thought: LLM raciocina “o que preciso fazer a seguir?”
- Action: seleciona uma tool e a chama com parâmetros apropriados.
- Observation: recebe o resultado da tool, coloca de volta no contexto.
- Repetir a partir da etapa 1 até quando LLM decide que há informações suficientes para a resposta final, ou esgota
maxSteps.
Para entender bem este mecanismo sem precisar chamar um LLM de verdade (custa API key), construímos um agent mini em Java puro, usando if-else em vez do LLM de verdade.
public class SimpleAgent {
private final List<Tool> tools;
private final int maxSteps;
public SimpleAgent(List<Tool> tools, int maxSteps) {
this.tools = tools;
this.maxSteps = maxSteps;
}
public String run(String goal) {
String observation = goal;
for (int step = 1; step <= maxSteps; step++) {
Tool chosen = tools.stream()
.filter(t -> t.canHandle(observation))
.findFirst()
.orElse(null);
if (chosen == null) {
return "Nenhuma tool pode lidar com: " + observation;
}
System.out.printf("Etapa %d - Thought: precisa usar a tool '%s'%n", step, chosen.name());
String result = chosen.execute(observation);
System.out.printf("Etapa %d - Observation: %s%n", step, result);
return result; // exemplo simples: concluído após 1 etapa
}
return "Limite de " + maxSteps + " etapas esgotado, mas a tarefa não foi concluída.";
}
}
maxSteps é exatamente o “orçamento” de etapas — obrigatório ter para que o agent não rode infinitamente se nunca alcançar o objetivo. O loop for simula Thought (seleciona a tool), Action (execute), Observation (resultado impresso no console).
Três ferramentas de exemplo:
public class WeatherTool implements Tool {
@Override
public String name() {
return "WeatherTool";
}
@Override
public boolean canHandle(String input) {
return input.toLowerCase().contains("clima");
}
@Override
public String execute(String input) {
return "Hanói hoje 28°C, céu nublado.";
}
}
public class OrderStatusTool implements Tool {
@Override
public String name() {
return "OrderStatusTool";
}
@Override
public boolean canHandle(String input) {
return input.toLowerCase().contains("pedido");
}
@Override
public String execute(String input) {
return "Pedido #1023 está sendo entregue, previsão de entrega em 2 dias.";
}
}
public class CalculatorTool implements Tool {
@Override
public String name() {
return "CalculatorTool";
}
@Override
public boolean canHandle(String input) {
return input.matches(".*\\d+\\s*\\+\\s*\\d+.*");
}
@Override
public String execute(String input) {
String digits = input.replaceAll("[^0-9+]", "");
String[] parts = digits.split("\\+");
int sum = Integer.parseInt(parts[0]) + Integer.parseInt(parts[1]);
return "Resultado: " + sum;
}
}
Experimentar:
SimpleAgent agent = new SimpleAgent(
List.of(new CalculatorTool(), new WeatherTool(), new OrderStatusTool()),
3
);
String result = agent.run("Me diga o clima de Hanói hoje");
System.out.println(result);
Resultado:
Etapa 1 - Thought: precisa usar a tool 'WeatherTool'
Etapa 1 - Observation: Hanói hoje 28°C, céu nublado.
Hanói hoje 28°C, céu nublado.
Escreva testes para validar o comportamento de seleção correta de ferramentas e tratamento do caso onde nenhuma ferramenta se encaixa:
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class SimpleAgentTest {
@Test
void shouldPickWeatherToolWhenGoalMentionsWeather() {
SimpleAgent agent = new SimpleAgent(
List.of(new CalculatorTool(), new WeatherTool(), new OrderStatusTool()),
3
);
String result = agent.run("Me diga o clima de Hanói hoje");
assertThat(result).contains("Hanói");
}
@Test
void shouldReturnErrorWhenNoToolMatches() {
SimpleAgent agent = new SimpleAgent(List.of(new CalculatorTool()), 3);
String result = agent.run("Cante uma música para mim");
assertThat(result).startsWith("Nenhuma tool pode lidar com");
}
}
Este exemplo usa if-else em vez de LLM, então o “raciocínio” é muito rígido. Agente real difere no ponto: em vez de canHandle rígido, pelo fato de LLM ler automaticamente a descrição da tool e depois decidir qual tool chamar, com parâmetros que LLM extrai automaticamente da pergunta em linguagem natural.
5. Construindo um agent de verdade com Spring AI e tool calling
Para ver como LLM de verdade toma decisões, usamos Spring AI — framework que integra modelos AI ao Spring Boot, com suporte integrado para tool calling.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>1.0.0</version>
</dependency>
Configurar API key e modelo:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4o-mini
Declarar ferramenta usando anotação @Tool, de acordo com o papel de OrderStatusTool no exemplo anterior, mas desta vez o LLM de verdade a chamará:
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
@Component
public class OrderTools {
@Tool(description = "Consultar status do pedido pelo código de pedido")
public String getOrderStatus(String orderId) {
// na prática, chamaria OrderService / banco de dados aqui
return "Pedido " + orderId + " está sendo entregue, previsão de entrega em 2 dias.";
}
}
description é extremamente importante: LLM baseia-se nesta descrição para decidir se deve chamar esta ferramenta e quais parâmetros passar.
Service usa ChatClient para associar a ferramenta ao agent:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class OrderAssistantService {
private final ChatClient chatClient;
public OrderAssistantService(ChatClient.Builder builder, OrderTools orderTools) {
this.chatClient = builder
.defaultTools(orderTools)
.build();
}
public String ask(String question) {
return chatClient.prompt(question).call().content();
}
}
Chamar ask("Onde está meu pedido ORD-1023?"), nos bastidores, Spring AI vai:
- Enviar a pergunta junto com a descrição da ferramenta para o modelo.
- O modelo retorna uma decisão “chamar
getOrderStatuscomorderId="ORD-1023"” em vez de responder imediatamente. - Spring AI invoca automaticamente o método Java correspondente, obtém o resultado.
- Envia este resultado de volta ao modelo para que o modelo escreva a resposta natural final.
Seu pedido ORD-1023 está sendo entregue e deve chegar em 2 dias.
Todas essas 4 etapas formam um loop ReAct completo, exceto que Spring AI ocultou o loop for. Você não precisa escrever o loop de controle como no exemplo de Java puro na seção 4.
Nota: versão
spring-ai-starter-model-openaie o nome do artifact podem mudar com o tempo; sempre verifique o BOM correspondente à versão do Spring Boot que você usa antes de adicionar a dependência.
6. Tipos comuns de Agent
- Single-agent ReAct: um único agent, itera Thought-Action-Observation. Adequado para tarefas médias, como nos dois exemplos acima.
- Plan-and-Execute: o agent cria um plano detalhado (lista de etapas), depois executa cada etapa, sem raciocinar continuamente como ReAct. Adequado para tarefas multi-etapas com estrutura clara (exemplo: “criar um relatório com 5 seções”).
- Multi-agent: múltiplos agentes especializados colaborando, geralmente tem um agent “Supervisor” coordenando agentes “Worker” (exemplo: agente de busca, agente de escrita, agente de verificação de dados), os resultados são consolidados.
A escolha do tipo depende da complexidade da tarefa: tarefas simples usam single-agent, tarefas com múltiplos domínios (busca + escrita + verificação) devem ser divididas em multi-agent para facilitar o controle e debug de cada parte.
7. Erros comuns & quando EVITAR usar Agent
- Loop infinito, queimando tokens: se você não definir
maxStepsou orçamento de tokens, o agent pode ficar em loop eternamente porque LLM “acha” que ainda não terminou. Sempre defina um limite claro de etapas como emSimpleAgentna seção 4. - Descrição vaga da ferramenta: se a
descriptionda ferramenta não for clara, LLM pode chamar a ferramenta errada ou passar parâmetros do tipo errado. Escreva uma descrição específica, deixe claro o formato dos parâmetros esperados. - Falta de guardrails para ações perigosas: o agent pode chamar ferramentas para deletar dados, transferir dinheiro… sem uma etapa de confirmação é um grande risco. Sempre adicione uma camada de revisão (human-in-the-loop ou verificação baseada em regras) antes de executar uma ação irreversível.
- Exagero para tarefas simples: se a pergunta só precisa de 1 chamada LLM para obter a resposta (exemplo: traduzir uma frase), não construa um loop de agent inteiro com tool calling. Apenas adiciona latência e custa mais chamar o modelo várias vezes desnecessariamente.
Nota: se seu sistema não precisa chamar ações externas (APIs, banco de dados) e apenas gera texto uma vez, esse é um problema para LLM comum — não para um agent. Não adicione complexidade desnecessária.
8. Conclusão
AI Agent é diferente de um chatbot comum na capacidade de tomar decisões sobre ações e repetir o processo de raciocínio até alcançar o objetivo, baseado em quatro componentes: LLM, ferramenta, memória e loop de controle. O loop ReAct (Thought-Action-Observation) é o mecanismo mais comum por trás da maioria dos agentes atuais, e você pode simular por conta própria em Java puro para entender a natureza antes de migrar para usar um framework como Spring AI para produção. O mais importante: sempre defina um limite de etapas, escreva descrições de ferramentas claras e adicione guardrails para ações irreversíveis — agente é poderoso mas também pode “fazer demais” se não for controlado.