Agent 的记忆系统一旦进入企业场景,问题就不只是“能不能记住”,而是“该记住谁的、在哪个上下文里用、哪些 Agent 可以读”。AgentCore Memory 中的 metadata 过滤,正是把记忆从一堆向量片段,变成可治理、可隔离、可审计的结构化资产。
元数据不是标签装饰,而是检索边界
在 AgentCore Memory 里,metadata 会贯穿三个阶段:配置、写入和检索。
配置阶段决定哪些字段值得成为过滤条件,例如 tenant_id、user_id、agent_id、session_id、department、data_classification。这些字段不只是方便查询,更是权限和隔离模型的一部分。
写入阶段,应用需要把业务上下文和记忆内容一起送入 Memory。比如一个客服 Agent 记录“用户偏好中文回复”,同时附带租户、用户、渠道和负责 Agent。没有这些字段,后续检索就只能依赖语义相似度,很容易把别的用户、别的租户、别的任务上下文带进来。
检索阶段,metadata filter 会先限定候选集合,再让语义检索发挥作用。一个好的过滤条件通常不是为了“找得更多”,而是为了“只在正确的池子里找”。
多 Agent 与多租户:最容易踩坑的地方
企业系统里,一个用户可能同时被多个 Agent 服务:销售助手、客服助手、合规助手、数据分析助手。它们可能共享一部分长期记忆,也可能必须严格隔离。
可以采用这样的划分思路:
tenant_id:强隔离边界,几乎所有查询都应带上。user_id:用户级记忆边界,用于个性化和历史偏好。agent_id:控制某类 Agent 的私有记忆,例如客服处理记录。memory_scope:区分private、team、global等访问层级。data_classification:区分public、internal、restricted,避免敏感记忆被低权限流程读取。
多租户架构中,最危险的不是查不到数据,而是“查到了不该查的数据”。因此 metadata 过滤应该是服务端强制逻辑,而不是只靠前端或 prompt 约束。
可以这样实践:写入和检索都带上结构化过滤
下面是一个可改造的 Python 示例。它不假设具体 SDK 名称,而是演示在 AgentCore Memory 客户端外层封装强制 metadata 的方式。你可以把 AgentCoreMemoryClient 替换成项目里的真实客户端。
from dataclasses import dataclass
from typing import Any, Dict, List
@dataclass(frozen=True)
class RequestContext:
tenant_id: str
user_id: str
agent_id: str
role: str
class AgentCoreMemoryClient:
"""示例占位客户端:替换为你实际使用的 AgentCore Memory SDK。"""
def put_memory(self, content: str, metadata: Dict[str, Any]) -> None:
print("WRITE", {"content": content, "metadata": metadata})
def search_memory(self, query: str, filters: Dict[str, Any], limit: int = 5) -> List[Dict[str, Any]]:
print("SEARCH", {"query": query, "filters": filters, "limit": limit})
return []
class MemoryService:
def __init__(self, client: AgentCoreMemoryClient):
self.client = client
def remember_user_preference(self, ctx: RequestContext, content: str) -> None:
metadata = {
"tenant_id": ctx.tenant_id,
"user_id": ctx.user_id,
"agent_id": ctx.agent_id,
"memory_scope": "private",
"data_classification": "internal",
"memory_type": "preference",
}
self.client.put_memory(content=content, metadata=metadata)
def recall_for_agent(self, ctx: RequestContext, query: str) -> List[Dict[str, Any]]:
filters = {
"tenant_id": ctx.tenant_id,
"user_id": ctx.user_id,
"agent_id": ctx.agent_id,
"data_classification": {"$in": ["public", "internal"]},
}
return self.client.search_memory(query=query, filters=filters, limit=5)
if __name__ == "__main__":
memory = MemoryService(AgentCoreMemoryClient())
context = RequestContext(
tenant_id="tenant-acme",
user_id="user-42",
agent_id="support-agent",
role="support",
)
memory.remember_user_preference(context, "用户偏好使用中文,并希望回答包含操作步骤。")
memory.recall_for_agent(context, "回复这个用户时要注意什么?")
运行方式:
python memory_metadata_demo.py
这个例子的重点不是客户端实现,而是两个约束:写入时必须带完整 metadata,检索时必须由服务端拼接不可绕过的过滤条件。
过滤策略要和权限模型一起设计
metadata 字段越多,不代表系统越安全。字段设计要服务于明确的访问规则。
一个可落地的检索策略可以这样写成配置:
memory_policy:
required_filters:
- tenant_id
- user_id
optional_filters:
- agent_id
- memory_type
- data_classification
default_limits:
max_results: 5
allowed_classifications:
- public
- internal
deny_if_missing_required_filter: true
这类配置适合放在 Agent 网关或 Memory 服务层,而不是散落在每个工具调用里。否则团队一多,某个新 Agent 很容易忘记传 tenant_id,导致跨租户记忆泄漏。
实施清单:先收紧边界,再追求智能
落地 AgentCore Memory metadata 过滤时,可以按这个顺序推进:
- 先定义租户、用户、Agent、数据分级这四类核心 metadata。
- 写入接口拒绝缺少关键 metadata 的请求。
- 检索接口在服务端强制追加租户和用户过滤条件。
- 对共享记忆单独设计
memory_scope,不要默认所有 Agent 可读。 - 给敏感字段建立审计日志,记录谁在什么上下文检索了哪些范围。
记忆系统越像数据库,就越需要数据库式的边界感。语义检索负责“相关”,metadata 负责“应该”。两者结合,Agent 才能在企业环境里既聪明,又不越界。