AWS ML ★ 79 6 min

Building a context-aware AI assistant on AgentCore and OpenClaw

Advanced (300)Amazon Bedrock AgentCoreTechnical How-to

🔗 https://aws.amazon.com/blogs/machine-learning/building-a-context-aware-ai-assistant-on-agentcore-and-openclaw/

📌 用 AgentCore 和 OpenClaw,打造記得住你的 AI 助理

TL;DR:AWS 展示如何用 Amazon Bedrock AgentCore 搭配開源 OpenClaw,做出會累積長期記憶的個人助理。

你三週前跟助理提過,你的花床排水太快,只用有機肥料,矮牽牛在熱浪中快撐不住了。今天你問「該怎麼照顧我的花」,它卻完全不記得這些事,要你從頭解釋一次。問題不在回答品質,而在助理沒有「你」的記憶。AWS 這篇文章用一個取名 Sprout 的園藝助理,示範如何解決這個問題。

🤔 無狀態助理的根本限制

多數現成 AI 助理擅長回答單一問題,但每次對話都是從零開始,把「重新解釋情境」的負擔丟給使用者。AWS 提出的做法是讓 OpenClaw(一套開源 agentic 系統)跑在 Amazon Bedrock AgentCore runtime 上,再透過 AgentCore memory 把「用過即丟的對話」變成「可持續查詢的知識」,並用結構化 metadata 標記記憶,讓助理只抓取跟當下問題相關的記錄。文中強調這個架構是領域無關的,換掉人格設定與技能清單,同一套 pipeline 就能變成客服機器人、健身教練或內部服務臺。

🧩 兩個入口,匯聚到同一個 agent

架構上,Telegram webhook 與 Amazon EventBridge Scheduler(例如晨間澆水提醒)是兩個獨立入口,分別透過 API Gateway + Lambda 和 cronjob Lambda,呼叫同一個 AgentCore runtime 的 InvokeAgentRuntime API。runtime 裡有一個精簡的 server.py 行程,負責協調 OpenClaw gateway、AgentCore memory,以及 Amazon Bedrock Converse API。其餘元件分工明確:Amazon S3 提供工作區儲存、AWS KMS 負責加密、AWS Secrets Manager 存放 bot token、Amazon CloudWatch 收集日誌與指標。整套系統只用一份 CloudFormation 範本,一行指令就能部署。

🧩 容器契約與文字/圖片雙路由

AgentCore runtime 的容器契約很單純:監聽 port 8080,提供 GET /ping 做健康檢查、POST /invocations 作為 agent 進入點。範例容器是 linux/arm64,以官方 OpenClaw 映像檔為基礎,再疊一層 Python 多階段建置。文字對話會走 OpenClaw gateway,帶著技能與 session 狀態;但圖片理解刻意繞過 gateway,改由 server.py 直接呼叫 Bedrock 的 LLM,把影像位元組作為多模態內容傳入——原因是容器內的 OpenClaw 版本會在送到 Bedrock 前把 image_url 內容區塊丟掉。兩條路徑共用同一份 system prompt(人格設定加記憶),維持體驗一致。模型 ID 透過 MODEL_ID、VISION_MODEL_ID 環境變數設定,換模型不用重新建置映像檔。

🧩 技能是設定檔,不是程式碼

能力以 community-skills.json 清單宣告,部署時的腳本會把技能寫進容器,並在建置映像檔前註冊到 OpenClaw 設定。Sprout 目前出廠內建天氣、提醒、植物筆記三種技能。換一份清單,同一套 pipeline 就能服務完全不同的領域,這也是作者強調這是「可重用模式」而不只是一個聊天機器人的原因。

🧩 為什麼選 Telegram

Telegram 是 webhook 式架構,整條鏈路都能維持無伺服器(serverless),不需要開發用戶端,使用者裝置上大多已經裝好,且原生支援文字、圖片與格式化文字。BotFather 發出的 bot token 存進 Secrets Manager,部署時把 webhook 註冊到 API Gateway 端點。文章也提到一個實務教訓:Telegram 舊版 markdown 對未轉義字元非常不寬容,模型回覆裡一個多出來的底線就可能讓整則訊息送不出去,所以助理會先把模型輸出轉成 Telegram 安全的 HTML 再發送。

💡 真正的差異化在 AgentCore memory

AgentCore memory 分兩層。短期記憶透過 CreateEvent 把每一回合對話存成事件,用 actorId(Telegram chat ID)與 sessionId 當 key,這是原始逐字稿。長期記憶則由管理式提取策略(managed extraction strategies)非同步運作,產生結構化、可長久保存的記錄,文中提到設定了三種策略。Sprout 把記錄分別寫入每個使用者各自的命名空間(namespace),因此不同聊天絕不會混在一起;chat ID 是唯一變動的區段,讓隔離性很容易驗證。每一回合,agent 都會檢索相關長期記錄、排序後注入 system prompt,而組裝步驟會讓「明確說過的偏好」排在「推論出來的事實」之前,同一類別內順序穩定,並在注入前做數量上限控制。命名空間回答「這是誰的記憶」,metadata 則回答「這段記憶在講什麼」。

📊 成本:消費制計價 vs. 常駐執行

AgentCore runtime 採消費制計價,只為 agent 實際耗用的運算付費,等待模型回應等 I/O 時間不計費。文中估算,個人輕量使用下,每月成本約 1-2 美元,相較之下一臺常駐執行的 Amazon EC2 執行個體約需 35 美元/月(以 2026 年 7 月的估算為準,實際費率請查 AgentCore pricing)。

🎯 實務啟示

這套架構的價值不是「發明了新東西」,而是把一個開源 agent 框架用一層薄薄的 server.py 包裝,套進 AgentCore 的容器契約,再用 AgentCore memory 補上「跨對話記憶」這塊長期缺口。如果你手上已經有一個能跑在本機行程的 agent 框架,這個 wrapper 模式幾乎可以直接複用,不需要改框架本身;真正值得抄的細節反而是記憶的分層設計與 metadata 排序邏輯,這對任何想做「有記憶的助理」的團隊都是現成的參考架構。

🔗 來源

#AWS #AmazonBedrock #AgentCore #OpenClaw #AIAgent #LLM #Telegram #AgenticAI #CloudArchitecture #MemoryAI

原始資料 AWS ML · 收集於 2026-10-06
來源原標題
Building a context-aware AI assistant on AgentCore and OpenClaw
作者
Thiago Verney
原始標籤
Advanced (300) · Amazon Bedrock AgentCore · Technical How-to
原始連結
https://aws.amazon.com/blogs/machine-learning/building-a-context-aware-ai-assistant-on-agentcore-and-openclaw/

摘要原文

Off-the-shelf AI assistants answer individual questions well, but they fall short on a different axis: continuity. Ask a stateless assistant about your garden today and it has no idea that you mentioned your fast-draining raised beds three weeks ago, that you only use organic fertilizer, or that your petunias were struggling through a heat wave. Every conversation starts from zero, and the burden of re-explaining context falls on the user. The problem isn’t the quality of the answers, but that the assistant has no memory of you. This post shows how to build a personal assistant that accumulates context using OpenClaw , an open source agentic system, running on AgentCore runtime, a capability of Amazon Bedrock AgentCore. AgentCore memory, a capability of Amazon Bedrock AgentCore, turns disposable chats into durable knowledge. You will also see how to tag those memories with structured metadata to retrieve records that matter for the question at hand. Our running example is Sprout, a gardening assistant, but the architecture is domain-agnostic. Swap the persona and the skills manifest, and the same pipeline serves a support bot, a fitness coach, or an internal help desk. The entire system lives in a single AWS CloudFormation template, deploys with one command, and runs on a consumption-based model that costs a few dollars a month for light personal use. Along the way, we share design guidelines you can apply to assistants you build on this stack. AgentCore is a platform to build, connect, and optimize agents at scale, with any framework or model. The following diagram shows the end-to-end request flow, from an inbound Telegram webhook through the AgentCore runtime, and its supporting AWS services. Figure 1: Telegram webhooks and Amazon EventBridge schedules both invoke the same AgentCore runtime agent, which coordinates the OpenClaw gateway, AgentCore memory, and Amazon Bedrock Two entry points converge on one agent. Telegram messages arrive through Amazon API Gateway and a webhook AWS Lambda function, while scheduled jobs such as morning watering reminders arrive through Amazon EventBridge Scheduler and a cronjob Lambda function. Both call the InvokeAgentRuntime API on the AgentCore runtime, where a thin server.py process coordinates the OpenClaw gateway, AgentCore memory, and the Amazon Bedrock Converse API. Amazon Simple Storage Service (Amazon S3) provides workspace storage, AWS Key Management Service (AWS KMS) handles encryption, AWS Secrets Manager holds the bot token, and Amazon CloudWatch captures logs and metrics. To deploy your own version using the Launch Stack button or scripts/ deploy.sh (described in the Grow your own section), you will need: Every component lives in a single CloudFormation template, and no build tooling is required to launch. The following sections walk through the load-bearing decisions. The agent lives in a container on AgentCore runtime, which uses consumption-based pricing. You’re billed for the compute your agent actively consumes, not for wall-clock uptime, and you don’t pay for the time when waiting for I/O such as model response. For a personal assistant used in short bursts, that is the difference between an approximately $1–2/month baseline and an approximately $35/month always-on Amazon Elastic Compute Cloud (Amazon EC2) instance. These figures are estimates for light personal use as of July 2026. Refer to AgentCore pricing for current rates. The runtime enforces a minimal container contract: listen on port 8080, and expose GET /ping for health and POST /invocations as the agent entry point. Our container is linux/arm64 , built multi-stage from the official OpenClaw image plus a Python layer. OpenClaw provides the agent loop, tool use, and a skills system. It runs a wrapper ( server.py ) that adapts it to AgentCore HTTP protocol contract : This wrapper pattern generalizes to other use cases. Any agent framework that runs as a local process can be adapted to the AgentCore runtime the same way, without modifying the framework itself. Text chat and image understanding have different cost and quality tradeoffs, so the assistant routes them to different Claude models on Bedrock : Text turns flow through the OpenClaw gateway, which brings skills and session state. Image turns call the large language model (LLM) from Bedrock directly from server.py , passing the image bytes as multimodal content blocks. We route images around the gateway deliberately: the in-container OpenClaw build dropped the image_url content parts before they reached Bedrock, so calling the Converse API directly from server.py makes sure the model sees the actual pixels. Both paths share the same system prompt (persona plus memory), so the experience stays consistent. The model IDs are environment variables ( MODEL_ID , VISION_MODEL_ID ), so you can swap models per deployment without rebuilding the image. Capabilities are declared as skills in a community-skills.json manifest. A deploy-time script materializes them into the container and registers them in the OpenClaw config before the image is built. Sprout ships with weather, reminders, and plant notes skills at the time of publishing this post. Swap the manifest and the same pipeline serves a different domain. This is what makes the whole thing a reusable pattern and not only one bot. Telegram is a practical channel for a personal assistant since it’s webhook-based, and it keeps everything serverless. It requires no client development, works on every device the user already owns, and supports text, images, and rich formatting through a straightforward bot API. BotFather issues a bot token, which is stored in Secrets Manager. The deployment registers a webhook that points Telegram at the API gateway endpoint. When the user sends a message, Telegram delivers it to the webhook Lambda function to validate the payload and call InvokeAgentRuntime . The reply travels back through the telegram bot API. One formatting lesson to note: Telegram’s legacy markdown model is unforgiving about unescaped characters and a single stray underscore in a model response can make the whole message fail to send. Rendering replies as HTML is reliable so the assistant converts model output to Telegram-safe HTML before sending. The architecture described so far is a capable, cheap, serverless agent, but on its own it still forgets you between conversations. Memory is what changes that. Imagine mentioning weeks ago that you garden organically, and today the assistant recommends a treatment and adds, on its own, that it picked the organic option because you don’t use synthetic fertilizer. A stateless model can’t do that. AgentCore memory has two layers. Short-term memory stores every conversation turn as an event through CreateEvent , keyed by actorId (the Telegram chat ID) and sessionId . This is the raw transcript. Long-term memory is produced asynchronously by managed extraction strategies into durable, structured records. We configured three strategies: Sprout files records into per-user namespaces, so no two chats ever mix: The chat ID is the only variable segment, which makes isolation straightforward to reason about and to test: each unique gardener maps to exactly one namespace, and no two gardeners collide. On every turn, the agent retrieves the relevant long-term records, ranks them, and injects them into the system prompt. Here is what happens on every single message, inside server.py : Snippet 1: Retrieving long-term records for the current turn (representative. See the repo for full source). Assemble function adds additional custom logic. We want the explicit preferences to rank ahead of inferred facts, order is stable within each class, and the result is capped before injection: Snippet 2: The assembly step ranks explicit preferences before inferred facts. Namespaces answer whose memory a record is, but metadata answers what it’s about.

由 claude-code/sonnet 自動生成