Construindo um assistente de IA com memória contextual usando AgentCore e OpenClaw

O problema da amnésia nos assistentes de IA

Assistentes de IA prontos para uso respondem bem a perguntas individuais, mas falham em um aspecto crítico: a continuidade. Um assistente sem memória não sabe que você mencionou, três semanas atrás, que seu canteiro drena rápido, que você só usa fertilizante orgânico ou que suas petúnias estavam sofrendo com uma onda de calor. Cada conversa começa do zero, e o peso de recontextualizar tudo recai sobre o usuário.

O problema não está na qualidade das respostas — está na ausência de memória sobre quem você é. É exatamente esse gap que a AWS endereça em um tutorial publicado no blog de Machine Learning, mostrando como construir um assistente pessoal que acumula contexto ao longo do tempo usando o OpenClaw, um sistema agêntico de código aberto, rodando sobre o AgentCore runtime, uma capacidade do Amazon Bedrock AgentCore.

Visão geral da solução

O assistente de exemplo se chama Sprout — um bot de jardinagem — mas a arquitetura é agnóstica de domínio. Troque a persona e o manifesto de habilidades, e o mesmo pipeline serve um bot de suporte, um coach de fitness ou um help desk interno.

Toda a infraestrutura vive em um único template do AWS CloudFormation, é implantada com um comando e opera em modelo de consumo, custando alguns dólares por mês para uso pessoal leve.

O fluxo de ponta a ponta funciona assim: mensagens do Telegram chegam pelo Amazon Interfaceace de Programação de Aplicações (API) Gateway e por uma função AWS Lambda de webhook, enquanto tarefas agendadas — como lembretes de rega matinal — chegam via Amazon EventBridge Scheduler e uma Lambda de cronjob. Ambas chamam a API InvokeAgentRuntime no AgentCore runtime, onde um processo server.py coordena o gateway do OpenClaw, o AgentCore Memory e a API Converse do Amazon Bedrock. O Amazon Simple Storage Service (Amazon S3) fornece armazenamento de workspace, o AWS Key Management Service (AWS KMS) cuida da criptografia, o AWS Secrets Manager guarda o token do bot, e o Amazon CloudWatch captura logs e métricas.

A arquitetura: um agente serverless no AgentCore runtime

Pagando apenas pelo compute ativo

O agente roda em um container no AgentCore runtime, que usa precificação baseada em consumo. A cobrança é pelo compute que o agente efetivamente usa — não pelo tempo ocioso aguardando respostas de modelos ou chamadas de I/O. Para um assistente pessoal usado em sessões curtas, isso representa a diferença entre uma baseline de aproximadamente US$ 1–2/mês e uma instância Amazon Elastic Compute Cloud (Amazon EC2) sempre ligada, que custaria cerca de US$ 35/mês. Esses valores são estimativas para uso pessoal leve referentes a julho de 2026. Consulte a página de preços do AgentCore para valores atualizados.

O runtime exige um contrato mínimo de container: escutar na porta 8080, expor GET /ping para health check e POST /invocations como ponto de entrada do agente.

OpenClaw como substrato do agente

O OpenClaw fornece o loop do agente, o uso de ferramentas e um sistema de habilidades (skills). Ele roda um wrapper (server.py) que o adapta ao contrato HTTP do protocolo AgentCore: na inicialização do container, o server.py lança o openclaw gateway run como subprocesso e verifica sua saúde. O GET /ping retorna saudável rapidamente para que o probe de prontidão do AgentCore passe. O POST /invocations faz o trabalho real: parseia o payload, recupera memória, monta o contexto, encaminha o turno ao gateway e persiste o resultado.

Um detalhe importante: o AgentCore pode descongelar um container cujo subprocesso já tenha encerrado. Por isso, o caminho de invocação não assume que o gateway está vivo — ele chama um helper ensure_openclaw_ready() que verifica a saúde (e reinicia o gateway se necessário) antes de encaminhar o turno. Esse padrão de wrapper se generaliza: qualquer framework de agente que rode como processo local pode ser adaptado ao AgentCore runtime da mesma forma, sem modificar o framework em si.

Dois modelos, roteados por tarefa

Chat de texto e compreensão de imagens têm tradeoffs diferentes de custo e qualidade, então o assistente roteia para modelos Claude distintos no Bedrock:

  • Claude Haiku 4.5 para texto: rápido e econômico para os turnos conversacionais de alto volume que dominam o uso diário.
  • Claude Sonnet 4.5 para visão: raciocínio multimodal mais robusto para a tarefa menos frequente, porém mais complexa, de diagnosticar uma planta a partir de uma foto.

Os turnos de texto fluem pelo gateway do OpenClaw, que traz habilidades e estado de sessão. Os turnos de imagem chamam o modelo diretamente da API Converse do Bedrock, passando os bytes da imagem como blocos de conteúdo multimodal. Os IDs dos modelos são variáveis de ambiente (MODEL_ID, VISION_MODEL_ID), então é possível trocar os modelos por implantação sem reconstruir a imagem.

Habilidades como unidade de capacidade reutilizável

As capacidades são declaradas como skills em um manifesto community-skills.json. Um script de deploy as materializa no container e as registra na configuração do OpenClaw antes da imagem ser construída. O Sprout vem com skills de clima, lembretes e notas de plantas. Trocar o manifesto faz o mesmo pipeline servir a um domínio completamente diferente — é o que torna o padrão reutilizável.

Memória: transformando chats descartáveis em conhecimento durável

O modelo mental: eventos de curto prazo, extração de longo prazo

O AgentCore Memory tem duas camadas. A memória de curto prazo armazena cada turno de conversa como um evento via CreateEvent, indexado por actorId (o chat ID do Telegram) e sessionId — é a transcrição bruta. A memória de longo prazo é produzida de forma assíncrona por estratégias de extração gerenciadas em registros estruturados e duráveis. Três estratégias são configuradas:

  • USER_PREFERENCE: escolhas explícitas do usuário (“só uso fertilizante orgânico”).
  • SEMANTIC: fatos inferidos (“cultiva petúnias mexicanas em um canteiro elevado de aço Corten”).
  • SUMMARIZATION: resumos episódicos de sessão (“discutiu folhas inferiores amarelando durante uma onda de calor”).

Namespaces: um jardim por jardineiro

O Sprout arquiva registros em namespaces por usuário, para que dois chats nunca se misturem:

  • sprout/{chat_id}/long_term: preferências e fatos semânticos.
  • sprout/{chat_id}/episodic/{session_id}: resumos de sessão.

O chat ID é o único segmento variável, o que torna o isolamento simples de raciocinar e testar: cada jardineiro único mapeia para exatamente um namespace, sem colisões.

O pipeline de recuperação, montagem e injeção

A cada turno, o agente recupera os registros de longo prazo relevantes, os classifica e os injeta no system prompt. Veja o que acontece em cada mensagem dentro do server.py:

1. Recuperar: chama RetrieveMemoryRecords contra sprout/{chat_id}/long_term, usando a mensagem do usuário como query de busca, limitado a 50 resultados e com budget de 3 segundos. Se a recuperação expirar ou falhar, o sistema degrada graciosamente e responde sem memória, em vez de falhar.

try:
    records = memory_client.retrieve_memory_records(
        memoryId=MEMORY_ID,
        namespace=f'sprout/{chat_id}/long_term',
        searchCriteria={
            'searchQuery': user_message,
            'topK': 50,
            'metadataFilters': []
        },
    )  # 3s timeout
except Exception:
    records = []  # fall back to answering without memory

2. Montar: preferências explícitas têm prioridade sobre fatos inferidos, a ordem é estável dentro de cada classe, e o resultado é limitado antes da injeção:

def assemble(records, cap=50):
    explicit = [r for r in records if r.type == 'USER_PREFERENCE']
    inferred = [r for r in records if r.type != 'USER_PREFERENCE']
    # explicit beats inferred; stable order within each class
    ordered = explicit + inferred
    return ordered[:cap]

Metadados: subagrupando memórias dentro de um namespace

Namespaces respondem de quem é um registro, mas metadados respondem sobre o quê ele trata. Dentro de sprout/{chat_id}/long_term, uma busca semântica por “minhas petúnias estão murchando” retornaria tudo que está semanticamente próximo — incluindo uma preferência de fertilizante de março e uma nota de poda de figueira. Metadados estruturados ajudam a restringir o escopo antes que os registros cheguem ao prompt.

Uma regra fundamental: uma chave de metadado só é filtrável no servidor se for declarada como chave indexada. Você pode aprender mais sobre isso em Filtragem estruturada de memória com metadados no Amazon Bedrock AgentCore Memory. O Sprout usa três chaves indexadas:

IndexedKeys:  # on the AWS::BedrockAgentCore::Memory resource
  - Key: type       # seperate the kinds of records
    Type: STRING
  - Key: section    # which bed or area it describes
    Type: STRING
  - Key: plants     # what is growing there
    Type: STRINGLIST

Persistindo o turno e fechando o loop

Após o modelo responder, o server.py chama CreateEvent com o turno do usuário e o turno do assistente. Esse novo evento alimenta as estratégias de extração, que enriquecem o armazenamento de longo prazo para a próxima vez:

memory.create_event(
    memoryId=MEMORY_ID,
    actorId=chat_id,
    sessionId=session_id,
    payload=[
        {'role': 'user', 'content': user_message},
        {'role': 'assistant', 'content': reply},
    ],
)
# feeds USER_PREFERENCE / SEMANTIC / SUMMARIZATION extraction; errors are logged, never fatal

A extração é assíncrona, então um fato mencionado nesta sessão tipicamente se torna recuperável em uma sessão posterior. O design considera esse delay: eventos de sessão de curto prazo cobrem a conversa atual, e registros de longo prazo cobrem tudo o que veio antes.

Mantendo os custos de inferência baixos com prompt caching

Injetar memória em cada turno torna o system prompt grande, e uma implementação ingênua pagaria por esses tokens em cada requisição. O prompt caching no Amazon Bedrock resolve isso. O assistente estrutura seu prompt de forma que o prefixo estável — a persona e o bloco de memória montado — venha primeiro, e a mensagem volátil do usuário venha por último. O Bedrock faz cache do prefixo processado entre requisições, então turnos repetidos dentro de uma conversa pulam o reprocessamento da parte inalterada. O prompt caching pode reduzir custos em até 90% e a latência em até 85% para modelos compatíveis.

A regra de ordenação importa mais do que qualquer configuração individual: coloque conteúdo estável primeiro, conteúdo volátil por último, e mantenha a ordenação interna do bloco de memória determinística — o que a função de montagem mostrada anteriormente facilita — para que o prefixo realmente coincida entre requisições.

Diretrizes de design para construir sobre AgentCore e OpenClaw

O Sprout é um assistente, mas as decisões por trás dele se generalizam. Estas são as diretrizes que a AWS recomenda para qualquer domínio:

  • Envolva, não bifurque. Adapte seu framework de agente ao contrato de container do AgentCore com um wrapper HTTP fino, em vez de modificar o framework. O contrato é pequeno — porta 8080 com /ping e /invocations — e um wrapper mantém você no caminho de atualização do framework.
  • Projete namespaces antes de armazenar qualquer coisa. Namespaces de memória são seu limite de isolamento. Use o ID do usuário como único segmento variável e escolha-o a partir de um ID nativo do canal em que você já confia.
  • Trate memória como melhoria, nunca como dependência. Toda operação de memória deve poder falhar graciosamente. Falhas de recuperação devem produzir uma resposta sem memória, sem bloquear a resposta. Usuários perdoam um turno esquecido muito mais facilmente do que um turno com falha.
  • Roteie modelos por tarefa. Use um modelo rápido e econômico para texto de alto volume e reserve um modelo multimodal mais robusto para os turnos que precisam dele. Mantenha os IDs dos modelos em variáveis de ambiente.
  • Ordene prompts para o cache. Persona estável e memória primeiro, input volátil do usuário por último, ordenação determinística ao longo de tudo.
  • Planeje para a latência de extração. A memória de longo prazo é extraída de forma assíncrona — não prometa recall na mesma sessão de fatos novos.
  • Defina um orçamento desde o primeiro dia. Um alerta no AWS Budgets em 80% e 100% de um teto mensal não custa nada e evita surpresas.
  • Mantenha skills pequenas e com propósito único. Uma skill deve fazer uma coisa que o usuário nomearia em uma frase — verificar o clima ou definir um lembrete. Skills pequenas são testáveis e trocáveis de forma independente.

Como implantar sua própria versão

Há duas formas de colocar o projeto no ar:

  • Launch Stack em um passo: o template do CloudFormation aponta para uma imagem pública do Amazon Elastic Container Registry (Amazon ECR), então implanta com apenas um token do Telegram bot.
  • Build próprio: o script scripts/deploy.sh valida o template, constrói e envia sua própria imagem ARM64 para seu repositório privado do Amazon ECR, implanta o stack e registra o webhook do Telegram — para um build totalmente customizável.

O uso pessoal leve custa cerca de US$ 5–9/mês em julho de 2026 (aproximadamente US$ 2 de infraestrutura, US$ 1–3 de texto com Haiku e US$ 2 de visão com Sonnet), com um AWS Budget embutido que alerta em 80% e 100% do teto que você definir. O código-fonte completo está disponível no repositório GitHub sample-agentcore-memory-openclaw.

Limpeza do ambiente

Ao terminar os experimentos, a AWS recomenda remover todos os recursos para evitar cobranças contínuas. Como todo o sistema é um único stack do CloudFormation, a limpeza é basicamente uma única exclusão:

  • Exclua o stack do CloudFormation — isso remove o agente AgentCore runtime, o API Gateway, as funções Lambda, o agendamento do EventBridge e as funções do AWS Identity and Access Management (IAM) associadas.
  • Exclua o armazenamento de memória do AgentCore (e seus namespaces) para que nenhum registro de usuário seja retido.
  • Exclua as imagens enviadas para seu repositório privado do ECR e o próprio repositório, se não for mais necessário.
  • Remova o alerta do AWS Budget, se criado fora do stack.
  • Revogue o webhook do Telegram (ou exclua o bot pelo BotFather) e revogue o acesso ao modelo do Bedrock, se não for mais necessário.

Conclusão

O núcleo reutilizável desta solução é um agente serverless no Amazon Bedrock AgentCore com um sistema de skills e memória gerenciada. O AgentCore Memory elimina a necessidade de construir pipelines customizados de vetores e extração, enquanto mantém controle total sobre o que o agente lembra e esquece. O compute baseado em consumo combinado com prompt caching mantém um assistente genuinamente personalizado por poucos dólares por mês, e o manifesto de skills do OpenClaw torna o padrão portátil entre domínios.

A personalização também se compõe ao longo do tempo: quanto mais um usuário interage, mais útil o assistente se torna. Para ir além, a AWS sugere começar com um único domínio como lembretes de rega e expandir o escopo de memória incrementalmente, explorar memória episódica para que o agente possa referenciar conversas passadas específicas, ou fazer fork do repositório, trocar a persona e as skills, e construir o assistente que você precisar.

Para aprofundar nos componentes individuais, a AWS disponibilizou posts relacionados: Amazon Bedrock AgentCore memory: construindo agentes com contexto, Construindo agentes de IA mais inteligentes: deep dive na memória de longo prazo do AgentCore, Como usar o prompt caching no Amazon Bedrock de forma eficaz e Lançando e escalando agentes e ferramentas com segurança no Amazon Bedrock AgentCore runtime. Para a documentação oficial, consulte a documentação do AgentCore.

Fonte

Building a context-aware AI assistant on AgentCore and OpenClaw (https://aws.amazon.com/blogs/machine-learning/building-a-context-aware-ai-assistant-on-agentcore-and-openclaw/)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *