Bom, se você chegou até aqui, tenho um pedido. Você pode me ajudar comprando o curso Preciso que você aguente mais alguns posts e, aí sim, vamos ter o nosso Xabiro.

Poderia ter feito um vídeo? Sim, mas eu sou horrível nisso. Já tentei, pode ver no TikTok. Prefiro ficar na escrita, no meu blog. Afinal, estou dentro de um espaço seguro

O que é estar seguro?

Onde eu não habilito os comentários, e eu posso deletar, caso estejam habilitados, 😂.

Brincadeiras à parte, essa série de posts é para mostrar o que aprendi no boot.dev de uma maneira incrementada. Super recomendo todos os cursos de lá.

Atenção

É importante ressaltar que, para fins didáticos, não pretendo colocar nenhum rigor científico nas explicações . Até porque não conseguiria fazer isso se fosse necessário, hahaha. Mas, a partir desta postagem, todas as definições estarão associadas à fonte de onde a informação foi retirada.

Tá, sem mais delongas, vamos começar o nosso agente.

O que é um agente?

Definição de agente

An Agent is a system that leverages an AI model to interact with its environment in order to achieve a user-defined objective. It combines reasoning, planning, and the execution of actions (often via external tools) to fulfill tasks. 1

Do que foi apresentado, podemos inferir que um agente nada mais é do que um sistema composto de duas partes:

  • Uma responsável por decidir qual ação tomar dada uma determinada situação;
  • Outra responsável por delimitar as ações que o sistema pode realizar (o conjunto de ferramentas).

Você deve estar pensando

Legal, Caíque! Você traduziu o hugging face

De fato, mas você já parou para pensar sobre isso? Por exemplo, como o agente percebe o ambiente? Como ele “raciocina”? Como ele executa uma ação em sequência?

Preparando o almoço

Tá, vamos fazer uma comparação de como nós realizamos as coisas.

Imagina que você tá lá cozinhando teu almoço. Entre uma série de ações que temos de realizar, acabamos utilizando a linguagem para ter um senso de progresso. Você já se pegou pensando ou falando algo como:

Antes de colocar o arroz no fogo, eu preciso aquecer a água

Ou

Mandei açúcar no lugar do sal. Fodeu. Vou ter que fazer arroz doce.

Ou até

Beleza, coloquei a água, o arroz e o sal. Mas era assim que precisava fazer?

Todos esses exemplos foram necessários para mostrar que existe uma relação entre agir e pensar que nos permite aprender ou executar tarefas mesmo em situações antes desconhecidas 2.

Uma “voz” interna

Os exemplos que foram fornecidos geralmente são feitos naqueles monólogos que temos. Nos agentes, nós realizamos isso através do Thought-Action-Observation Loop.

Essa técnica é um processo estruturado que permite que a LLM faça iterativamente:

  • Thought: Aqui é onde o “cérebro” do agente escolhe qual a próxima ação;
  • Action: Aqui é onde o “agente” acessa as suas ferramentas e executa a ação;
  • Observation: Aqui é onde o modelo “reflete” sobre a resposta da ação tomada.

Esse ciclo continua até que o modelo convirja para a solução que complete uma tarefa. Fica a cargo do leitor a prova da convergência do resultado…

Se você conhece essa frase

Ah, o Boulos! Não, não estou falando do Boulos político. Aqui me refiro ao autor do livro de Geometria Analítica que já tirou o sono de alguns leitores do livro no primeiro período de algum curso de exatas com as frases que começavam com “É fácil perceber…” ou “Fica a cargo do leitor…”.

Você é foda. Acabei de usar a frase, e que delícia!

É nesse momento que você deve estar no monólogo interno:

Pra que tudo isso?

Tudo isso é o que nos guiará na construção do System Prompt. Em muitos frameworks (Agnos, Lang Graph, Smolagents), as regras e as guidelines são injetadas diretamente no system_prompt, o que garante que toda iteração no ciclo siga a mesma lógica.

Antes de prosseguirmos para a criação do nosso prompt, vou tentar resumir o que falamos até agora através da tabela do Hugging Face [ˆ3].

Agency LevelDescriçãoO nome do bonitoExemplo
☆☆☆A saída do agente não tem impacto no fluxo do programaSimple processorprocess_llm_output(llm_response)
★☆☆A saída do agente determina o fluxo de controle básicRouterif llm_decision(): path_a() else: path_b()
★★☆A saída do agente determina a execução de funçõesTool callerrun_function(llm_chosen_tool, llm_chosen_args)
★★★A saída do agente controla a iteração e a continuação do programaMulti-step Agentwhile llm_should_continue(): execute_next_step()
★★★Um fluxo agêntico inicia outro fluxo agênticoMulti-Agentif llm_trigger(): execute_agent()

Codificando nosso Prompt

Como a configuração do Xabiro é feita a partir de um yaml, temos de ajustar o nosso valor default no constants.py

from typing import Dict, Any
 
CONFIG_FILE_NAME: str = "xabiro.yaml"
DEFAULT_CONFIG: Dict[str, Any] = {
	"max_steps": 10,
	"tools": [
		{
			"name": "planner",
			"description": "Usado para decompor tarefas complexas e criar a sequência de passos."
		},
		{
			"name": "file_manager",
			"description": "Gerencia a criação, leitura e escrita de arquivos no projeto."
		}
	],
	"prompt": {
		"value": (
			"Você é o agente de código pessoal Xabironelson. Sua tarefa é ajudar o usuário a escrever, revisar e depurar código.\n"
			"Siga o ciclo de raciocínio (Thought) e ação (Action) até a tarefa ser concluída ou o número máximo de passos ser atingido.\n\n"
			"# REGRAS\n"
			"1. **PENSAMENTO (Thought):** Sempre comece seu turno com um bloco 'Thought'. Descreva seu raciocínio, o plano atual, o passo a ser executado e por que a ferramenta foi escolhida.\n"
			"2. **AÇÃO (Action):** Após o Thought, use a sintaxe 'Action: nome_da_ferramenta(argumentos)' para executar uma ação.\n"
			"3. **RESPOSTA FINAL (Final Answer):** Quando a tarefa estiver 100% concluída, use a sintaxe 'Final Answer: sua resposta final para o usuário'.\n\n"
			"## FERRAMENTAS DISPONÍVEIS\n"
			"1. planner: Usado para decompor tarefas complexas e criar a sequência de passos.\n"
			"2. Nenhuma outra ferramenta está disponível ainda. (Em breve: file_manager, code_executor, etc.)\n\n"
			"## EXEMPLO DO CICLO\n"
			"Thought: A tarefa é 'Criar um plano para um app de lista de tarefas'. Primeiro, usarei o planner.\n"
			"Action: planner(tarefa='Criar plano para app de lista de tarefas')\n"
		),
		"metadata": {
			"version": "1.0",
			"description": "A prompt to guide the multi-step agent using the Thought-Action-Observation loop."
		}
	},
	"llm": {
		"model": "gpt-4",
		"temperature": 0.7,
		"max_tokens": 1500,
	}
}

Se você notou, além do novo modelo de prompt, adicionamos o versionamento dele. Isso vai permitir que tenhamos um controle de como o Prompt está se comportando e aplicar algumas técnicas de deploy.

Além disso, note que alteramos um pouco como modelamos as nossas ferramentas. A ideia é que façamos essas pequenas modificações no curso do projeto.

Modelando as nossas entidades

Vamos usar o bom e velho UML para modelarmos nossas classes antes de codificarmos.

classDiagram
    class AgentConfig {
        +int max_steps
        +List<Tool> tools
        +PromptConfig prompt
        +LLMConfig llm
    }

    class Tool {
        +str name
        +str description
    }

    class PromptConfig {
        +str value
        +PromptMetadata metadata
    }

    class PromptMetadata {
        +str version
        +str description
    }

    class LLMConfig {
        +str model
        +float temperature
        +int max_tokens
    }

Isso dai, em Python, daria algo do tipo

from typing import List
from pydantic import BaseModel, Field
 
 
class PromptMetadata(BaseModel):
    """Metadados do prompt, permitindo versionamento e descrição."""
 
    version: str = Field(
        ..., description="Versão do prompt, para controle de mudanças."
    )
    description: str = Field(..., description="Descrição da finalidade deste prompt.")
 
 
class LLMConfig(BaseModel):
    """Configurações de parâmetros de chamada para a LLM."""
 
    model: str = Field("gpt-4", description="Nome do modelo de LLM a ser utilizado.")
    temperature: float = Field(
        0.7, description="Temperatura de amostragem da LLM (0.0 a 2.0)."
    )
    max_tokens: int = Field(
        1500, description="Limite máximo de tokens para a resposta da LLM."
    )
    api_key_env: str = Field(
        "LLM_API_KEY",
        description="Nome da variável de ambiente que contém a chave API.",
    )
 
 
class Tool(BaseModel):
    """Representa uma única ferramenta que o agente pode utilizar."""
 
    name: str = Field(
        ..., description="Nome de invocação da ferramenta (ex: 'file_manager')."
    )
    description: str = Field(
        ..., description="Descrição detalhada da ferramenta para o raciocínio da LLM."
    )
 
 
class PromptConfig(BaseModel):
    """Contém o valor (a string do prompt) e seus metadados."""
 
    value: str = Field(..., description="O corpo do system_prompt injetado na LLM.")
    metadata: PromptMetadata = Field(
        ..., description="Metadados do prompt, incluindo a versão."
    )
 
 
class AgentConfig(BaseModel):
    """Modelo de configuração raiz para toda a aplicação do agente."""
 
    max_steps: int = Field(
        10, description="Número máximo de passos no ciclo Thought-Action-Observation."
    )
    tools: List[Tool] = Field(
        ..., description="Lista de ferramentas disponíveis para o agente."
    )
    prompt: PromptConfig = Field(
        ..., description="Configurações e valor do prompt de sistema."
    )
    llm: LLMConfig = Field(
        ..., description="Configurações específicas do modelo de linguagem."
    )

Depois de tudo isso feito, basta invocar:

AgentConfig.model_validate(config_data)

E ta feito o danoninho.

Má que caralh*

Até aqui fizemos a configuração inicial do nosso agente. A partir do próximo post, iremos para a camada que será responsável por abstrair a interação com as APIs

Lembra do dilema do Make vs. Buy? Então, em relação a essa decisão, vamos utilizar o LiteLLM para dar um speed e termos como fazer as nossas primeiras interações com os modelos.

Má isso aí é papo para outra hora!

Referências

Footnotes

    • YAO, Shunyu et al. ReAct: Synergizing Reasoning and Acting in Language Models. [S.l.]: Cornell University, 2022. Disponível em: https://arxiv.org/pdf/2210.03629. Acesso em: 8 out. 2025.