Building a context-aware AI assistant on AgentCore and OpenClaw

TL;DR · AI 摘要
Building a context-aware AI assistant on AgentCore and OpenClaw Artificial Intelligence Building a context-aware AI assi...
核心要点
- 主题聚焦:Building a context-aware AI assistant on AgentCo
- 来源:AWS Machine Learning Blog,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
在AgentCore和OpenClaw上构建上下文感知的AI助手 | 人工智能
在AgentCore和OpenClaw上构建上下文感知的AI助手
现成的AI助手在回答单个问题方面表现良好,但在另一个维度上存在不足:连续性。向无状态助手询问你花园的情况时,它不知道你三周前提到过排水迅速的抬高种植床,你只使用有机肥料,或者你的矮牵牛花在热浪中挣扎过。每次对话都从零开始,重新解释上下文的负担落在用户身上。
问题不在于答案的质量,而在于助手没有记住你。本文将展示如何使用OpenClaw(一个开源的智能代理系统)和AgentCore运行时(Amazon Bedrock AgentCore的一项功能)构建一个能够积累上下文的个人助手。Amazon Bedrock AgentCore的AgentCore内存功能将一次性对话转化为持久知识。你还将看到如何使用结构化元数据标记这些记忆,以检索与当前问题相关的记录。
我们的运行示例是Sprout(一个园艺助手),但该架构与领域无关。只需更换角色和技能清单,相同的流程即可服务于支持机器人、健身教练或内部帮助台。整个系统包含在一个AWS CloudFormation模板中,通过一个命令即可部署,并基于按使用量计费的模式运行,轻量级个人使用每月仅需几美元。在过程中,我们将分享你可以应用到基于此架构构建的助手上的设计指南。
解决方案概述
AgentCore是一个平台,用于大规模构建、连接和优化代理,支持任何框架或模型。下图展示了端到端请求流程,从传入的Telegram网络钩子通过AgentCore运行时及其支持的AWS服务。
图1:Telegram网络钩子和Amazon EventBridge计划都会调用同一个AgentCore运行时代理,该代理协调OpenClaw网关、AgentCore内存和Amazon Bedrock
两个入口点汇聚到一个代理上。Telegram消息通过Amazon API Gateway和一个网络钩子AWS Lambda函数到达,而计划任务(如早晨浇水提醒)则通过Amazon EventBridge计划器和一个定时任务Lambda函数到达。两者都调用AgentCore运行时上的InvokeAgentRuntime API,其中薄的server.py进程协调OpenClaw网关、AgentCore内存和Amazon Bedrock Converse API。Amazon简单存储服务(Amazon S3)提供工作区存储,AWS密钥管理服务(AWS KMS)处理加密,AWS Secrets Manager保存机器人令牌,Amazon CloudWatch捕获日志和指标。
先决条件
要使用“启动堆栈”按钮或脚本/deploy.sh(在“自己种植”部分描述)部署你自己的版本,你需要:
- Amazon Bedrock AgentCore的访问权限,包括AgentCore运行时和AgentCore内存。
- 为计划路由的模型授予访问权限:文本使用Claude Haiku 4.5,视觉使用Claude Sonnet 4.5(或你账户中可用的等效模型)。
- 带有linux/arm64构建支持的Docker,以及配置好的AWS命令行界面(AWS CLI)。如果你计划构建和推送自己的镜像,则需要此配置。
- 一个Telegram机器人令牌(来自BotFather),作为助手的前端门。
- 对代理编排概念和CloudFormation的基本了解。
架构:基于 AgentCore 运行时的无服务器代理
每个组件都包含在一个 CloudFormation 模板中,无需任何构建工具即可启动。以下部分将逐步介绍关键设计决策。
AgentCore 运行时:仅对实际计算付费
代理运行在 AgentCore 运行时的容器中,采用按使用量计费模式。您仅需为代理实际消耗的计算资源付费,而非基于墙钟时间的持续运行时长,且在等待 I/O(如模型响应)期间无需付费。对于短时使用的个人助手,这使得每月成本从约 1-2 美元的基础费用,与始终运行的 Amazon EC2 实例(约 35 美元/月)形成显著差异。这些数据为 2026 年 7 月轻度个人使用场景的估算值,具体费率请参考 AgentCore 官方定价。
运行时强制要求容器满足最低契约:监听 8080 端口,并暴露 GET /ping 健康检查接口和 POST /invocations 作为代理入口点。我们的容器为 linux/arm64 架构,基于官方 OpenClaw 镜像和 Python 分层构建。
OpenClaw 作为代理基底
OpenClaw 提供代理循环、工具调用和技能系统。它运行一个包装器(server.py),用于适配 AgentCore HTTP 协议契约:
- 容器启动时,server.py 启动 openclaw gateway 作为子进程并执行健康检查。
- GET /ping 快速返回健康状态,使 AgentCore 就绪探针通过。
- POST /invocations 执行实际工作:解析负载、检索内存、构建上下文、将对话转发给网关并持久化结果。特别说明:AgentCore 可以解冻子进程已退出的容器。因此调用路径不假设网关处于活动状态,而是调用 ensure_openclaw_ready() 辅助函数,在转发对话前重新检查健康状态(必要时重启网关)。
这种包装器模式可扩展到其他使用场景。任何以本地进程运行的代理框架均可通过相同方式适配到 AgentCore 运行时,无需修改框架本身。
按任务路由的两个模型
文本聊天和图像理解在成本和质量上存在不同权衡,因此助手会根据任务类型路由到 Bedrock 上不同的 Claude 模型:
- Claude Haiku 4.5(文本):针对高频日常对话场景,提供快速且低成本的处理能力。
- Claude Sonnet 4.5(视觉):针对较少但更复杂的任务(如通过照片诊断植物),提供更强的多模态推理能力。
文本对话通过 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 作为无服务器前端入口
Telegram 是个人助手的理想渠道,因其基于 Webhook 的特性可实现完全无服务器架构。它无需客户端开发,兼容用户已有的所有设备,且通过简洁的 Bot API 支持文本、图片和富文本格式。BotFather 会颁发 Bot 令牌并存储于 Secrets Manager。部署流程会注册一个 Webhook,将 Telegram 指向 API 网关端点。当用户发送消息时,Telegram 会将消息传递给 Webhook 的 Lambda 函数进行负载验证并调用 InvokeAgentRuntime。回复内容通过 Telegram Bot API 返回。
一个格式注意事项:Telegram 的传统 Markdown 模式对未转义字符极为严格,模型响应中若出现单个未转义下划线可能导致整条消息发送失败。因此建议将回复内容渲染为 HTML 格式,助手会在发送前将模型输出转换为 Telegram 兼容的 HTML 格式。
记忆:将临时对话转化为持久知识
前述架构已实现功能强大、成本低廉的无服务器代理,但单独使用时仍会在对话间遗忘用户信息。记忆功能将改变这一现状。设想数周前你提到采用有机种植,今天助手推荐治疗方案时会主动补充"我选择了有机方案,因为您不使用化学肥料"。无状态模型无法实现这种记忆能力。
认知模型:短期事件与长期提取
AgentCore 记忆系统包含两个层级。短期记忆通过 CreateEvent 接口将每次对话回合存储为事件,以 actorId(Telegram 聊天 ID)和 sessionId 作为键。这是原始对话记录。长期记忆则通过托管提取策略异步生成结构化记录。我们配置了三种策略:
- USER_PREFERENCE:园艺师明确声明的偏好("我只使用有机肥料")。
- SEMANTIC:推断出的事实("在 Corten 钢种植箱中种植墨西哥矮牵牛")。
- SUMMARIZATION:会话摘要("讨论了热浪期间下层叶片发黄问题")。
命名空间:每个园艺师对应独立花园
Sprout 将记录存储在用户专属命名空间中,确保任何对话不会相互干扰:
- sprout/{chat_id}/long_term:存储偏好和语义事实。
- sprout/{chat_id}/episodic/{session_id}:存储会话摘要。
chat_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 = [] # 回退到不使用记忆直接回答片段1:为当前回合检索长期记录(代表性示例,完整代码请参见仓库)。
Assemble 函数添加了额外的自定义逻辑。我们希望显式偏好优先于推断事实,同一类别内的顺序稳定,并在注入前对结果进行限制:
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']
# 显式优先于推断;同一类别内顺序稳定
ordered = explicit + inferred
return ordered[:cap]片段2:组装步骤将显式偏好排在推断事实之前。
元数据:在命名空间内对记忆进行子分组
命名空间用于标识记录属于哪个记忆,但元数据用于说明记录的内容。在 sprout/{chat_id}/long_term 内,对“我的天竺葵正在枯萎”进行语义搜索,会返回所有语义相近的内容。对于园艺师来说,这意味着三月的肥料偏好和无花果树修剪记录会与真正相关的记录并列。而结构化元数据帮助我们在内容到达提示前缩小记忆范围。
这里有一个规则决定了所有决策。只有在声明为索引键时,元数据键才能在服务器端进行过滤。你可以在《Amazon Bedrock AgentCore Memory 中的结构化记忆过滤》中了解更多。在此案例中,sprout 使用了三个索引键:
IndexedKeys: # 在 AWS::BedrockAgentCore::Memory 资源中
- Key: type # 区分记录类型
Type: STRING
- Key: section # 描述的床或区域
Type: STRING
- Key: plants # 生长的植物
Type: STRINGLIST每个条目命名一个键,该键必须匹配索引键才能进行过滤,并将提取类型设置为 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},
],
) # 触发 USER_PREFERENCE / SEMANTIC / SUMMARIZATION 提取;错误会被记录,但不会导致致命问题片段3:持久化当前回合,使提取策略能够异步丰富长期记忆。
信息提取是异步进行的,因此当前对话中提到的事实通常会在后续对话中变得可检索。设计时需考虑这种延迟:短期会话事件覆盖当前对话内容,而长期记录则涵盖所有历史信息。
综合应用:定制化浇水方案
现在来看完整流程如何端到端运作。通过几次对话,你可以用自然语言逐个记录整个花园的信息,每个提及的内容都会生成一个事件。提取策略将植物信息、位置和光照条件提取到 sprout/{chat_id}/long_term 目录中。今天早上用户提问:"你还记得我花园里的其他植物吗?" 检索模块会调取历史记录,组装模块进行排序,这些信息随后进入系统提示。助手的回答包含用户的位置、光照情况、种植床结构、土壤特性以及植物清单,这些信息在原始消息中均未出现。
图2:Sprout通过调取存储的植物清单和生长条件来回答关于花园的问题
通过在Amazon EventBridge的Cron路径上使用调度技能,Sprout还能将该计划转化为主动提醒("跳过香草植物,土壤仍残留昨日的湿润"),并在遇到降雨或热浪时,根据天气技能自动调整提醒。
记忆与视觉能力会相互增强。当用户发送一张枯萎植物的照片时,图像会被传送到Claude Sonnet 4.5模型进行分析,而系统提示中仍然包含记忆层掌握的所有信息。助手能将照片与用户已保存清单中的墨西哥矮牵牛匹配,并结合上下文诊断出萎蔫压力,而非对一张孤立的植物照片进行冷启动分析。
图3:视觉与记忆协同工作。照片发送给视觉模型,而系统提示中包含用户存储的花园上下文信息
视觉模型并非完美无误。在之前没有库存上下文的对话中,同一种植物被自信地识别为牵牛花,这是一种具有相似喇叭状紫色花朵的物种。通过将用户的库存信息作为视觉模型的基准,使一个看似合理的猜测变成了准确的个性化诊断,这很好地说明了为什么记忆能提升准确率而不仅仅是语气。
通过提示缓存降低推理成本
将记忆注入每次交互会使系统提示变得庞大,粗暴的实现方式会在每次请求时都支付这些token的费用。Amazon Bedrock的提示缓存功能解决了这个问题。助手将提示结构化为:先放置稳定的前缀(包括角色设定和组装后的记忆块),最后放置易变的用户消息。Bedrock会在不同请求间缓存处理后的前缀,因此对话中的重复交互可以跳过未变化部分的重新计算。对于支持的模型,提示缓存可将成本降低高达90%,延迟降低高达85%。
排序规则比任何单一设置都更重要:始终将稳定内容放在前面,易变内容放在最后,并保持记忆块内部排序的确定性(如前述的组装函数所实现的),这样才能确保不同请求间的前缀真正匹配。
基于AgentCore和OpenClaw的架构设计指南
Sprout只是一个示例助手,但其背后的设计原则具有普适性。如果你正在基于这套架构构建自己的助手,以下指南适用于任何领域:
- 封装,而非分支。通过一个轻量的 HTTP 封装器将您的代理框架适配到 AgentCore 容器契约,而不是修改框架本身。契约内容简单,仅需开放 8080 端口的 /ping 和 /invocations 接口,封装方式能确保您始终跟上框架的升级路径。
- 在存储任何数据前先设计命名空间。内存命名空间是您的隔离边界。应将用户 ID 设为唯一变量段,并从您已信任的渠道原生 ID(如聊天 ID)中选取。多租户设计最终都会面临审计和删除请求,清晰的命名空间方案能让这些操作变得简单直接。
- 将内存视为增强功能而非依赖项。每个内存操作都应允许优雅失败。检索失败时应生成无记忆依赖的回复,而非阻塞响应。用户对遗忘的容忍度远高于对失败的容忍度。
- 按任务路由模型。使用快速且成本效益高的模型处理高流量文本,将更强大的多模态模型保留给需要的场景。将模型 ID 存储在环境变量中,使路由变更成为配置问题而非代码问题。
- 为缓存优化提示顺序。先稳定的人格和记忆,后易变的用户输入,全程保持确定性顺序。这种结构性习惯是推理成本节省的主要来源。
- 预留提取延迟的缓冲空间。长期记忆是异步提取的,因此不要承诺在当前会话中回忆新事实。让短期会话事件覆盖当前对话,长期记录覆盖过往内容。
- 从第一天起就设定预算。基于消耗的代理在出现重试循环或健谈用户前都很廉价。在 AWS 预算中设置月度上限 80% 和 100% 的预警,成本为零却能提前发现异常。
- 保持技能模块小而专一。每个技能应完成用户会用一句话命名的单一功能,如查看天气或设置提醒。小型技能可独立测试、独立替换,且便于模型正确选择。全能型技能会迫使模型猜测您想使用的行为。
自主培育
两种种植方式,同一片花园:
- 单步启动模板:CloudFormation 模板指向公共 Amazon Elastic Container Registry(Amazon ECR)镜像,仅部署 Telegram 机器人令牌。
- 自主构建:scripts/deploy.sh 脚本验证模板,构建并推送您自己的 ARM64 镜像到私有 Amazon ECR 仓库,部署堆栈并注册 Telegram Webhook,实现完全可定制的构建。
截至 2026 年 7 月,轻量个人使用成本约为每月 5-9 美元(约 2 美元基础设施,1-3 美元 Haiku 文本,2 美元 Sonnet 视觉),内置 AWS 预算在您设定的上限 80% 和 100% 时发出预警。
完整源代码可在 sample-agentcore-memory-openclaw GitHub 仓库获取。
清理资源
实验结束后请彻底清理以避免持续计费。由于整个系统是一个 CloudFormation 堆栈,清理工作主要为单次删除操作:
- 删除 CloudFormation 堆栈。这将移除 AgentCore 运行时代理、API 网关、Lambda 函数、Amazon EventBridge 调度以及相关 AWS Identity and Access Management(IAM)角色。
- 删除 AgentCore 内存存储(及其命名空间),确保不保留任何用户记录。
- 删除推送到私有 ECR 仓库的镜像,如果不再需要仓库本身也一并删除。
- 如果您在堆栈外部创建了 AWS 预算警报,请将其删除。
- 如果不再需要,撤销 Telegram 的 webhook(或通过 BotFather 删除机器人),并撤销 Bedrock 模型访问权限。
结论
该解决方案的可复用核心是一个基于 Amazon Bedrock AgentCore 的无服务器代理,包含技能系统和托管内存。AgentCore 内存消除了构建自定义向量存储和提取管道的需要,同时让您完全控制代理的记忆和遗忘内容。基于消耗的计算加上提示缓存可将真正个性化的助手成本控制在每月几美元,而 OpenClaw 技能清单使该模式能够跨领域移植。个性化效果会叠加:用户互动越多,助手就越有用。
要更进一步,可以从单个领域(如浇水提醒)开始,逐步扩展内存范围,探索情景记忆功能,使代理能够引用特定的过往对话(“上次我们讨论无花果树时,您决定推迟施肥”),或 Fork 该仓库,替换自己的角色和技能,构建所需的任意助手。
如需了解更多内容,请参考 AgentCore 文档。以下相关文章将更深入地介绍构建模块:
- Amazon Bedrock AgentCore 内存:构建上下文感知代理
- 构建更智能的 AI 代理:AgentCore 长期内存深度解析
- 在 Amazon Bedrock 上有效使用提示缓存
- 在 Amazon Bedrock AgentCore 运行时安全启动和扩展您的代理及工具
作者简介
'"`