Um agente que funciona no notebook não é um agente em produção
Essa é a premissa central de um guia técnico publicado pela AWS sobre como migrar workloads agênticos para o Amazon Bedrock AgentCore. O texto parte de um ponto muito honesto: a inferência do modelo raramente é o problema em produção. O que consome o time de engenharia são as responsabilidades operacionais que aparecem depois — isolamento de sessão, persistência de estado, autenticação de ferramentas, patching de infraestrutura, entre outras.
O guia mapeia dez dessas cargas operacionais e mostra como o AgentCore as absorve progressivamente, em estágios. O agente de exemplo é um bot de suporte ao cliente construído com LangGraph: ele classifica mensagens, escala clientes insatisfeitos e responde os demais usando três ferramentas. As chamadas de modelo já passam pelo Amazon Bedrock desde o início — mas isso, como o próprio guia destaca, não é a vantagem que parece.
O que o AgentCore cobre — e o que continua sendo seu
Antes de entrar nos estágios, o guia faz questão de ser claro sobre o escopo do AgentCore. Ele é descrito como uma plataforma para construir, conectar e otimizar agentes em escala, com qualquer framework ou modelo. Mas ele não elimina tudo:
- Runtime assume o compute: patching de sistema operacional, auto scaling e isolamento de sessão deixam de ser sua responsabilidade.
- Gateway assume a autenticação das ferramentas e as publica como ferramentas Protocolo de Contexto de Modelo (MCP — Model Context Protocol).
- Memory assume o estado da conversa, tornando-o durável entre turnos, processos e dias.
O que continua sendo responsabilidade da equipe: configuração de Rede Virtual Privada (VPC — Virtual Private Cloud), regras de Firewall de Aplicação Web (WAF — Web Application Firewall), políticas de Gerenciamento de Identidade e Acesso (IAM — Identity and Access Management), rotação de segredos e atualizações de dependências (estas últimas só saem do seu escopo no Estágio 3).
Estágio 0: o agente que você já tem
Antes de mover qualquer coisa, o guia recomenda registrar uma linha de base: quais ferramentas foram executadas e qual foi a mensagem final do estado do grafo. Isso transforma o próximo estágio em uma comparação objetiva, não em uma aposta.
O agente do exemplo usa ChatBedrockConverse como modelo, um MemorySaver com thread_id como checkpointer, e três ferramentas (lookup_order, process_return e search_faq) como funções @tool. O roteamento é feito por um nó classify_intent com uma função Python determinística.
O único problema real nesse estágio é o estado: um dicionário em memória morre com o processo, e duas réplicas não conseguem ver as conversas uma da outra. Tudo o mais funciona bem em escala de produção — mas esse ponto não.
Para quem chega de OpenAI ou Anthropic direto, a única mudança necessária neste estágio é trocar o construtor do modelo pelo ChatBedrockConverse, passando o ID do modelo e a região AWS. A lista de modelos disponíveis por região pode ser consultada na documentação de modelos suportados por região no Amazon Bedrock.
Estágio 1: o mesmo agente, migrado
O Estágio 1 move cinco das dez cargas operacionais sem alterar o comportamento do agente. Três coisas mudam: o Runtime assume o processo, duas das três ferramentas vão para o Gateway, e o estado da conversa passa para o Memory.
Runtime: hospedando o loop
O loop existente é envolvido por BedrockAgentCoreApp com um entrypoint decorado. O thread_id que antes era escolhido manualmente agora chega como context.session_id do RequestContext que o Runtime injeta. O guia faz um alerta importante: construa o grafo uma vez e mantenha-o, porque reconstruir por requisição pode derrubar a sessão MCP das ferramentas.
from bedrock_agentcore import BedrockAgentCoreApp
from langchain_core.messages import HumanMessage
app = BedrockAgentCoreApp()
@app.entrypoint
def agent_invocation(payload, context):
state = support_graph().invoke(
{"messages": [HumanMessage(payload.get("prompt", ""))]},
config={"configurable": {"thread_id": context.session_id or "local-session"}},
)
return {"result": state["messages"][-1].text}
if __name__ == "__main__":
app.run()
O mesmo wrapper funciona com loops CrewAI, LlamaIndex ou qualquer outro: aceite um dicionário de payload, invoque, retorne um dicionário.
Gateway: publicando ferramentas como MCP
O motivo de colocar uma ferramenta atrás de um gateway é o que vem junto: a autenticação sai do seu código e a ferramenta publicada passa a ser acessível por outros agentes futuros, não apenas pelo agente atual.
lookup_order e process_return são publicadas como ferramentas MCP pelo AgentCore Gateway a partir de uma função Lambda. A criação é feita com duas chamadas no cliente bedrock-agentcore-control: uma para criar o gateway (escolhendo o tipo de autorizador — AWS_IAM ou CUSTOM_JWT) e outra para registrar o target apontando para a função Lambda com o schema JSON das ferramentas.
client = boto3.client("bedrock-agentcore-control", region_name=region)
gateway = client.create_gateway(
name="MigratedAgentGateway",
roleArn=role_arn,
protocolType="MCP",
authorizerType="AWS_IAM",
)
gateway_id = gateway["gatewayId"]
gateway_url = gateway["gatewayUrl"]
As ferramentas descobertas chegam prefixadas com o nome do target e três underscores: lookup_order vira supportTools___lookup_order. search_faq permanece como função Python local em todos os estágios — e o guia deixa claro que esse é o caso normal, não um compromisso. Uma ferramenta que nenhum outro agente precisa e nenhuma política controla não tem nada a ganhar com a migração para o Gateway.
Memory: estado que sobrevive ao processo
O MemorySaver do Estágio 0 é substituído por um checkpointer respaldado pelo AgentCore Memory, identificado por actor_id e sessão. O checkpointer já vem como dependência instalada (langgraph-checkpoint-aws) e não precisa de código customizado:
from langgraph_checkpoint_aws import AgentCoreMemorySaver
graph = build_graph(
llm=llm,
tools=tools,
checkpointer=AgentCoreMemorySaver(memory_id, region_name=region),
)
state = graph.invoke(
{"messages": [HumanMessage(prompt)]},
config={"configurable": {"thread_id": session_id, "actor_id": actor_id}},
)
O guia recomenda testar a durabilidade explicitamente: um segundo processo, compartilhando apenas os IDs de memória, actor e sessão, deve conseguir responder sobre uma conversa que nunca foi carregada localmente.
Deploy e armadilhas comuns
O deploy usa uma codeConfiguration: um zip do código-fonte no Amazon S3 com as dependências vendorizadas ao lado. Sem container, sem Amazon Elastic Container Registry (ECR — Elastic Container Registry), sem Docker. Mas há duas armadilhas que custam tempo real:
- Wheels de plataforma errada: o Runtime roda em ARM64 Linux. Instale as dependências para o target correto:
--platform manylinux2014_aarch64 --python-version 3.12 --only-binary=:all: - Dependência faltando no zip: um
requirements.txtdentro do zip é inerte. O arquivo é o ambiente finalizado. Se uma dependência falta, o erro aparece como timeout de inicialização do Runtime, não comoModuleNotFoundError.
Estágio 2: reconstruindo o loop por escolha
O Estágio 2 não move cargas operacionais — ele muda quem decide o próximo passo. Faz sentido quando o roteamento escrito à mão (route_intent) se torna o gargalo: cada nova intenção exige um novo nó no grafo em vez de uma linha no prompt.
Com Strands Agents, o planejamento passa para o modelo. O add_conditional_edges não tem equivalente — e o guia é explícito sobre o trade-off: o branch determinístico e auditável é trocado por um planejamento que não é nem um nem outro.
O gerenciamento de memória colapsa em um objeto de configuração e um argumento de construtor, reutilizando o Gateway, o target e o Memory store do Estágio 1:
config = AgentCoreMemoryConfig(
memory_id=memory_id,
session_id=session_id,
actor_id=actor_id
)
kwargs["session_manager"] = AgentCoreMemorySessionManager(
config, region_name=region_name
)
return Agent(**kwargs)
Policy: decisão determinística de volta em cada chamada de ferramenta
Para compensar a perda do branch auditável, a Policy do Amazon Bedrock AgentCore coloca uma decisão determinística na frente de cada chamada de ferramenta via Gateway, usando regras Cedar avaliadas no plano de dados — em um caminho que a aplicação não consegue contornar. Um guardrail na saída do modelo não está nesse caminho; quando ele roda, a chamada já aconteceu.
O exemplo do guia usa duas regras: uma identidade somente-leitura pode chamar lookup_order; uma identidade privilegiada pode também chamar process_return. Cedar é default-deny — a recusa do caller somente-leitura é simplesmente a ausência de uma regra permit correspondente.
Estágio 3: entregando o loop
O Estágio 3 é documentado no guia, mas não construído no walkthrough. Um AgentCore harness executa o loop por você, alimentado por Strands Agents. O agente é declarado como configuração (modelo, prompt de sistema, ferramentas, memória e limites) e a AWS o executa — trocar de modelo vira uma mudança de configuração, não um redeploy.
O pré-requisito é que o agente já seja um loop orientado a modelo (não um grafo), o que significa que o Estágio 2 precede obrigatoriamente o Estágio 3. É o único ponto do guia onde a ordem recomendada é também a única ordem possível. Seis das dez cargas operacionais se movem aqui — e atualização de dependências é a única que só sai do seu escopo neste estágio.
Armadilhas comuns de migração
O guia fecha com três padrões que custam mais tempo às equipes após a migração:
1. Assumir paridade de comportamento
O agente não vai se comportar de forma idêntica após a migração, e sem critérios acordados antes da mudança, qualquer diferença de redação vira uma discussão sem fim. A recomendação é definir critérios de aceitação baseados em resultados, não em implementação — e usar o AgentCore Evaluations para testá-los.
2. Manter estado no processo
Uma sessão não é uma invocação: ela contém múltiplas invocações, e o Runtime encerra o ambiente de execução após 15 minutos de inatividade por padrão, provisionando um novo para a mesma sessão. Esse timeout é configurável via idleRuntimeSessionTimeout (de 60 segundos a 8 horas), mas ajustá-lo move o prazo — não o elimina. A sessão sobrevive; o estado em memória, não.
3. Subestimar a arquitetura de autenticação
Lacunas de autenticação custam retrabalho, não configuração. Mapeie primeiro todos os fluxos: como o agente se autentica em APIs externas, como usuários se autenticam no agente, como as permissões são escopadas. O AgentCore Identity responde à primeira questão, referenciado no target do gateway no lugar de GATEWAY_IAM_ROLE.
Pré-requisitos para seguir o walkthrough
Para reproduzir o guia, são necessários: uma conta AWS com acesso ao Amazon Bedrock habilitado, Python 3.12 e a Interface de Linha de Comando AWS (AWS CLI) configurada com credenciais para criar recursos de AgentCore, Lambda, Amazon S3 e IAM. Também é necessário habilitar o CloudWatch Transaction Search uma vez na conta — sem isso, os traces gerados não podem ser visualizados.
O repositório de exemplo está organizado por estágio, permitindo comparar cada um com o anterior. O setup cria um ambiente virtual e instala sete dependências com um único script.
Conclusão
O Estágio 1 é um ponto de parada válido: você mantém a orquestração em que confia, em compute gerenciado, com ferramentas gerenciadas e estado durável. O Estágio 2 é outro ponto de parada, para agentes onde o roteamento escrito à mão virou o gargalo. O Estágio 3 tira o loop do seu codebase.
O guia também destaca que nenhuma dessas migrações precisa ser feita duas vezes: as features do AgentCore se encaixam como um argumento de keyword para as ferramentas do gateway, uma dependência pinada para o checkpointer, um objeto de configuração para o session manager e um arquivo de regras Cedar para a Policy.
Para aprofundamento, a AWS recomenda clonar o repositório de exemplo, ler a comparação de arquitetura de segurança e consultar a documentação do Amazon Bedrock AgentCore.
Fonte
Migrate agentic workloads to Amazon Bedrock AgentCore (https://aws.amazon.com/blogs/machine-learning/migrate-agentic-workloads-to-amazon-bedrock-agentcore/)
Leave a Reply