Quando conversar não é suficiente
Agentes de IA já dominam a arte de conversar. Mas e quando a tarefa exige mais do que texto? Renderizar um gráfico diretamente no chat, manter um painel de tarefas sincronizado em tempo real ou pausar a execução para aguardar aprovação do usuário — essas interações pedem um padrão de comunicação mais robusto entre o backend do agente e o frontend.
É aí que entra o AG-UI (Agent-User Interaction Protocol), um protocolo aberto que define exatamente esse padrão. Ele funciona com múltiplos frameworks de agentes — Strands Agents, LangGraph, CrewAI — e com as principais bibliotecas de frontend como React, Angular e Vue. A grande vantagem: o código do agente e o código da interface ficam completamente desacoplados, permitindo escolher o melhor de cada mundo sem amarrações.
A AWS publicou um guia detalhado mostrando como o AG-UI se integra ao Fullstack AgentCore Solution Template (FAST) e como o CopilotKit expande essas capacidades com interfaces generativas, estado compartilhado e fluxos human-in-the-loop — tudo rodando no Amazon Bedrock AgentCore.
Como a solução está estruturada
O Amazon Bedrock AgentCore Runtime é um ambiente serverless, seguro e dedicado para hospedar agentes de IA e ferramentas. Ele suporta três protocolos principais: o MCP (Model Context Protocol) conecta agentes a ferramentas, o A2A (Agent2Agent) conecta agentes entre si, e o AG-UI conecta agentes aos usuários.
Quando um container de agente é implantado com a flag do protocolo AG-UI, o AgentCore funciona como um proxy transparente: cuida da autenticação (SigV4 ou OAuth 2.0 via Amazon Cognito), do isolamento de sessão, da escalabilidade e da observabilidade. O container precisa expor POST /invocations para requisições AG-UI e GET /ping para verificações de saúde na porta 8080. Para mais detalhes sobre esse processo, a AWS disponibiliza a documentação de como implantar servidores AG-UI no AgentCore Runtime.
O FAST é um projeto inicial pronto para implantação que conecta AgentCore Runtime, Gateway, Identity, Memory e Code Interpreter com um frontend React e autenticação via Amazon Cognito — tudo definido com AWS CDK. A versão v0.4.1 adicionou dois padrões AG-UI (agui-strands-agent e agui-langgraph-agent) que compartilham um único parser de frontend. Para um guia completo da arquitetura e implantação do FAST, vale conferir o post Accelerate agentic application development with a full-stack starter template for Amazon Bedrock AgentCore.
A solução apresentada tem duas camadas independentes. A primeira é o AG-UI integrado ao FAST, com dois padrões de agente e um parser único de frontend que os trata de forma transparente — o frontend não precisa saber qual framework está rodando no backend. A segunda é a amostra CopilotKit + FAST, que substitui a interface de chat nativa pelo CopilotKit, adicionando interface generativa com componentes inline, estado compartilhado bidirecional e interações human-in-the-loop.
AG-UI no FAST: um parser, dois frameworks
Padrão agui-strands-agent
O padrão agui-strands-agent envolve um Strands Agent no StrandsAgent da biblioteca ag-ui-strands. O wrapper traduz automaticamente os eventos de streaming do Strands em Server-Sent Events (SSE) do AG-UI. Cada requisição cria um agente novo com as ferramentas MCP do Gateway. O AgentCore Memory é associado por thread por meio de um provedor de gerenciador de sessão, de forma que o histórico da conversa persiste mesmo durante o escalonamento. A memória é opcional: o provedor retorna None quando MEMORY_ID não está definido:
# patterns/agui-strands-agent/agent.py
from ag_ui_strands import StrandsAgent, StrandsAgentConfig
from bedrock_agentcore.runtime import BedrockAgentCoreApp, RequestContext
from strands import Agent
app = BedrockAgentCoreApp()
# Build the model and Code Interpreter once at module load
MODEL = BedrockModel(model_id="us.anthropic.claude-sonnet-4-5-20250929-v1:0")
CODE_INTERPRETER = StrandsCodeInterpreterTools(REGION).execute_python_securely
@app.entrypoint
async def invocations(payload: dict, context: RequestContext):
input_data = RunAgentInput.model_validate(payload)
actor_id = extract_user_id_from_context(context)
# Fresh agent per request --- picks up the caller's identity and tools
agent = Agent(
model=MODEL,
system_prompt=SYSTEM_PROMPT,
tools=[create_gateway_mcp_client(actor_id), CODE_INTERPRETER],
session_manager=get_memory_session_manager(actor_id, session_id),
)
agui_agent = StrandsAgent(
agent=agent,
name="agui_strands_agent",
config=StrandsAgentConfig(
session_manager_provider=make_memory_provider(actor_id),
replay_history_into_strands=False,
),
)
async for event in agui_agent.run(input_data):
yield event.model_dump(mode="json", by_alias=True, exclude_none=True)
O BedrockAgentCoreApp lê os cabeçalhos do AgentCore Runtime (WorkloadAccessToken, Authorization, Session-Id) e popula variáveis de contexto, de forma que a autenticação do Gateway e o Memory funcionam da mesma forma que os padrões HTTP.
Padrão agui-langgraph-agent
Já o padrão agui-langgraph-agent usa o LangGraphAGUIAgent da biblioteca copilotkit. O grafo compilado é construído a cada requisição, garantindo que cada invocação receba as ferramentas MCP com escopo do chamador. O AgentCore Memory também é opcional aqui — o helper retorna None quando MEMORY_ID não está definido, permitindo executar o padrão sem provisionar Memory:
# patterns/agui-langgraph-agent/agent.py
from copilotkit import CopilotKitMiddleware, LangGraphAGUIAgent
async def build_graph(actor_id: str):
"""Build a fresh LangGraph compiled graph with Gateway tools."""
mcp_client = await create_gateway_mcp_client(actor_id)
tools = await mcp_client.get_tools()
tools.append(CODE_INTERPRETER)
return create_agent(
model=MODEL,
tools=tools,
checkpointer=get_memory_saver(), # None when MEMORY_ID is unset
middleware=[CopilotKitMiddleware()],
system_prompt=SYSTEM_PROMPT,
)
@app.entrypoint
async def invocations(payload: dict, context: RequestContext):
input_data = RunAgentInput.model_validate(payload)
actor_id = extract_user_id_from_context(context)
graph = await build_graph(actor_id)
agui_agent = LangGraphAGUIAgent(
name="agui_langgraph_agent",
graph=graph,
config={"configurable": {"actor_id": actor_id}},
)
async for event in agui_agent.run(input_data):
yield event.model_dump(mode="json", by_alias=True, exclude_none=True)
Um único parser para ambos os frameworks
Os dois padrões produzem os mesmos eventos AG-UI — um fluxo de eventos tipados sobre SSE. Por exemplo, uma única chamada de ferramenta gera esta sequência:
data: {"type": "RUN_STARTED", "threadId": "t1", "runId": "r1"}
data: {"type": "TEXT_MESSAGE_START", "messageId": "m1", "role": "assistant"}
data: {"type": "TEXT_MESSAGE_CONTENT", "messageId": "m1", "delta": "Let me check "}
data: {"type": "TEXT_MESSAGE_CONTENT", "messageId": "m1", "delta": "that for you."}
data: {"type": "TEXT_MESSAGE_END", "messageId": "m1"}
data: {"type": "TOOL_CALL_START", "toolCallId": "tc1", "toolCallName": "get_weather"}
data: {"type": "TOOL_CALL_ARGS", "toolCallId": "tc1", "delta": "{\"location\": \"Seattle\"}"}
data: {"type": "TOOL_CALL_END", "toolCallId": "tc1"}
data: {"type": "TOOL_CALL_RESULT", "toolCallId": "tc1", "content": "{\"temp\": 55}"}
data: {"type": "RUN_FINISHED", "threadId": "t1", "runId": "r1"}
O parser de frontend mapeia cada evento para uma ação correspondente:
// frontend/src/lib/agentcore-client/parsers/agui.ts
export const parseAguiChunk: ChunkParser = (line, callback) => {
if (!line.startsWith("data: ")) return;
const json = JSON.parse(line.substring(6).trim());
switch (json.type) {
case "TEXT_MESSAGE_CONTENT":
callback({ type: "text", content: json.delta ?? "" });
break;
case "TOOL_CALL_START":
callback({ type: "tool_use_start", toolUseId: json.toolCallId, name: json.toolCallName });
break;
case "TOOL_CALL_RESULT":
callback({ type: "tool_result", toolUseId: json.toolCallId, result: json.content ?? "" });
break;
case "RUN_FINISHED":
callback({ type: "result", stopReason: "end_turn" });
}
};
Diferente dos padrões HTTP — onde Strands, LangGraph e Claude Agent SDK exigem parsers separados para seus diferentes formatos de streaming — o AG-UI abstrai o framework do backend. Trocar agui-strands-agent por agui-langgraph-agent na configuração não exige nenhuma mudança no frontend.
Para implantar, basta definir o padrão em infra-cdk/config.yaml e executar o CDK:
backend:
pattern: agui-strands-agent # or agui-langgraph-agent
deployment_type: docker
cd infra-cdk
cdk deploy --require-approval never
python3 ../scripts/deploy-frontend.py
CopilotKit + FAST: indo além do chat
O frontend base do FAST oferece uma interface de chat funcional, mas o AG-UI suporta interações muito mais ricas. O CopilotKit é uma biblioteca React construída especificamente para esses padrões avançados. A equipe do CopilotKit desenvolveu uma aplicação de exemplo sobre o FAST que demonstra essas capacidades no AgentCore, com suporte tanto para LangGraph quanto para Strands — a escolha é feita no momento da implantação.
Interface generativa: componentes React renderizados pelo agente
Com o CopilotKit, o agente consegue renderizar componentes React customizados diretamente no chat, não apenas texto. O frontend registra componentes que o agente pode invocar por meio de eventos de chamada de ferramenta do AG-UI:
// Register a pie chart the agent can render
useComponent({
name: "pieChart",
description: "Displays data as a pie chart.",
parameters: PieChartPropsSchema,
render: PieChart,
});
Quando o agente chama a ferramenta pieChart, o CopilotKit intercepta os eventos TOOL_CALL_START e TOOL_CALL_ARGS e renderiza o componente PieChart diretamente na conversa. O agente primeiro chama uma ferramenta query_data para buscar dados de um arquivo CSV de exemplo e então passa os resultados para o componente de gráfico.
Estado compartilhado: canvas de tarefas sincronizado em tempo real
A amostra inclui um canvas de tarefas com sincronização bidirecional entre o agente e a interface. Ao pedir ao agente “Adicione três tarefas: design da API, escrever testes e implantar em staging”, ele chama manage_todos e o canvas é atualizado em tempo real via eventos STATE_SNAPSHOT do AG-UI. Edições feitas diretamente na interface também são visíveis para o agente na próxima invocação, porque o padrão Strands injeta as tarefas atuais no prompt do sistema:
def state_context_builder(state: dict) -> str:
todos = state.get("todos", [])
if todos:
return f"\nCurrent todos:\n{json.dumps(todos, indent=2)}"
return ""
Human-in-the-loop: o agente pausa e aguarda sua decisão
A amostra demonstra um agendador de reuniões onde o agente pausa no meio da execução e renderiza um seletor de horário. O usuário escolhe um horário e o agente retoma com essa informação:
useHumanInTheLoop({
name: "scheduleTime",
description: "Schedule a meeting with the user.",
parameters: z.object({
reasonForScheduling: z.string(),
meetingDuration: z.number(),
}),
render: ({ respond, status, args }) => (
<MeetingTimePicker status={status} respond={respond} {...args} />
),
});
O mecanismo usa o fluxo de chamada de ferramenta do AG-UI: o agente emite TOOL_CALL_START para scheduleTime, o CopilotKit renderiza o seletor no lugar de executar uma ferramenta no backend, e a resposta do usuário volta como um TOOL_CALL_RESULT.
Pré-requisitos e como implantar
Para seguir o guia, você vai precisar de:
- Uma conta AWS com permissões para AWS CloudFormation, Amazon ECR, Amazon Bedrock AgentCore, Amazon Cognito e AWS Amplify.
- AWS CLI v2 instalada e configurada.
- AWS CDK instalado.
- Node.js 18 ou superior e Python 3.11 ou superior.
- Docker em execução, para builds de container.
- Acesso ao modelo habilitado no console do Amazon Bedrock para o modelo utilizado pelo agente.
Para implantar a amostra CopilotKit, clone o repositório de amostras FAST e execute:
git clone https://github.com/aws-samples/sample-FAST-applications.git
cd sample-FAST-applications/samples/copilotkit-generative-ui
cp config.yaml.example config.yaml
# Edit config.yaml --- set stack_name_base and admin_user_email
./deploy-langgraph.sh # or ./deploy-strands.sh
O script provisiona toda a stack: pool de usuários do Amazon Cognito, repositório do Amazon ECR, AgentCore Runtime, AgentCore Gateway, AgentCore Memory, a Lambda do CopilotKit Runtime com Amazon API Gateway e hospedagem no AWS Amplify. Ao final, basta abrir a URL do Amplify exibida no terminal e fazer login para verificar a implantação.
Limpando os recursos
A solução implanta dois stacks separados. Para evitar cobranças contínuas, remova o que foi implantado.
Para remover a implantação FAST:
cd infra-cdk
npx cdk destroy --all
Para remover a amostra CopilotKit:
cd sample-FAST-applications/samples/copilotkit-generative-ui
npx cdk destroy --all
Se um repositório do Amazon ECR ainda contiver imagens de container, exclua-o manualmente — algumas configurações do CDK mantêm repositórios no lugar após o destroy.
Conclusão
A integração do AG-UI ao FAST permite alternar entre os backends Strands e LangGraph sem tocar no código do frontend. A amostra CopilotKit vai além, adicionando interface generativa, estado compartilhado e interações human-in-the-loop — tudo rodando no AgentCore com autenticação gerenciada, escalabilidade e memória.
Para explorar mais, os recursos disponíveis incluem o repositório FAST (para implantar um padrão AG-UI com agui-strands-agent ou agui-langgraph-agent), a amostra CopilotKit Generative UI (para experimentar interface generativa, estado compartilhado e human-in-the-loop no AgentCore), a documentação AG-UI do AgentCore (contrato completo do protocolo e detalhes de implantação), a especificação do protocolo AG-UI (tipos de eventos e design do protocolo) e a documentação do CopilotKit (guia de integração de frontend para interface generativa). Dúvidas e feedback podem ser registrados como issues no repositório FAST ou no repositório FAST Samples.
Fonte
Build generative UI for AI agents on Amazon Bedrock AgentCore with the AG-UI protocol (https://aws.amazon.com/blogs/machine-learning/build-generative-ui-for-ai-agents-on-amazon-bedrock-agentcore-with-the-ag-ui-protocol/)
Leave a Reply