展示如何在 Amazon Bedrock AgentCore 运行时上用 OpenClaw 构建带上下文累积的个人助手,将临时对话转为可按元数据过滤的持久结构化知识。
现成的 AI 助手能很好地回答单个问题,但在另一个维度上存在不足:连续性。今天向一个无状态的助手询问你花园的情况,它完全不知道你三周前提到过排水很快的升高苗床、你只用有机肥,或者你的矮牵牛花经历了热浪而苦苦挣扎。每次对话都从零开始,重新解释上下文的负担落在用户身上。
问题不在于答案的质量,而在于助手对你没有任何记忆。本文展示如何使用 OpenClaw(一个开源的智能体系统)构建一个利用 AgentCore memory(Amazon Bedrock AgentCore 的一项能力)积累上下文的个人助手。AgentCore memory 将可丢弃的聊天转化为持久化的知识。你还将看到如何用结构化元数据标记这些记忆,以便检索对当前问题重要的记录。
我们的演示示例是一个园艺助手 Sprout,但其架构是与领域无关的。更换角色设定和技能清单,同样的流程可以服务于支持机器人、健身教练或内部服务台。整个系统存在于一个 AWS CloudFormation 模板中,只需一条命令即可部署,并运行在按需付费模式上,轻度个人使用每月仅需几美元。在此过程中,我们分享的设计指南可应用于你在此技术栈上构建的其他助手。
AgentCore 是一个在大规模上构建、连接和优化智能体的平台,支持任何框架或模型。下图展示了端到端的请求流程:从入站 Telegram Webhook 通过 AgentCore runtime 及其支持的 AWS 服务。
图 1:Telegram Webhook 和 Amazon EventBridge 调度程序都调用同一个 AgentCore runtime 智能体,该智能体协调 OpenClaw 网关、AgentCore memory 和 Amazon Bedrock
两个入口点汇聚到一个智能体。Telegram 消息通过 Amazon API Gateway 和 Webhook Lambda 函数到达,而定时任务(如早晨浇水提醒)通过 Amazon EventBridge Scheduler 和 cronjob Lambda 函数到达。两者都调用 AgentCore runtime 上的 InvokeAgentRuntime API,在那里一个轻薄的 server.py 进程协调 OpenClaw 网关、AgentCore memory 和 Amazon Bedrock Converse API。Amazon Simple Storage Service(Amazon S3)提供工作区存储,AWS Key Management Service(AWS KMS)处理加密,AWS Secrets Manager 保存机器人令牌,Amazon CloudWatch 捕获日志和指标。
要使用 Launch Stack 按钮或 scripts/deploy.sh(详见"构建你自己的"部分)部署你自己的版本,你需要:
每个组件都存在于一个 CloudFormation 模板中,启动时不需要任何构建工具。以下部分将介绍关键的架构决策。
智能体运行在 AgentCore runtime 上的容器中,采用按需付费定价。你只需为智能体实际消耗的计算付费,而不是为挂钟时间付费,在等待 I/O(如模型响应)时不收费。对于以短时burst方式使用的个人助手,这与每月约 1–2 美元的基础费用和每月约 35 美元的始终开启的 Amazon Elastic Compute Cloud(Amazon EC2)实例之间的区别。这些数字是截至 2026 年 7 月轻度个人使用的估算。请参阅 AgentCore 定价了解当前费率。
Runtime 强制执行一个最小容器契约:在端口 8080 上监听,并通过 GET /ping 提供健康检查和 POST /invocations 作为智能体入口点。我们的容器是 linux/arm64,从官方 OpenClaw 镜像加上 Python 层多阶段构建。
OpenClaw 提供智能体循环、工具使用和技能系统。它运行一个包装器(server.py),将其适配到 AgentCore HTTP 协议契约:
这种包装器模式可推广到其他用例。任何作为本地进程运行的智能体框架都可以以相同方式适配到 AgentCore runtime,而无需修改框架本身。
文本聊天和图像理解具有不同的成本和质量权衡,因此助手将它们路由到 Bedrock 上不同的 Claude 模型:
文本轮次通过 OpenClaw 网关流动,该网关带来技能和会话状态。图像轮次直接从 server.py 调用 Bedrock 上的大语言模型(LLM),将图像字节作为多模态内容块传递。我们有意将图像绕过网关路由:容器内的 OpenClaw 构建在图像到达 Bedrock 之前丢弃了 image_url 内容部分,因此从 server.py 直接调用 Converse API 可以确保模型看到实际像素。两条路径共享相同的系统提示词(角色设定加记忆),因此体验保持一致。
模型 ID 是环境变量(MODEL_ID、VISION_MODEL_ID),因此你可以在每次部署时更换模型而无需重建镜像。
能力在 community-skills.json 清单中声明为技能。部署时脚本将它们物化到容器中,并在镜像构建之前在 OpenClaw 配置中注册。Sprout 在发布时附带天气、提醒和植物笔记技能。更换清单,同样的流程即可服务不同领域。这使得整个系统成为可重用模式,而非仅仅是一个机器人。
Telegram 是个人助手的实用渠道,因为它基于 Webhook,保持一切无服务器。它不需要客户端开发,在用户已有的每台设备上都能运行,并通过简单的机器人 API 支持文本、图像和富格式。BotFather 发放机器人令牌,存储在 Secrets Manager 中。部署注册一个指向 API Gateway 端点的 Webhook。当用户发送消息时,Telegram 将其传送到 Webhook Lambda 函数以验证负载并调用 InvokeAgentRuntime。回复通过 Telegram 机器人 API 返回。
一个格式化经验需要注意:Telegram 的传统 Markdown 模式对未转义字符毫不宽容,模型响应中单个杂散的下划线可能导致整个消息发送失败。渲染为 HTML 是可靠的,因此助手在发送前将模型输出转换为 Telegram 安全的 HTML。
到目前为止描述的架构是一个有能力的、廉价的无服务器智能体,但就其本身而言,它仍然会在对话之间忘记你。记忆改变了这一点。想象一下,几周前提到你实行有机园艺,今天助手推荐了一种处理方法,并主动补充说它选择了有机方案,因为你不使用合成肥料。无状态模型无法做到这一点。
AgentCore memory 有两层。短期记忆通过 CreateEvent 将每个对话轮次存储为事件,以 actorId(Telegram 聊天 ID)和 sessionId 为键。这是原始记录。长期记忆通过托管提取策略异步生成,转化为持久的结构化记录。我们配置了三种策略:
SUMMARIZATION:情景会话摘要("讨论了热浪期间下部叶片发黄的问题")。
命名空间:一个园丁一个花园
Sprout 将记录写入每个用户独立的命名空间,因此任意两条聊天记录绝不会混淆:
sprout/{chat_id}/long_term:用户偏好和语义事实。
sprout/{chat_id}/episodic/{session_id}:会话摘要。
聊天 ID 是唯一的可变段,这使得隔离逻辑易于推理和测试:每个不同的园丁精确映射到一个命名空间,且任意两个园丁之间不会产生冲突。
在每个回合中,智能体检索相关的长期记录、对其进行排序,然后注入到系统提示词中。以下是 server.py 中每条消息的处理流程:
检索。 针对 sprout/{chat_id}/long_term 调用 RetrieveMemoryRecords,用用户消息作为搜索查询,最多返回 50 条结果,预算时间为 3 秒。如果检索超时或出错,系统会优雅降级,在没有记忆的情况下回答,而不会失败。
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
代码片段 1:检索当前回合的长期记录(代表性代码,完整源码见仓库)。
组装 函数添加了额外的自定义逻辑。我们希望显式偏好优先于推断事实,每类内部顺序稳定,并在注入前对结果进行截断:
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]
代码片段 2:组装步骤将显式偏好排在推断事实之前。
命名空间回答的是"谁的记忆",而元数据回答的是"它是关于什么的"。在 sprout/{chat_id}/long_term 内,语义搜索"我的矮牵牛正在枯萎"会返回所有语义相近的内容。对于园丁来说,这意味着三月份的肥料偏好和关于无花果修剪的笔记会和实际重要的记录一起被排名。而结构化的元数据帮助我们在记忆进入提示词之前缩小其范围。
一条规则决定了此处的所有决策。元数据键只有在声明为索引键时才能在服务器端过滤。你可以在 Amazon Bedrock AgentCore Memory 的结构化记忆过滤:使用元数据中阅读更多内容。在这种情况下,Sprout 使用三个索引键:
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
每个条目命名一个键(必须与某个索引键匹配才能被过滤),并设置 extractionType 为 STRICTLY_CONSISTENT(直接从事件传递)或 LLM_INFERRED(从对话中提取)。对于推断的键,提取配置可以将值限制为固定列表。Sprout 正是这样做的,因此两种写入路径会创建相同的词汇表,且过滤器无论由哪部分创建记录都表示相同的含义。
在模型响应后,server.py 调用 CreateEvent,传入用户回合和助手回合。这个新事件会馈送到提取策略,以在下一次丰富长期存储。
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
代码片段 3:持久化回合,以便提取策略可以异步丰富长期记忆。
提取是异步的,因此本次会话中提到的事实通常在后续会话中才可被检索。针对该延迟进行设计:短期会话事件覆盖当前对话,长期记录覆盖此前的一切。
这才是完整管道端到端工作的场景。在几次对话中,你用日常语言逐棵植物地记录整个花园。每次提及都会成为一个事件。提取策略将关于植物、位置和阳光照射的信息提取到 sprout/{chat_id}/long_term。今天早上用户问了一个问题:"你还记得我花园里的其他植物吗?" 检索拉取记录,组装对其进行排序,然后它们进入系统提示词。助手根据用户的位置、阳光照射、花坛构造、土壤特性和植物清单来回答,这些信息在消息本身中都没有出现。
图 2:Sprout 通过回忆存储的植物清单和生长条件来回答关于花园的问题
使用 Amazon EventBridge → Cron 路径上的调度器技能,Sprout 还可以将计划转化为主动提醒("跳过草本植物,土壤昨天还很湿"),并在雨天或热浪来袭时根据天气技能进行调整。
记忆与视觉也会相互增强。当用户发送枯萎植物的照片时,图像会被发送到 Claude Sonnet 4.5,同时系统提示词仍携带记忆层知道的所有信息。助手将照片与用户已保存清单中的墨西哥矮牵牛进行匹配,并在上下文中诊断萎蔫压力,而不是冰冷地分析一张匿名植物照片。
图 3:视觉与记忆协同工作。照片发送给视觉模型,而系统提示词携带用户的存储花园上下文
视觉模型并非绝对可靠。在早期没有清单上下文的对话中,同一株植物被自信地识别为牵牛花——一种具有相似喇叭状紫色花朵的物种。用用户自己存储的清单为视觉模型提供 grounding,将一个看似合理但错误的猜测转变为了正确、个性化的诊断,这很好地说明了为什么记忆不仅改善语气,还能提高准确性。
在每个回合向系统提示词注入记忆会使其体积庞大,天真的实现会为每次请求支付这些 token 的费用。Amazon Bedrock 上的提示词缓存解决了这个问题。助手将其提示词结构化,使得稳定前缀(角色设定和组装的记忆块)位于最前,变化的用户消息位于最后。Bedrock 跨请求缓存处理后的前缀,因此会话内的重复回合跳过未变化部分的重新计算。对于支持的模型,提示词缓存最高可减少 90% 的成本和 85% 的延迟。
排序规则比任何单个设置都更重要:稳定内容优先,变化内容最后,并保持记忆块内部的排序确定性(前面的 assemble 函数有助于实现这一点),这样前缀才能在请求之间实际匹配。
Sprout 是一个助手,但其背后的决策具有通用性。如果你在此技术栈上构建自己的助手,以下是我们会带入任何领域的指南。
包装,而非 fork。 用一个薄的 HTTP 包装器将你的智能体框架适配到 AgentCore 容器契约,而不是修改框架本身。契约很小:8080 端口,/ping 和 /invocations 端点,包装器让你保持在框架的升级路径上。
在存储任何东西之前先设计命名空间。 内存命名空间是你的隔离边界。让用户 ID 成为唯一的可变段,并从你已经信任的渠道原生 ID(如聊天 ID)中选择它。多租户设计最终会有审计和删除请求。清晰的命名空间方案使两者都变得微不足道。
将记忆视为增强,而非依赖。 每个记忆操作都应该能够优雅地失败。检索失败应该产生无记忆的回答,而不阻塞回复。用户远比一次失败的请求更容易原谅一次健忘的回合。
按任务路由模型。 对高容量文本使用快速、成本效益高的模型,只在需要的回合保留更强的多模态模型。将模型 ID 放在环境变量中,这样路由变更就是配置而非代码。
为缓存优化提示词顺序。 稳定的角色设定和记忆在前,变化的用户输入在后,全程保持确定的排序。这一结构性习惯是大部分推理成本节省的来源。
Plan for extraction latency. Long-term memory is extracted asynchronously, so don't promise same-session recall of new facts. Let short-term session events cover the current conversation and long-term records cover prior ones.
为提取延迟做好规划。长期记忆是异步提取的,所以不要承诺在同一会话内就能回想起新事实。让短期会话事件覆盖当前对话,让长期记录覆盖之前的对话。
Put a budget on it from day one. A consumption-based agent is inexpensive until a retry loop or a chatty user makes it otherwise. An AWS Budgets alert at 80 percent and 100 percent of a monthly cap costs nothing and catches surprises early.
从第一天就设置预算。基于用量计费的 AI 智能体在出现重试循环或话痨用户之前并不贵。在月度上限的 80% 和 100% 处设置 AWS Budgets 告警无需任何成本,却能及早发现问题。
Keep skills small and single-purpose. A skill should do one thing a user would name in a sentence, such as check the weather or set a reminder. Small skills are independently testable, independently swappable, and easy for the model to select correctly. A do-everything skill forces the model to guess which of its behaviors you meant.
保持技能小而单一职责。一个技能应该只做用户能用一句话描述的一件事,比如查天气或设提醒。小技能可以独立测试、独立替换,模型也更容易正确选择。一个包揽一切的技能会迫使模型猜测你指的是它的哪种行为。
Two ways to plant it, same garden:
两种安装方式,同一套架构:
Single-step Launch Stack: the CloudFormation template points at a public Amazon Elastic Container Registry (Amazon ECR) image, so it deploys nothing but a Telegram bot token.
单步启动栈:CloudFormation 模板指向一个公开的 Amazon Elastic Container Registry (Amazon ECR) 镜像,因此它只部署一个 Telegram bot token。
Build your own: The scripts/deploy.sh script validates the template, builds and pushes your own ARM64 image to your private Amazon ECR repository, deploys the stack, and registers the Telegram webhook, for a fully customizable build.
自行构建:scripts/deploy.sh 脚本会验证模板、将你自己的 ARM64 镜像构建并推送到你的私有 Amazon ECR 仓库、部署栈并注册 Telegram webhook,实现完全可定制的构建。
Light personal use runs about $5–9/month as of July 2026 (roughly $2 infrastructure, $1–3 Haiku text, $2 Sonnet vision), with a built-in AWS Budget that alerts at 80 percent and 100 percent of a cap you set.
截至 2026 年 7 月,轻量个人使用费用约为每月 5–9 美元(约 2 美元基础设施、1–3 美元 Haiku 文本、2 美元 Sonnet 视觉),内置的 AWS Budget 会在你设定的上限的 80% 和 100% 处发送告警。
The full source code is available in the sample-agentcore-memory-openclaw GitHub repository.
完整源代码可在 sample-agentcore-memory-openclaw GitHub 仓库中获取。
When you are done experimenting, tear everything down to avoid ongoing charges. Because the whole system is one CloudFormation stack, cleanup is mostly a single delete:
实验结束后,拆除所有资源以避免持续产生费用。因为整个系统是一个 CloudFormation 栈,清理基本上只需一次删除:
Delete the CloudFormation stack. This removes the AgentCore runtime agent, API Gateway, the Lambda functions, the Amazon EventBridge schedule, and the associated AWS Identity and Access Management (IAM) roles.
删除 CloudFormation 栈。这会移除 AgentCore 运行时 agent、API Gateway、Lambda 函数、Amazon EventBridge 计划以及相关的 AWS Identity and Access Management (IAM) 角色。
Delete the AgentCore memory store (and its namespaces) so no user records are retained.
删除 AgentCore 记忆存储(及其命名空间),确保不保留任何用户记录。
Delete any images you pushed to your private ECR repository, and the repository itself if it's no longer needed.
删除你推送到私有 ECR 仓库的任何镜像,如果不再需要该仓库则一并删除。
Remove the AWS Budget alert if you created one outside the stack.
如果在栈外创建了 AWS Budget 告警,将其移除。
Revoke Telegram's webhook (or delete the bot through BotFather), and revoke Bedrock model access if you no longer need it.
撤销 Telegram 的 webhook(或通过 BotFather 删除机器人),如果不再需要则撤销 Bedrock 模型访问权限。
The reusable core of this solution is a serverless agent on Amazon Bedrock AgentCore with a skills system and managed memory. AgentCore memory removes the need to build custom vector stores and extraction pipelines while leaving you full control over what the agent remembers and forgets, consumption-based compute plus prompt caching keeps a genuinely personalized assistant at a few dollars a month, and the OpenClaw skills manifest makes the whole pattern portable across domains. Personalization also compounds: the more a user interacts, the more useful the assistant becomes.
该方案的可复用核心是一个基于 Amazon Bedrock AgentCore 的无服务器 AI 智能体,配备了技能系统和托管记忆。AgentCore 记忆功能无需构建自定义向量存储和提取管道,同时让你完全控制 AI 智能体记忆和遗忘的内容,基于用量的计算加上 prompt 缓存将一个真正个性化的助手每月费用控制在几美元,而 OpenClaw 技能清单使整个模式可跨领域移植。个性化还会产生复合效应:用户交互越多,助手就越有用。
To go further, start with a single domain such as watering reminders and expand memory scope incrementally, explore episodic memory so the agent can reference specific past conversations ("last time we discussed the fig tree, you decided to hold off on fertilizer"), or fork the repository, swap in your own persona and skills, and grow whatever assistant you need.
要进一步探索,可以从一个单一领域开始(如浇水提醒),然后逐步扩展记忆范围;探索情景记忆,让 AI 智能体能够引用特定的过往对话("上次我们讨论无花果树时,你决定暂缓施肥");或者 fork 该仓库,换上你自己的角色和技能,构建你所需的任何助手。
To learn more, refer to the AgentCore documentation. The following related posts cover the building blocks in more depth:
更多内容请参阅 AgentCore 文档。以下相关文章更深入地介绍了各个构建模块:
Amazon Bedrock AgentCore memory: Building context-aware agents
Amazon Bedrock AgentCore 记忆:构建上下文感知的 AI 智能体
Building smarter AI agents: AgentCore long-term memory deep dive
构建更智能的 AI 智能体:AgentCore 长期记忆深度解析
Effectively use prompt caching on Amazon Bedrock
在 Amazon Bedrock 上有效使用 prompt 缓存
Securely launch and scale your agents and tools on Amazon Bedrock AgentCore runtime
在 Amazon Bedrock AgentCore 运行时上安全地启动和扩展你的 AI 智能体及工具