04. Skills、Memory、Backend 与持久化
7 min read

04. Skills、Memory、Backend 与持久化

按生命周期区分消息、checkpoint、AGENTS.md、Store 与持久文件,理解 Skills、Memory 和 Backend 如何共同支撑长任务。

04. Skills、Memory、Backend 与持久化#

前一篇解决“怎样完成任务”,本篇解决“知识和状态放在哪里”。很多 Agent 项目的问题不是模型不会推理,而是把所有规则、历史、文件和长期记忆都塞进一条消息,最后既贵又难以隔离。

1. 四种上下文载体#

载体生命周期典型内容
对话消息当前交互用户问题、模型回答、工具结果
checkpoint一次 thread 运行中断位置、state、恢复信息
AGENTS.md memoryAgent 启动时始终相关项目规则、长期约定
Store / 持久文件跨 thread用户偏好、研究资料、共享知识

不要把对话历史当长期记忆,也不要把所有文档都塞入 AGENTS.md。先根据生命周期选择载体。

2. Skills:按需加载知识#

Skill 适合“只在特定任务出现”的流程和知识,例如 API 审查、PDF 处理、研究报告或部署。目录:

text
skills/
└── research-report/
    ├── SKILL.md
    └── references/
        └── source-rubric.md

SKILL.md 使用 frontmatter:

markdown
---
name: research-report
description: 当用户要求基于来源撰写研究报告时使用;要求保存证据并标注不确定性。
---

# Research report

1. 读取 `references/source-rubric.md`
2. 将原始结果和去重证据分开保存。
3. 在最终报告中列出来源和限制。

description 是路由信号,必须说明做什么、什么时候使用。渐进式披露的顺序是 metadata → SKILL.md → supporting files;不要把参考资料一次塞进 system prompt。

3. 接入 Skills 和 Memory#

typescript
import { createDeepAgent, FilesystemBackend } from "deepagents";

const backend = new FilesystemBackend({
  rootDir: "/absolute/path/to/research-agent",
  virtualMode: true,
});

const agent = createDeepAgent({
  model,
  backend,
  skills: ["/skills/"],
  memory: ["/AGENTS.md"],
});

路径相对于 backend root,并使用 POSIX 虚拟路径。默认 StateBackend 没有真实磁盘文件;如果使用它,需要在 invoke state 中按当前 FileData 结构提供 AGENTS.md 和 Skill 文件。

4. AGENTS.md 应该写什么#

始终加载的 memory 应该短、稳定、可执行:

markdown
# Project rules

- 使用 TypeScript ESM,公共函数必须有测试。
- 外部来源必须保留 URL;没有来源时标记未核验。
- 不读取或写入 `.env`、凭据和用户 home。
- 发布、删除和发信必须等待人工审批。

不要把一次性任务、长篇产品文档或频繁变化的搜索结果放入其中。Skill 文件和 memory 都能指导模型,但都不能授予新的文件、网络或 shell 权限。

5. Backend 选择矩阵#

Backend生命周期适合场景
StateBackend当前 thread state临时计划、scratchpad、工具结果卸载
StoreBackendLangGraph Store用户记忆、跨 thread 资料
FilesystemBackend本地磁盘 root受控 CLI、项目工作区
CompositeBackend按路径分流把工作区落盘、内部产物留在 state

默认 StateBackend 类似线程级 scratchpad,不等于 Node.js fs。Store 需要 namespace;Filesystem 需要 root、权限和隔离;Composite 需要稳定的路径前缀协议。

6. 当前推荐的实例化方式#

typescript
import {
  CompositeBackend,
  FilesystemBackend,
  StateBackend,
} from "deepagents";

const backend = new CompositeBackend(
  new StateBackend(),
  {
    "/workspace/": new FilesystemBackend({
      rootDir: "/absolute/path/to/project",
      virtualMode: true,
    }),
  },
);

/workspace/ 下的项目文件落到磁盘,内部临时路径仍留在 StateBackend。较旧教程中的 backend factory 写法要根据当前版本迁移,推荐以官方当前实例化 API 为准。

7. Store 和 namespace#

typescript
import { InMemoryStore } from "@langchain/langgraph";
import { StoreBackend } from "deepagents";

const store = new InMemoryStore();
const backend = new StoreBackend({
  namespace: () => ["users", currentUserId],
});

const agent = createDeepAgent({ model, store, backend });

InMemoryStore 只适合演示,重启后数据消失。生产环境按用户、租户、assistant 设计 namespace,不能把所有用户放进默认命名空间。namespace 的顺序和版本也要固定,否则迁移后历史数据会“看起来丢失”。

8. Checkpoint 和 Store 的配合#

checkpoint 保存“这次运行走到哪里”,Store 保存“跨运行要复用什么”。恢复 interrupt 需要 checkpoint;让用户下周继续使用研究资料,需要 Store 或持久文件系统。二者混成一个概念会导致清理策略和权限边界模糊。

9. 路径契约和读写冲突#

CompositeBackend 可以定义:

text
/workspace/       → 受限项目目录
/user-memory/     → StoreBackend
/tmp/             → StateBackend
/report/          → 经过权限策略的工作区

前缀不能由用户输入随意拼接。路径要先规范化,再由 backend、permissions 和 rootDir 重复校验。多个 Agent 写同一文件时,最后写入者可能覆盖前者;更安全的方式是每个子 Agent 写独立 artifact,由父 Agent 聚合。

10. 迁移与测试#

更换 backend 时检查路径、编码、旧 thread 可读性、权限规则、清理任务和二进制 mime type。为文件工作流写集成测试:缺少 evidence.md 时不得生成已核验结论;草稿存在但检查失败时不得生成 final.md;A 用户的数据不能被 B namespace 读取。

本章练习

  1. 创建一个 research-report Skill 和一个短 AGENTS.md
  2. 用 StateBackend 运行两个 thread,确认临时文件不共享。
  3. 将用户偏好迁移到 Store,并用不同 namespace 验证隔离。
  4. 用 CompositeBackend 映射 /workspace/,测试路径之外的访问。

验收标准:能区分对话、checkpoint、memory 和 Store;知道何时使用真实磁盘;能解释 namespace 和路径前缀如何影响多租户安全。

相关文章