Olá! Bem-vindo ao curso de protocolos para Construção de Agentes Inteligentes: MCP, A2A, AG-UI e BFA. Meu nome é Michael Douglas, mas a comunidade me conhece como MD. Gosto de usar alguns termos da comunidade, como "IAZeiros" para quebrar o gelo. Compartilho muitas coisas e sinta-se à vontade para entrar em contato comigo. Estou contando um pouco sobre minha vida para que conheçam o instrutor do curso. Acredito que é importante esse ponto, já que vocês passarão uma jornada comigo na construção de um agente que chamaremos de MD Bank.
Para toda essa jornada, acho que é bom fazermos essa introdução e nos conhecermos. Estou compartilhando um pouco da minha vida pessoal e algumas coisas que gosto de fazer fora do ambiente de trabalho. Atualmente, trabalho no Itaú, na parte de investimentos, na construção de agentes de IA generativa para atendimento ao cliente, focando na materialização da gestão de patrimônio.
Por que fazer este curso? Quero compartilhar um pouco da minha experiência e do que venho trabalhando no dia a dia, mostrar os protocolos e fazer com que entendam o que pretendemos aplicar aqui. Espero que também possam aplicar isso no dia a dia de vocês e aprender com o que será ensinado. Preparei este conteúdo para que acompanhem comigo o meu dia a dia e que pode ser tornar o seu.
Vocês aprenderão a criar a camada de agentes aqui no curso. Vamos desenvolver um agente bancário chamado MD Bank. Vocês aprenderão a criar os agentes de abertura de conta, cartão de crédito com MCP, A2A, AG-UI e BFA. Além disso, você irá aprender a criar um front-end com Streamlit e, posteriormente, um front-end com React, utilizando a GUI.
Neste curso, vamos aprender a configurar nosso servidor MCP. Também aprenderemos a construir uma camada supervisora, que será responsável por receber os textos do MD Bank e exibi-los. Todo o nosso projeto será iniciado a partir deste Docker Compose. Tudo o que realizarmos aqui seguirá uma arquitetura de referência para o nosso projeto. Vamos abrir o projeto para visualizar nossa construção.
Aprenderemos desde o início, a construção de agentes profissionais e prontos para produção com os protocolos mais famosos de mercado.
Nós veremos juntos o que construiremos e veremos como é incrível o nosso agente MDBank!
Vamos em frente!
Como a ideia do nosso curso é ser prático, vamos iniciar escolhendo um caso. O caso escolhido é um banco, e vamos criar um agente bancário fictício chamado MD Bank. A primeira parte do nosso projeto será entender, de forma ilustrada, o que um cliente nos solicitou. Obviamente, o cliente não nos perguntará, como pessoas engenheiras de IA, qual arquitetura escolher para nosso agente. Ele simplesmente apresentará o problema.
Imaginando esse cenário, nosso cliente poderia dizer: "Gostaria de um agente bancário onde a pessoa pudesse, por exemplo, em um estilo GPT, enviar um texto e esse agente tentasse, por exemplo, abrir uma conta, solicitar um cartão de crédito e direcionar para o atendimento do banco." Dado esse contexto básico, pediríamos muitos mais detalhes sobre o banco, mas vamos começar escolhendo essa porta de entrada para o MD Bank.
Antes de escolher o estilo de arquitetura, seja multi-agente ou single agent, gosto de apresentar uma comparação entre agente único e multi-agente. Por isso, temos uma imagem mostrando a entrada, onde ilustramos um cachorro, e ao final pedimos a uma rede neural que nos diga se é um cachorro. Muitas vezes, ao iniciar um projeto de agente, é importante lembrar que tudo reflete um percurso. Se o projeto reflete o MD Bank, que é um banco, teremos uma entrada, que seria um texto, e esperamos como saída uma avaliação determinando o caminho para onde queremos que o cliente vá. Tudo isso depende de um modelo.
Ao criar um agente, utilizaremos LinkedIn, que solicitará um modelo. Esses modelos, conhecidos como modelos de linguagem grande, são executados usando redes neurais. A capacidade desse modelo é entender a entrada do texto, que chamamos de Token e depois Embed, de forma matemática, não textual. Isso gera diversas bifurcações no banco, onde podemos cair em diferentes lugares.
Dependendo do projeto, o estilo chamado Single Agent, ou agente único, pode ser entendido como uma arquitetura de agente único. O papel desse agente único é ajudar uma pessoa com questões do banco. Basicamente, esse agente atua como um agente de suporte, respondendo perguntas. Não entraremos ainda na questão de recursos, que são as ferramentas, pois teremos uma aula especial sobre isso. Aqui, focaremos apenas na parte do agente, que ajuda uma pessoa.
Esse agente de suporte pode tomar diferentes caminhos para o cliente, e esses caminhos, dependendo do crescimento do projeto, podem resultar em decisões de engenharia não muito favoráveis. No dia a dia, sem aplicar questões de engenharia de IA, mas sim de engenharia de software, poderíamos até usar o termo "monolito" para descrever nosso agente. No entanto, isso não significa uma decisão ruim de arquitetura, pois depende de cada caso. Em determinado momento, um agente único pode fazer sentido, sem necessidade de divisão em vários agentes ou domínios de entendimento.
Por se tratar de um projeto bancário, pode ser interessante dividir esses entendimentos. No MD Bank, seria interessante ter uma camada ou pasta com um agente especialista em cartão de crédito e outro em abertura de conta. Esses percursos são longos e complexos, e manter uma arquitetura de agente único poderia resultar em um monolito modular. Novamente, isso não é necessariamente ruim, pois depende de cada caso. Para nosso projeto, dada a volumetria desejada, escolhemos a arquitetura estilo multi-agente.
Então, isso nos remete a ter um agente que receberá o cliente, e seu papel é entender se a pessoa deseja uma cartão de crédito, abrir uma conta ou qualquer outra necessidade, podendo até ser suporte. Esse é o seu papel. Após essa decisão, o cliente será encaminhado para o agente de domínio que possui o conhecimento necessário. Ou seja, se for sobre cartão de crédito, encaminharemos para um subagente, ou utilizaremos outras técnicas de arquitetura para cada agente.
Na documentação da LangChain, ao rolarmos um pouco, chegaremos às arquiteturas estilo multi-agente. Cada uma dessas arquiteturas representa uma capacidade, uma forma de construir nossos agentes. Se escolhermos uma de subagente, estamos dizendo que o agente principal depende dos subagentes para responder. Em muitos casos, precisa do agente A, do agente B e do C para dar uma resposta. Ou, às vezes, pode ser apenas o agente A. Esse estilo de arquitetura é onde temos uma divisão de decisões, mas que necessita de seus subagentes para executar.
Existem outros padrões, não vamos passar por todos agora, mas vamos abrir outro, que é do estilo de roteamento. Esse roteamento decide para onde encaminhar, como se fosse uma rota que estamos acostumados a fazer no dia a dia, e combina a resposta para devolvê-la. Podemos ir ao agente A, depois ao B, depois ao C, sintetizar todas essas respostas e combiná-las. No caso do subagente, não há um sintetizador, então passa por agentes que têm contextos isolados, como podemos ver na documentação: cada um possui um contexto, o que implica muita engenharia de contexto, sobre a qual também falaremos.
Dado todo esse contexto e entendimento, podemos passar ao design conceitual da nossa arquitetura do agente MDB. Imagine que, juntos, estaremos construindo o agente. Mas, antes de tudo, precisamos desenhar essa arquitetura, precisamos visualizá-la, saber o que vai acontecer no MDB.
Dado isso, o primeiro de todos os agentes, se não for multimodal, ou seja, se não tiver vídeo e áudio, mas considerarmos apenas como texto, a primeira questão é: se chega um texto, o que fazemos com ele? Essa é a primeira pergunta que devemos nos fazer sobre nossa arquitetura. Esse texto deveria executar um modelo para tomar uma decisão? E essa decisão já é a resposta para nosso cliente? Esse é um ponto inicial que devemos considerar. Se gostaríamos que aqui já estivesse nossa resposta, então colocaremos a resposta na tela, que seria nossa saída. Nosso modelo dá uma saída que remete a uma resposta.
Podemos começar a nos orientar para o que gostaríamos, que já não é chamar isso de modelo e saída, mas sim de um decisor ou um roteador. Lembramos que vimos que pode ser um roteador, um subagente, ou até mesmo skills (habilidades), que também veremos a seguir.
Dado esse primeiro aspecto de decisão da nossa arquitetura do MD Bank, o que já definimos? Inicialmente, vamos utilizar roteamento. Por quê? Porque queremos delimitar domínios em nosso projeto. Que domínio é esse do MD? O domínio é cartão de crédito, por exemplo. Teremos aqui a abertura de conta. Também podemos ter um suporte ao cliente, então colocaremos como suporte ao cliente.
Qual é o papel do nosso roteador na arquitetura do nosso projeto? É decidir o seguinte: quando chega um texto, vamos fazer isso juntos. Quando chega um texto do tipo "quero abrir uma conta", vamos colocar "quero abrir uma conta". Olhando para isso e deixando de lado a questão gerativa, se fosse uma situação cotidiana, o que diríamos a esse cliente que enviou essa pergunta? A questão de abrir conta deveria ir para um fluxo específico. Chamaremos isso de fluxo 1. Se nosso cliente diz "quero um cartão de crédito agora", então iremos para outro fluxo. Nesse caso, por querer um cartão de crédito, iremos ao roteamento e diremos que entendemos que a pessoa quer um cartão de crédito, então isso seria o fluxo 2. No fluxo 2, entendemos que a pessoa deve ser direcionada para cartão de crédito.
Neste primeiro vídeo, já começamos a perceber algo. Se queremos um cartão de crédito, qual é a primeira pergunta que pode vir à mente? A nossa foi: se queremos um cartão de crédito, temos uma conta? Então, já temos uma questão aqui. Nosso roteador não deveria estar buscando um recurso? Que recurso é esse? Conta: se a pessoa tem uma conta, antes de mais nada. Queremos deixar isso em mente, para que comecemos a pensar juntos. Na próxima aula, desmembramos mais nosso design e começaremos a falar sobre tools (ferramentas), que são esses recursos de decisão do nosso projeto. Vamos encerrar o vídeo por aqui e esperamos vocês na próxima aula, onde falaremos sobre tools.
Vamos colocar em prática a arquitetura que desenvolvemos. Para que o vídeo não fique muito longo, já preparamos o código, que estará disponível para download. Vamos copiar, colar e explicar o que estamos fazendo. Ao final, teremos nosso front-end, escrito em Streamlit, mostrando o resultado do nosso agente.
Vamos começar criando um arquivo docker-compose, que será responsável por levantar nosso projeto. Inicialmente, colocamos os serviços que vamos utilizar. O primeiro é o Supervisor, que supervisiona nossos agentes e decide como executá-los. Neste vídeo, deixaremos os agentes, tanto o Supervisor quanto o Sub, dentro do mesmo script. No próximo vídeo, moveremos esses agentes para seus locais definitivos, mas nesta primeira versão, não há problema.
Aqui está o trecho do docker-compose que define os serviços:
services:
supervisor:
build: ./supervisor
container_name: mdbank_supervisor_agents
ports:
- "8080:8000"
volumes:
- ./supervisor:/app
frontend:
build: ./frontend
container_name: mdbank_frontend
ports:
- "9090:9090"
volumes:
- ./frontend:/app
Já temos um front-end, que será responsável por mostrar o resultado do nosso projeto. Vamos criar uma pasta chamada "Supervisor" para manter a didática do curso. Talvez fosse interessante chamá-la de "mdbank", mas manteremos esse nome. Também criaremos uma pasta para o front-end, onde estará nosso Streamlit, a interface visual do projeto.
Dentro de "Supervisor", criaremos um arquivo de environment. Não deixaremos nossa chave da OpenAI, mas você deverá colocá-la no seu código. Aqui está como você pode definir a chave da API:
OPENAI_API_KEY=""
Vamos adicionar um .gitignore para itens que não queremos no projeto e um Dockerfile, necessário para o projeto. O conteúdo do .gitignore pode ser o seguinte:
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
.venv
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
No Dockerfile, utilizamos Python na versão 3.13 Slim, com algumas instalações. Definimos que funcionará na app, copiamos o requirements e, embora pudéssemos usar venv ou outro gerenciador, manteremos o padrão do PIP. Realizamos um pip install, copiamos nosso projeto e utilizamos o uvicorn para levantar nossa app, onde ficará a estrutura do Supervisor.
FROM python:3.13-slim
RUN apt-get update && apt-get install -y \
build-essential \
libffi-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
Agora, criaremos um script chamado app.py. Este script será responsável por levantar o FastAPI e o logging, para registrar as atividades do projeto. Instanciamos o FastAPI e definimos um app.post para uma rota padrão de chat, criando um endpoint de chat. Basicamente, criamos uma função que receberá o payload com a request. Validamos se o payload está no formato correto, pois criaremos um padrão para ele. Utilizamos um try/except para garantir que tudo se execute corretamente. Quando a mensagem é recebida no chat, o agente responde e executa o Supervisor, passando o texto do usuário e o payload de mensagens, que o Supervisor supervisionará, roteará e escolherá o agente correto para o projeto.
import logging
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from src.schemas import ChatRequest
from src.agents import executar_supervisor
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
@app.post("/chat")
async def chat_endpoint(payload: ChatRequest):
if not payload.message:
return JSONResponse(status_code=400, content={"error": "Campo 'message' é obrigatório"})
try:
logger.info(f"Mensagem recebida no /chat: {payload.message}")
resposta = await executar_supervisor(texto_usuario=payload.message)
logger.info(f"Resposta gerada: {resposta}")
return {"resposta": resposta}
except Exception as e:
logger.exception("Erro ao processar requisição no endpoint /chat")
return JSONResponse(status_code=500, content={"error": str(e)})
Com o Dockerfile pronto, vamos adicionar o arquivo de requirements, que instala as dependências do projeto. Utilizaremos fastapi, uvicorn, langchain, langchain.openai, langchain.community, httpx e python-dotenv para carregar as variáveis de ambiente.
fastapi
uvicorn
langchain
langchain_openai
langchain-community
httpx
python-dotenv
Agora, criaremos uma pasta chamada "source", onde teremos um arquivo agents, o principal do nosso estudo. Vamos criar o agents.py e começar a escrever o que precisamos. A parte de carregar os pacotes já está pronta, pois não precisamos gastar tempo com isso. Importamos o createAgent, human message para enviar mensagens, o WinChatModel para iniciar nosso modelo, .env, os para carregar as variáveis e load_dotenv.
from langchain.agents import create_agent
from langchain_core.messages import HumanMessage
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
import os
load_dotenv()
A primeira parte será escrever o LLM. Usaremos um WinChatModel. Não aprofundamos na escolha do modelo, pois não temos avaliação para validar, então utilizamos o gpt4o. Poderia ser outro modelo, mas seguiremos com este. Vamos definir a API key usando os.getenv para carregar a OpenAI API key que já escrevemos. Definimos uma temperatura de 0.7 para o modelo, completando a primeira parte do nosso LLM.
__llm = init_chat_model(
model="gpt-4o",
api_key=os.getenv("OPENAI_API_KEY"),
temperature=0.7
)
Vamos criar um agente de cartão de crédito, que é o objetivo do nosso estudo. Utilizaremos a função create_agent para isso. O agente usará o mesmo LLM que definimos anteriormente. Pode haver um problema, pois estamos usando o GPT-4, mas seguiremos assim. Não há tools (ferramentas) aqui, e passaremos um system prompt simples. Não há muito trabalho de engenharia de prompts envolvido, então não ajustaremos muito este prompt. O prompt será: "Você é um especialista em cartões de crédito do Banco Miderbank, ajuda o cliente com dúvidas, solicitações e limites." Com isso, temos nosso primeiro agente.
agente_cartao_credito = create_agent(
__llm,
tools=[],
system_prompt=(
"Você é um especialista em cartão de crédito do banco MDBank. "
"Ajude o cliente com dúvidas, solicitação e limites."
)
)
Agora, criaremos o segundo agente, que é o agente de abertura de contas. Utilizaremos novamente a função create_agent, com o mesmo LLM e tools. Passaremos também um system prompt: "Você é um especialista em abertura de contas do MD Bank, ajuda o cliente a abrir uma conta e explica os tipos disponíveis."
agente_abertura_conta = create_agent(
__llm,
tools=[],
system_prompt=(
"Você é um especialista em abertura de contas do banco MDBank. "
"Ajude o cliente a abrir uma conta e explique os tipos disponíveis."
),
)
Vamos trabalhar na classificação das perguntas para entender se são sobre cartão de crédito ou abertura de conta. Para isso, criaremos a função classificar_pergunta, que receberá uma pergunta como string e devolverá uma string. Faremos um prompt com a responsabilidade de classificar. O texto do prompt será: "Classifique a intenção do usuário. Os possíveis agentes que resolvem são o de cartão de crédito e o de abertura de conta. Aqui está a pergunta e você responderá com um agente."
def classificar_pergunta(pergunta: str) -> str:
prompt = f"""
Classifique a intenção do usuário.
Possíveis agentes:
cartao_credito
abrir_conta
Pergunta: {pergunta}
Responda apenas com o nome do agente.
"""
resposta = __llm.invoke(prompt)
return str(resposta.content).strip()
Escreveremos a função executarSupervisor, que encontrará os agentes. A função receberá um texto do usuário como string e devolverá uma string. O papel do Supervisor é encontrar um agente classificando a pergunta. Se o agente for do tipo cartão de crédito, invocaremos o agente de cartão de crédito e devolveremos uma mensagem do tipo human message com o conteúdo do texto do usuário.
async def executar_supervisor(texto_usuario: str) -> str:
agente = classificar_pergunta(texto_usuario)
if agente == "cartao_credito":
resultado = agente_cartao_credito.invoke(
{"messages": [HumanMessage(content=texto_usuario)]}
)
elif agente == "abrir_conta":
resultado = agente_abertura_conta.invoke(
{"messages": [HumanMessage(content=texto_usuario)]}
)
else:
resultado = "Não consegui entender sua solicitação"
mensagem_ia = resultado["messages"][-1]
return str(mensagem_ia.content)
Podemos agora definir o esquema do nosso código, necessário para validar o que está sendo enviado. O esquema incluirá message, sessão do usuário e a parte client do projeto, que é o client ID. Na pasta do Supervisor, adicionaremos um dockerignore para evitar subir arquivos indesejados. A estrutura do Supervisor incluirá dockerignore, env, gitignore, app, Dockerfile e requirements.
from pydantic import BaseModel
class ChatRequest(BaseModel):
message: str
session_id: str
client_id: str
Vamos pausar o vídeo aqui para não se estender muito. Em seguida, testaremos nosso Supervisor e, ao final, integraremos o front-end chamando toda a nossa estrutura. Isso é tudo por agora. Nos vemos no próximo vídeo.
O curso Protocolos e arquitetura para construção de agentes: MCP, A2A, AG-UI e Backend for Agents (BFA) possui 291 minutos de vídeos, em um total de 49 atividades. Gostou? Conheça nossos outros cursos de IA para Dados em Inteligência Artificial, ou leia nossos artigos de Inteligência Artificial.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
O Plano Plus evoluiu: agora com Luri para impulsionar sua carreira com os melhores cursos e acesso à maior comunidade tech.
2 anos de Alura
Matricule-se no plano PLUS 24 e garanta:
Jornada de estudos progressiva que te guia desde os fundamentos até a atuação prática. Você acompanha sua evolução, entende os próximos passos e se aprofunda nos conteúdos com quem é referência no mercado.
Programação, Data Science, Front-end, DevOps, Mobile, Inovação & Gestão, UX & Design, Inteligência Artificial
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
Acesso à inteligência artificial da Alura.
No Discord, você participa de eventos exclusivos, pode tirar dúvidas em estudos colaborativos e ainda conta com mentorias em grupo com especialistas de diversas áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Luri Vision chegou no Plano Pro: a IA da Alura que enxerga suas dúvidas, acelera seu aprendizado e conta também com o Alura Língua que prepara você para competir no mercado internacional.
2 anos de Alura
Todos os benefícios do PLUS 24 e mais vantagens exclusivas:
Chat, busca, exercícios abertos, revisão de aula, geração de legenda para certificado.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.
Para quem quer atingir seus objetivos mais rápido: Luri Vision ilimitado, vagas de emprego exclusivas e mentorias para acelerar cada etapa da jornada.
2 anos de Alura
Todos os benefícios do PRO 24 e mais vantagens exclusivas:
Catálogo de tecnologia para quem é da área de Marketing
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais de forma ilimitada.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.
Conecte-se ao mercado com mentoria individual personalizada, vagas exclusivas e networking estratégico que impulsionam sua carreira tech para o próximo nível.