LangGraph e LangChain: Seu Primeiro ReAct Agent com Tools
Nesta jornada, vamos unir tudo o que aprendemos até agora para construir nosso primeiro ReAct Agent usando LangGraph e LangChain.
Nesta jornada, vamos unir tudo o que aprendemos até agora para construir nosso primeiro ReAct Agent usando LangGraph e LangChain. Se você ainda não ouviu falar sobre ReAct Agents, prepare-se: este é o futuro da interação com IAs.
O que é um ReAct Agent?
Um ReAct Agent (Reasoning and Acting Agent) é um tipo de agente de IA que não apenas gera respostas, mas também pode raciocinar sobre um problema e agir para resolvê-lo. Isso é feito através do uso de “tools” (ferramentas), que são, na essência, funções Python que o agente pode decidir chamar para obter informações ou executar tarefas.
Imagine um assistente que, ao invés de apenas responder “eu não sei a cotação do dólar”, pode ativamente buscar essa informação em tempo real usando uma ferramenta de busca na internet. É exatamente isso que vamos construir.
Em vídeo
Abaixo, fiz um vídeo bem detalhado sobre ReAct Agent:
Para acompanhar toda a playlist gratuita, seguem os links:
A Arquitetura do Nosso Agente
Antes de mergulhar no código, vamos visualizar a estrutura do nosso agente em LangGraph. Um grafo em LangGraph é composto por “nodes” (nós) e “edges” (arestas).
Nosso agente terá a seguinte arquitetura básica:
LLM Node (
call_llm): Este é o cérebro do nosso agente. Ele recebe a pergunta do usuário e decide o que fazer. A resposta pode ser um texto direto ou a decisão de chamar uma ferramenta.Tool Node (
tool_node): Se o LLM decidir que precisa de uma ferramenta, a execução é direcionada para este nó. Ele executa a ferramenta solicitada (por exemplo, uma calculadora) e captura o resultado.Conditional Edge (Router): Esta é a parte crucial. Após o LLM Node, uma aresta condicional (nosso
router) decide o próximo passo:Se o LLM forneceu uma resposta final, o grafo termina (
__end__).Se o LLM decidiu chamar uma ferramenta, o grafo vai para o
tool_node.
O mais interessante é o que acontece depois do tool_node: ele não vai para o final!
O resultado da ferramenta é injetado de volta no LLM Node, criando um loop. O LLM recebe o resultado e pode então usar essa nova informação para formular a resposta final ou até mesmo chamar outra ferramenta em sequência.
Isso permite que o agente execute tarefas complexas em múltiplos passos, como “calcule 2x2 e depois multiplique o resultado por 5”.
Estruturando o Projeto
Para manter nosso código organizado, vamos dividi-lo em alguns arquivos:
utils.py: Funções utilitárias, como a inicialização do nosso modelo de linguagem (LLM).tools.py: Definição das nossas ferramentas. Começaremos com uma ferramenta simples de multiplicação.state.py: Definição do estado do nosso grafo, que passará as mensagens entre os nós.prompts.py: Armazenará nossos system prompts.graph.py: Onde a mágica acontece! Aqui construiremos nosso grafo LangGraph com os nós e arestas.main.py: O ponto de entrada da nossa aplicação, onde interagimos com o agente.
Mão na Massa: O Código
Vamos ver como implementar isso em Python.
1. A Ferramenta (tools.py)
Primeiro, definimos nossa ferramenta. Usaremos a decorator @tool do LangChain para criar uma ferramenta de multiplicação simples.
from langchain.tools import BaseTool, tool
@tool
def multiply(a: float, b: float) -> float:
“”“Multiply a * b and returns the result
Args:
a: float multiplicand
b: float multiplier
Returns:
the resulting float of the equation a * b
“”“
return a * b
TOOLS: list[BaseTool] = [multiply]
TOOLS_BY_NAME: dict[str, BaseTool] = {tool.name: tool for tool in TOOLS}
2. O Estado (state.py)
O estado é a memória do nosso grafo. Ele manterá a lista de mensagens trocadas. Usamos TypedDict e Annotated para isso.
from collections.abc import Sequence
from typing import Annotated, TypedDict
from langgraph.graph.message import BaseMessage, add_messages
class State(TypedDict):
messages: Annotated[Sequence[BaseMessage], add_messages]
O add_messages é o o reducer que falamos várias vezes nas outras aulas.
3. O Grafo (graph.py)
Aqui construímos a lógica do nosso agente.
from typing import Literal
from langchain_core.messages import AIMessage, ToolMessage
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.constants import START
from langgraph.graph.state import CompiledStateGraph, StateGraph
from pydantic import ValidationError
from examples.ex006.state import State
from examples.ex006.tools import TOOLS, TOOLS_BY_NAME
from examples.ex006.utils import load_llm
def call_llm(state: State) -> State:
print(”> call llm”)
llm_with_tools = load_llm().bind_tools(TOOLS)
result = llm_with_tools.invoke(state[”messages”])
return {”messages”: [result]}
def tool_node(state: State) -> State:
print(”> tool node”)
llm_response = state[”messages”][-1]
if not isinstance(llm_response, AIMessage) or not getattr(
llm_response, “tool_calls”, None
):
return state
call = llm_response.tool_calls[-1]
name, args, id_ = call[”name”], call[”args”], call[”id”]
try:
content = TOOLS_BY_NAME[name].invoke(args)
status = “success”
except (KeyError, IndexError, TypeError, ValidationError, ValueError) as error:
content = f”Please, fix your mistakes: {error}”
status = “error”
tool_message = ToolMessage(content=content, tool_call_id=id_, status=status)
return {”messages”: [tool_message]}
def router(state: State) -> Literal[”tool_node”, “__end__”]:
print(”> router”)
llm_response = state[”messages”][-1]
if getattr(llm_response, “tool_calls”, None):
return “tool_node”
return “__end__”
def build_graph() -> CompiledStateGraph[State, None, State, State]:
builder = StateGraph(State)
builder.add_node(”call_llm”, call_llm)
builder.add_node(”tool_node”, tool_node)
builder.add_edge(START, “call_llm”)
builder.add_conditional_edges(”call_llm”, router, [”tool_node”, “__end__”])
builder.add_edge(”tool_node”, “call_llm”)
return builder.compile(checkpointer=InMemorySaver())
4. O Loop Principal (main.py)
Finalmente, criamos um loop para conversar com nosso agente.
from langchain_core.messages import BaseMessage, HumanMessage, SystemMessage
from langgraph.graph.state import RunnableConfig
from rich import print
from rich.markdown import Markdown
from rich.prompt import Prompt
from examples.ex006.graph import build_graph
from examples.ex006.prompts import SYSTEM_PROMPT
def main() -> None:
graph = build_graph()
config = RunnableConfig(configurable={”thread_id”: 1})
all_messages: list[BaseMessage] = []
prompt = Prompt()
Prompt.prompt_suffix = “”
while True:
user_input = prompt.ask(”[bold cyan]Você: \n”)
print(Markdown(”\n\n --- \n\n”))
if user_input.lower() in [”q”, “quit”]:
break
human_message = HumanMessage(user_input)
current_loop_messages = [human_message]
if len(all_messages) == 0:
current_loop_messages = [SystemMessage(SYSTEM_PROMPT), human_message]
result = graph.invoke({”messages”: current_loop_messages}, config=config)
print(”[bold cyan]RESPOSTA: \n”)
print(Markdown(result[”messages”][-1].content))
print(Markdown(”\n\n --- \n\n”))
all_messages = result[”messages”]
print(all_messages)
if __name__ == “__main__”:
main()
O Poder em Ação
Ao executar o main.py, você pode interagir com o agente.
Você:
Olá!IA:
Olá! Como posso ajudar você hoje?
Neste caso, o router viu que não havia tool_calls e foi direto para o END.
Agora, vamos usar a ferramenta:
Você:
quanto é 123 * 456?IA:
O resultado de 123 multiplicado por 456 é 56088.
O que aconteceu aqui?
O
call_llmrecebeu a pergunta e, em vez de responder, gerou umtool_callpara a funçãomultiply.O
routerdetectou otool_calle direcionou a execução para otool_node.O
tool_nodeexecutou a multiplicação e gerou umaToolMessagecom o resultado.O grafo voltou para o
call_llm, agora com o histórico da conversa E o resultado da ferramenta.O LLM usou o resultado para formular a resposta final para você.
E o mais incrível é que ele pode fazer isso em múltiplos passos:
Você:
quanto é 2.13 vezes 3.12 e pega o resultado disso e multiplica por 2?
O agente chamará a ferramenta multiply duas vezes em sequência para chegar ao resultado final, demonstrando sua capacidade de raciocínio e ação em cadeia.
Este é apenas o começo do que é possível com ReAct Agents e LangGraph. A partir daqui, você pode adicionar mais ferramentas, como buscas na web, acesso a bancos de dados ou o que mais sua imaginação permitir.
Espero que você tenha se animado para construir seus próprios agentes. Comente aí: “Eu fiz o meu primeiro ReAct Agent”!
Concluindo
Se ainda não viu o vídeo, segue novamente.



