Turn a single Anthropic SDK call into a real support-triage agent with a role, memory, and the judgment to answer, route, or escalate.
Quando coloquei pela primeira vez um assistente de automação de suporte diante de usuários reais — o RAG de automação de suporte de-identificado que construí depois do Painel de Suporte interno — a parte mais difícil não foi fazer o modelo escrever frases bonitas. Foi fazê-lo decidir o que fazer. Uma mensagem de cliente chega. O sistema deveria respondê-la diretamente a partir do que sabe? Passá-la à equipe certa? Ou admitir que não tem certeza e trazer um humano? Uma única chamada de modelo pode produzir texto. Um agente é a coisa que envolve essa chamada em um papel, uma memória e uma decisão.
Neste módulo você e eu construímos exatamente isso: um assistente de triagem de suporte ao cliente de-identificado. Ele recebe uma mensagem de cliente e faz uma de três coisas — responde a partir de uma pequena base de conhecimento, encaminha a mensagem para uma equipe ou escala quando não está confiante. Vamos fazê-lo crescer uma capacidade de cada vez, e cada linha de código é uma chamada real ao SDK da Anthropic que você pode rodar.
Pense em um agente como um novo colega no seu primeiro plantão de suporte. O modelo é a capacidade bruta dele de ler e escrever. Mas para ser útil ele também precisa de uma descrição de cargo (seu papel), uma memória da conversa até agora e o julgamento para escalar em vez de adivinhar. Adicionamos essas três coisas em ordem.
Ideia-chave: um agente não é um modelo mais inteligente — é um modelo mais um papel, mais memória, mais uma decisão sobre o que fazer com a resposta do modelo.
Um script comum faz a mesma coisa toda vez que você o roda. Um agente lê sua situação e escolhe seu próximo movimento. Os módulos anteriores desta trilha lhe deram a chamada bruta de modelo; um agente é o que você constrói em torno dessa chamada para que ela se comporte como um trabalhador em vez de uma calculadora.
Três ingredientes transformam uma chamada de modelo em um agente:
Armadilha comum: as pessoas chamam qualquer chatbot de "agente." A palavra justifica seu uso apenas quando o programa de fato age sobre a saída do modelo — encaminhando, escalando, chamando uma ferramenta — em vez de devolvê-la ao usuário.
Antes de escrevermos qualquer código, preveja: se você removesse o papel do nosso assistente de triagem e apenas enviasse a mensagem bruta do cliente ao modelo, o que você perderia? (Dica: pense no que o impede de inventar com confiança uma política de reembolso que não existe.)
Vamos fixar o trabalho antes de construí-lo. O assistente lida com uma mensagem de cliente por vez e precisa colocar essa mensagem em exatamente um de três baldes:
Esse terceiro balde é o que iniciantes pulam e o que mais importou no meu sistema real. Um assistente de triagem que nunca diz "não tenho certeza" é pior do que nenhum assistente, porque ele encaminha com confiança errada. Projetamos o escalonamento como um resultado de primeira classe, não um caso de erro.
Bom padrão: dê ao agente um caminho explícito de "escalar quando incerto". Conhecer os próprios limites é uma feature, não uma falha.
Tudo começa com uma chamada real de modelo. Esta é a menor versão possível do nosso agente: ela
entrega uma mensagem de cliente ao modelo e imprime a resposta. Copie-a, defina ANTHROPIC_API_KEY no
seu ambiente e rode — não há camada de abstração escondendo o que acontece.
Usamos claude-haiku-4-5 porque é o modelo mais rápido e barato para as primeiras chamadas reais de um aprendiz
— perfeito para um laço de triagem que roda em cada mensagem recebida. A resposta volta como uma
lista de blocos de conteúdo; response.content[0].text é a resposta do modelo. Isso é uma chamada de modelo. Ainda
não é um agente, porque nada disse ao modelo qual é o seu trabalho e nada decidiu o que fazer
com a resposta. Vamos consertar o primeiro desses pontos.
Neste momento o modelo está improvisando. Para fazê-lo nosso assistente de triagem, damos a ele um prompt de sistema — uma instrução permanente que enquadra cada mensagem que ele vê. Esta é a descrição de cargo do agente.
Note o que o papel faz: ele nomeia os três baldes do nosso design e exige que o modelo
comprometa-se com um. A instrução de "comece sua resposta com a ação em maiúsculas" é deliberada — ela
dá ao nosso código algo previsível para ler depois. Agora passamos esse papel ao modelo com o
parâmetro system.
O parâmetro system é separado das messages da conversa de propósito: o papel é constante,
a conversa muda. Com essa única mudança, a mesma chamada de modelo agora se comporta como um trabalhador de triagem
em vez de um chatbot genérico. Mas ele ainda não tem memória — cada chamada esquece a anterior.
Armadilha comum: enfiar o papel na mensagem do usuário em vez do parâmetro system. Isso
frequentemente funciona, mas o modelo trata instruções de sistema como mais autoritativas — exatamente o que você quer
para regras que o cliente nunca deveria conseguir sobrepor.
Uma conversa de suporte real tem acompanhamentos. "Ainda não está funcionando" só faz sentido se o agente lembra o que "isso" era. Damos memória ao agente mantendo a lista corrente de mensagens e repassando a lista inteira a cada turno. Vamos envolver nossa lógica de triagem em uma pequena classe que guarda esse histórico.
A linha-chave é messages=self.history. A cada turno acrescentamos a mensagem do cliente, enviamos a conversa
inteira, depois acrescentamos a resposta do modelo para que o próximo turno também a tenha. Essa lista crescente é
a memória do agente. Aqui está uma troca de dois turnos onde a segunda mensagem só faz sentido por causa da
primeira:
Como o primeiro turno ainda está em history, o modelo entende que a segunda mensagem se refere à
exportação que falha — e pode decidir escalar agora que o cliente tentou duas vezes. Isso é o papel,
a memória e o início do julgamento, tudo construído sobre a única chamada real de modelo com que começamos.
Reflita antes do quiz: nossa lista history cresce para sempre. Em uma conversa longa isso é tanto
caro (você reenvia cada mensagem passada) quanto, eventualmente, grande demais para o contexto do modelo. Qual é
um trade-off que você pesaria ao decidir como cortar esse histórico — e o que você poderia perder ao
cortar o lado errado?
Você agora tem um agente de triagem funcional: uma chamada verificada à Anthropic envolvida em um papel, uma memória e um conjunto claro de decisões. O que ele ainda não consegue fazer é agir sobre o mundo — consultar um cliente, abrir um chamado, ler a base de conhecimento real. Esse é o trabalho das ferramentas e do servidor MCP do módulo anterior. No projeto final, conectamos este agente a essas ferramentas e montamos o sistema completo de triagem de suporte de ponta a ponta.
Ideia-chave: tudo o que é avançado — ferramentas, planos de múltiplos passos, múltiplos agentes — é construído sobre as três coisas que você acabou de adicionar. Acerte o papel, a memória e a decisão, e o resto é extensão, não reinvenção.
Application-level questions on what makes a model call an agent.
1. According to this module, what turns a plain model call into an agent?
Correct Answer: B
An agent is a model call wrapped in a role (system prompt), memory (conversation history), and a decision your code makes with the output — not simply a smarter model.
2. In the first real call, what does response.content[0].text hold?
Correct Answer: C
The response is a list of content blocks; the first block's .text is the model's generated reply. The other options describe metadata or inputs, not the output text.
3. Why pass the triage role in the system parameter instead of inside the user message?
Correct Answer: C
The role is constant and authoritative, so it belongs in system. The model weights system instructions more heavily, which protects rules from being overridden by user input. Both system and user text are billed.
4. Why does the design treat ESCALATE as a first-class outcome rather than an error case?
Correct Answer: B
Knowing its limits is a feature. Without an explicit escalate path, the agent answers or routes confidently even when wrong — the failure mode that mattered most in the real support system.
5. In the TriageAgent class, which line gives the agent its memory?
Correct Answer: C
Passing the whole running history as messages is what lets the model see the prior turns. The system prompt sets the role, max_tokens caps the reply length, and model selects the model — none of those provide memory.
6. The second turn sends "It still does not work after retrying." Why can the agent understand what "it" means?
Correct Answer: B
Memory is just the resent message list. Because the first turn about the failing export is still in history, the model resolves 'it' from context. The model itself is stateless between calls.
7. What real trade-off does the unbounded history list create on a long conversation?
Correct Answer: B
Every turn resends all prior messages, so cost grows and the context can overflow. Trimming is necessary, but trimming the wrong end can drop the context a follow-up depends on.