…
Módulo 1 · Parte A de 3

O Agente

Um agente é uma entidade que interage com um ambiente em qualquer nível significativo. Uma pessoa em seu dia a dia é um agente nesse sentido, assim como um termostato que mantém a temperatura de uma sala ou um carro autônomo que se desloca pelo trânsito.

Todos eles percebem o ambiente por meio de sensores e agem sobre ele por meio de atuadores. Como cada ação alimenta a observação seguinte, percepção e ação formam um ciclo contínuo, o ciclo perceber, raciocinar e agir, que dura enquanto o agente interage. Todos os agentes construídos no curso seguem esse ciclo. O que muda é quanto conseguem perceber e até onde suas ações alcançam.

As três partes do ciclo

Cada iteração passa por três etapas, com nomes simples e funções distintas.

O agente percebe o ambiente por meio de observações e atua sobre ele por meio de ações. A etapa de decisão entre as duas pode mudar.

A percepção reúne o que o agente pode saber, o raciocínio escolhe o que fazer e a ação altera o ambiente. A percepção e a ação costumam vir de um modelo de interação existente, seja ele usado para controlar um aspirador, automação web, uma entidade de jogo ou um humanoide. O raciocínio pode mudar sem alterar essa fronteira, o que separa capacidade de alcance.

Explorar o ciclo e as arquiteturas clássicas?

Abra esta seção para ver exemplos concretos e uma taxonomia mais completa de arquiteturas.

  • A percepção fornece tudo o que o agente sabe sobre o ambiente. Um termostato lê um único número: a temperatura atual. Um carro autônomo combina câmeras, radar e um mapa em um modelo da via. O agente trabalha somente com o que a percepção captura, pois as etapas seguintes não acessam o mundo diretamente. Uma lacuna na percepção permanece invisível para o restante do agente.
  • O raciocínio transforma uma percepção em uma decisão, e isso varia muito entre agentes. Um termostato compara a temperatura com um alvo e para por aí, enquanto um motor de xadrez busca milhões de jogadas e um carro autônomo executa uma política aprendida. Os agentes que você constrói aqui raciocinam chamando um modelo de linguagem, e quase tudo o que o curso acrescenta depois (ferramentas/memória/planejamento) se apoia nesse único passo.
  • A ação altera o ambiente para o próprio agente e para outros participantes. Pode ser tão pequena quanto acionar um relé ou tão complexa quanto conduzir um carro. Nas páginas seguintes, o código exposto ao modelo recebe o nome de ferramenta, pois, para o modelo, ele representa outra ação disponível. Chamar uma ferramenta significa solicitar que esse código seja executado como ação. O conjunto de ações também define o alcance máximo do agente: por melhor que seja o raciocínio, ele só afeta o mundo por meio das ações permitidas.
A etapa de raciocínio pode ser substituída. Percepção e ação não dependem da função de decisão usada entre elas. Uma regra simples, uma árvore de decisão, uma rotina de busca ou uma rede neural podem conduzir o mesmo ciclo. Manter o ciclo como uma estrutura fixa separa duas perguntas: qual é a capacidade do raciocínio e até onde as ações alcançam?

Os projetos clássicos de agentes diferem na etapa de decisão. O livro Artificial Intelligence: A Modern Approach, de Russell e Norvig, organiza esses projetos em um espectro que vai do agente reflexo a um agente de aprendizagem capaz de melhorar as próprias regras. O curso começa com lógica rígida e depois acrescenta um modelo de linguagem e contexto projetado, aproximando o ciclo de um agente orientado a objetivos e baseado em modelo. Nos módulos seguintes, o ciclo continua sobre um estado que muda, padrão que serve de base para agentes de aprendizagem.

Quatro arquiteturas de agente em ordem crescente de estrutura, de um agente reflexo que mapeia entradas diretamente em ações até um agente de aprendizado que reescreve as próprias regras. Adaptado de Artificial Intelligence: A Modern Approach, de Russell e Norvig ( Artificial Intelligence: A Modern Approach ).
Executar o menor ciclo de agente baseado em regras?

Um agente sem modelo de linguagem

A menor função de decisão é uma única instrução if. Aqui ela conduz uma pista unidimensional limitada por paredes nas posições 0 e 9. Pressione Run e observe a posição alternar entre as paredes enquanto o ciclo é executado.

Duas coisas que vale a pena examinar no código acima:

  • O ambiente (posições das paredes, posição atual) vive em state.env, enquanto as características intrínsecas do agente (sua direção) vivem em state.agent. Mantê-los separados significa que um agente diferente, com estado intrínseco diferente, pode operar no mesmo ambiente sem atrito.
  • O passo de raciocínio é uma única instrução if . Substituí-lo por algo mais poderoso, seja uma árvore de decisão, uma rede neural ou um modelo de linguagem, exige apenas mudar o que está entre a percepção e a ação. A estrutura do laço, a organização do estado e o passo de ação permanecem idênticos.

O que muda quando o raciocínio chama um LLM

Você chama a interface de chat-completions como qualquer outra função: entregue a ela uma lista de mensagens e um nome de modelo, e ela devolve uma mensagem do assistente mais metadados.

Sobre o chat(). É o wrapper fornecido pelo curso que você executa ao vivo um pouco mais adiante nesta página. O trecho abaixo prevê o formato de chamada e os campos que ele retorna, para que os nomes já sejam familiares quando você chegar à célula executável.
const reply = await chat({
  model:    "nvidia/nemotron-3.5-lightning-30b-a3b",
  messages: [{ role: "user", content: "Hi" }],
});
// reply.choices[0].message  → { content, reasoning_content }
// reply.choices[0].finish_reason → "stop" | "tool_calls" | "length"

Três fatos sobre essa função moldam como os agentes construídos sobre ela precisam funcionar:

Comparar onde as APIs mantêm o estado da conversa?

Este curso usa a Chat Completions API o tempo todo: você mantém a conversa como um array messages[] no seu próprio código e reenvia o array completo a cada turno. A mais recente Responses API pode, em vez disso, manter a thread no servidor, de modo que você envia apenas a nova entrada e uma referência ao turno anterior. De qualquer forma, o modelo permanece sem estado e inalterado entre as chamadas. A conversa vive fora dele, em um estado que seu código ou o servidor guarda.

As duas interfaces envolvem a mesma chamada sem estado. Elas diferem apenas em quem guarda a conversa entre os turnos.

Uma chamada de verdade, no seu navegador

Pressione Run para enviar uma única requisição. Ela se sustenta inteiramente sozinha, sem nenhum laço em volta e sem carregar nada de um turno anterior.

Inspecionar a solicitação e a resposta HTTP brutas?

O que o chat() realmente envia

chat() é um wrapper de conveniência em torno de um único POST HTTP comum no formato de transmissão compatível com a OpenAI. Essa requisição carrega três coisas:

  • o endpoint para onde enviar,
  • os cabeçalhos da solicitação; um endpoint personalizado pode exigir um cabeçalho Authorization,
  • e um corpo JSON com model e messages.

A célula abaixo monta essa chamada manualmente. Abra request para examinar a URL, os cabeçalhos e o corpo, com qualquer valor de autorização oculto. Abra raw response para examinar o objeto completo retornado por chat().

O endpoint do modelo usa esse formato. O gateway do OpenClaw do módulo 3 expõe um protocolo separado para turnos do agente, sessões e operações do ambiente de execução.

Configure um endpoint compatível no painel do modelo antes de executar a célula. Os endpoints hospedados pela NVIDIA exigem uma chave de API da NVIDIA. Confira o acesso e a cota do serviço selecionado. O painel mostra o endpoint ativo e as configurações de credenciais; examine a solicitação abaixo, com os dados sensíveis ocultos, antes de enviá-la.

A rota selecionada determina qual serviço recebe a solicitação e sua credencial. Uma chamada pelo navegador exige que o endpoint permita a origem do curso. O curso pode usar seu serviço de retransmissão configurado quando o provedor não permite essa solicitação direta pelo navegador. Examine a rota ativa e os cabeçalhos da solicitação no painel do modelo.

Examine o helper de streaming. chatStream() processa o texto da resposta, qualquer texto de raciocínio retornado, os metadados de uso e o sinal de fim da transmissão. Ele conecta a resposta ao painel da lição e ao botão Stop. Abra o código-fonte do helper pelo menu da célula para examinar a solicitação e o tratamento de eventos.
Comparar formas de raciocinar sobre o labirinto dentro de um ciclo fixo?

Trocar a função de decisão sem alterar o ciclo

Os próximos exemplos mantêm o ciclo de perceber, raciocinar e agir e variam sua função de decisão. Compare regras fixas e algoritmos de busca antes de usar chat() para escolher um movimento.

Execute os nós em ordem. Cada um aplica uma regra de decisão diferente ao mesmo ciclo que resolve o labirinto:

  • A regra constante "sempre leste" alcança o objetivo em um corredor reto, depois trava na primeira parede do labirinto, já que um rumo fixo não consegue virar.
  • A busca em profundidade (DFS) segue um ramo até o fim antes de voltar.
  • A busca em largura (BFS) explora a fronteira por níveis e encontra o caminho mais curto em uma grade sem pesos.
  • O A* usa uma heurística de distância para priorizar caminhos promissores sem perder a garantia de menor caminho.
Somente a etapa de decisão varia. DFS, BFS e A* leem o estado atual do labirinto e devolvem um movimento. Uma linha no último nó escolhe a função, enquanto o ciclo abaixo permanece igual para cada escolha. No próximo exemplo, o modelo escolhe entre ramificações enquanto um controlador registra as células exploradas e o caminho de volta.

Como usar um modelo de linguagem para escolher movimentos

O controlador registra as células visitadas e um caminho de volta, filtra os ramos visitados e percorre os corredores. Nas bifurcações, o modelo lê o mapa e escolhe a ordem dos ramos com choose_direction. O controlador gerencia a exploração em profundidade; ele não fornece ao modelo uma rota resolvida.

Execute as células nesta ordem e depois altere um controle por vez:

  1. Comece pelo nó do mecanismo. Ele exporta os utilitários e o resolvedor compartilhado state.runMaze, que percorre corredores automaticamente e chama o modelo somente nas bifurcações.
  2. Execute o nó editável do agente de labirinto abaixo. DIRECTIVE é a instrução central do sistema; o objeto de opções controla o modelo, o tamanho do labirinto, o mapa textual, o histórico de movimentos, a trilha de coordenadas e a repetição do schema da ferramenta.
  3. Comece com os padrões funcionais. Depois, altere model para comparar rotas com capacidades verificadas, remova o histórico ou defina advanced para ampliar o labirinto quando o caso simples funcionar.
Valide a ação solicitada. O esquema de choose_direction declara os valores de direção permitidos. O modelo solicita uma direção, e o controlador verifica o nome da ferramenta e os argumentos antes de mover. Examine a solicitação e a resposta para distinguir o esquema declarado da validação feita pelo seu código.

O ciclo em detalhe

No exemplo do labirinto, o controlador monta uma solicitação para chat() e valida o movimento retornado antes de aplicá-lo. As etapas abaixo mostram essa troca.

  • Amostrar localmente. Seu código lê uma parte do ambiente. Aqui ele lê a célula atual do labirinto e seus movimentos válidos. A solicitação também pode incluir o mapa completo e os turnos anteriores, dependendo dos controles selecionados.
  • Perceber localmente. Essa parte é incorporada a um contexto completo e preparado: o prompt de sistema, o histórico acumulado de messages[], os resultados anteriores de ferramentas e a parte que você acabou de amostrar. Neste exemplo, o labirinto é representado como texto nas mensagens enviadas ao modelo.
  • Agir localmente. O modelo mapeia esse texto em mais texto: um sinal de intenção, idealmente uma chamada de ferramenta tipada como { "move": "east" } em vez de prosa livre. A intenção apenas solicita uma ação, e nunca executa uma. Seu código a lê e aplica uma atualização limitada ao ambiente (doMove(...)), validando-a primeiro.
  • Impactar localmente. A atualização muda o mundo. Nada permanece dentro do modelo. O estado durável está no ambiente e no contexto que o código reconstruirá. No turno seguinte, a amostragem local lê o mundo alterado e o ciclo recomeça.

Neste exemplo, chat() recebe texto que descreve o labirinto e retorna uma solicitação de movimento. O controlador fornece as observações, valida a solicitação e altera o estado do labirinto. A chamada ao modelo não executa o movimento.

Examine os dois limites: o contexto fornecido ao modelo e a validação que seu código realiza antes de aplicar uma ação solicitada.

amostrar → perceber → (texto → texto) → agir → impactar
A solicitação do labirinto pode incluir o mapa completo e os turnos anteriores. Abra os detalhes da solicitação para ver qual contexto está presente. O módulo 1b constrói o loop de ferramentas com um array explícito de mensagens.

Antes de continuar

Cada pergunta pode ser respondida ajustando um controle na célula do labirinto-LLM acima e rodando de novo.

  1. Compare o histórico de conversa. Defina includeHistory:false e execute novamente com o mesmo perfil e labirinto. Compare a ordem dos ramos, as decisões nas bifurcações e o tempo decorrido com o histórico ativado. O controlador mantém as células visitadas e o caminho de volta nas duas execuções.
  2. Remova a dica de estratégia de DIRECTIVE. Apague a linha que recomenda preferir ramos não explorados a células visitadas e execute novamente com o mesmo perfil e labirinto. Compare a ordem dos ramos, as decisões nas bifurcações e o tempo decorrido. O controlador continua filtrando os ramos visitados; repita as execuções para verificar se alguma diferença persiste.
  3. Compare perfis de modelo. Comece com model:"direct" e depois compare model:"reasoning" e model:"omni" no mesmo labirinto. Examine o modelo, o orçamento de tokens, a temperatura e as configurações de raciocínio de cada solicitação. Esses perfis alteram várias configurações; compare a ordem dos ramos e a latência sem atribuir toda diferença apenas à identidade do modelo.

Experimente · compare o histórico de conversa

Este chat começa com o histórico de conversa ativado. Diga seu nome e depois pergunte qual é o seu nome. Desative o controle de memória e pergunte novamente. Cada chamada a chat() recebe as mensagens montadas pela interface; com a memória desativada, os turnos anteriores são omitidos. Compare as respostas e examine como o código monta a solicitação.

← Configuração