给Agent装上记忆和审计,从工具人升级为幕僚长
时间:2026-06-03 12:05
Agent通过CLAUDE md实现长时记忆存储公司背景,利用OutputStyles定制不同高管报告,采用PlanMode复杂任务先计划后执行,借助SlashCommands简化高频操作,并通过Hooks机制记录所有操作日志,从而从工具人升级为可靠的首席幕僚,满足企业产品化需求。
> 这是「从 Demo 到生产:老张的 Agent 进阶之路」系列的第二篇。前一篇,老张仅用两小时便搭建了一个竞品研究 Agent,并顺利通过老板的演示验收。而本篇,他将面对更棘手的挑战:让 Agent 从“勉强能用”真正蜕变为“稳定可靠”。
---
周一例会结束后,王总把老张叫进办公室。
“演示效果不错。但你觉得这东西能量产吗?”
老张心里早有准备:“技术上没问题,不过需要补充几个关键功能。”
“具体说说?”
“第一,Agent 必须能记住我们公司的基本信息,不用每次重复交代。第二,所有操作都得有审计日志,谁让它做了什么,必须留下记录。第三,不同高管需要看到不同格式的报告。”
王总点头:“预算批了。下周看升级版。”
老张回到工位,打开上周的代码。他很快发现了痛点:每次运行 Agent,都要重新输入公司背景、行业术语、常用联系人。Agent 就像“金鱼记忆”,重启一次,忘得一干二净。
他翻阅文档后发现,上周使用的 Claude Agent SDK 用来快速搭建 Demo 非常顺手,但要实现产品化,还需要更多成熟的能力。他了解到 Anthropic 的 Claude Code CLI——一款 AI 编程助手,拥有完善的设计机制:`CLAUDE.md` 记忆、Hooks 审计、Slash Commands 快捷命令。这些设计思路恰好可以借鉴,解决老张当前的困境。
老张的思路很明确:用 Claude Agent SDK 作为 Agent 核心,再借鉴 Claude Code 的设计理念为它“加 Buff”。
这篇文章,就是老张这一周的心得总结。
---
## 老张的挑战:从 Demo 走向产品
上周的 Demo 充其量只是个“毛坯房”。要想真正投入生产,老张必须攻克三个棘手难题:
**问题一:记忆缺失**
每次重启 Agent,公司背景、行业术语、常用联系人全部归零。高管们可没有耐心反复重复同样的需求。
**问题二:输出单一**
财务总监要看表格,销售总监想看要点列表,王总则只需要一句话总结。同一个调研结果,不同人需要不同的呈现方式。
**问题三:审计缺失**
企业环境中,合规是底线。Agent 执行了什么操作、访问了哪些数据、调用了什么工具,所有这些都必须有日志可查。
老张心里清楚,这三个问题的背后,其实是 Agent 从“工具人”升级为“Chief of Staff”的过程。工具人只管干活,而 Chief of Staff 需要懂背景、能定制、留痕迹。
---
## CLAUDE.md:给 Agent 装上“长时记忆”(借鉴 Claude Code)
老张找到的第一个方案是 `CLAUDE.md`——这是 Claude Code 的核心特色:一个放在项目根目录的 Markdown 文件,每次启动 Claude Code 时自动读取。
老张的想法很直接:虽然我的 Agent 本身基于 Claude Agent SDK,但完全可以把这套思路迁移过来——将公司背景写入文件,启动时读取,直接注入到 System Prompt 中。
```
项目目录/
├── CLAUDE.md ← Agent 的记忆文件
├── main.py
└── ...
```
**`CLAUDE.md` 的内容示例**:
```markdown
# 公司背景
我们是一家中型制造企业,主营工业自动化设备。
## 行业术语
- PLC:可编程逻辑控制器
- SCADA:数据采集与监控系统
- MES:制造执行系统
## 常用联系人
- 采购部老李:lili@company.com
- 财务部张姐:zhangjie@company.com
## 竞品关注清单
- 华中自控(武汉)
- 智能装备集团(苏州)
- 华东自动化(无锡)
```
**工作原理**:
```
┌─────────────────────────────────────────────────┐
│Agent 启动 │
└─────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ 读取 CLAUDE.md │
│ (公司背景、术语、联系人、偏好) │
└─────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ System Prompt 注入 │
│ (CLAUDE.md 内容作为背景知识) │
└─────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────┐
│ Agent 开始工作 │
│ (无需用户重复交代背景) │
└─────────────────────────────────────────────────┘
```
老张把公司背景、行业术语、常用联系人一股脑写进 `CLAUDE.md`。从此,Agent 记住了公司是谁、做什么、关注谁,再也不是“金鱼”了。
**实现方式**:
```python
# 读取 CLAUDE.md 内容
with open("CLAUDE.md", "r") as f:
company_context = f.read()
# 注入到 System Prompt
async with ClaudeSDKClient(
options=ClaudeAgentOptions(
system_prompt=company_context + "\n\n" + DEFAULT_PROMPT
)
) as agent:
await agent.query("分析竞品动态")
```
**记忆的边界**:
需要说明的是,`CLAUDE.md` 属于静态记忆——写入后不再变化。如果需要动态记忆(比如“上次调研的结论”),那就得引入 Session 机制或外部存储,这将在生产篇详细讲解。
---
## Output Styles:同一个人,不同“面孔”
王总看完 Agent 的报告,又提了新要求:“财务老刘要看表格,销售老赵要看要点,而我要一句话总结。能不能自动适配?”
老张想到了 Claude Code 的 Output Styles 机制——针对不同场景定义不同的输出格式。虽然 SDK 没有内置此功能,但通过 System Prompt 就能轻松实现。
**Output Styles 的定义**:
```python
# 定义输出风格
OUTPUT_STYLES = {
"财务报告": """
输出格式:表格
包含:公司名称、营收规模、技术路线、风险等级
风格:简洁、数据导向
""",
"销售报告": """
输出格式:要点列表
包含:竞品优势、劣势、市场机会
风格:口语化、可复用
""",
"高管摘要": """
输出格式:一句话
包含:核心结论 + 建议行动
风格:精炼、决策导向
"""
}
```
**如何使用**:
```python
# 老刘要看财务报告
async with ClaudeSDKClient(
options=ClaudeAgentOptions(
system_prompt=CLAUDE_MD + OUTPUT_STYLES["财务报告"]
)
) as agent:
await agent.query("分析华中自控的财务状况")
# 老赵要看销售报告
async with ClaudeSDKClient(
options=ClaudeAgentOptions(
system_prompt=CLAUDE_MD + OUTPUT_STYLES["销售报告"]
)
) as agent:
await agent.query("分析华中自控的市场策略")
```
**架构示意**:
```
┌─────────────────────────────────┐
│ CLAUDE.md │
│ (公司背景记忆) │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ Output Styles │
│ ┌─────────┬─────────┬────────┐ │
│ │ 财务报告 │ 销售报告 │ 高管摘要│ │
│ └─────────┴─────────┴────────┘ │
└────────────────┬────────────────┘
│
┌────────────────▼────────────────┐
│ Agent │
│ (输出定制化报告) │
└─────────────────────────────────┘
```
老张发现,Output Styles 的本质是“个性化”——同一个 Agent,不同用户看到不同的输出。这,正是企业级 Agent 的标配能力。
---
## Plan Mode:让 Agent “先想后做”(借鉴 Claude Code)
王总又提出了更复杂的需求:“下周有个行业展会,帮我做一个完整的参展调研,包括竞品动态、技术趋势、潜在客户。”
老张知道,这种复杂任务如果直接让 Agent 动手,很容易偏离方向——搜索一大堆信息,最后东一块西一块,缺乏逻辑主线。
他了解到 Claude Code 有一个 Plan Mode——让 AI 先制定计划,展示给用户确认后再执行。这个思路用在 Agent 里再合适不过:先让 Agent 输出计划,用户确认后,再正式执行。
**普通模式 vs Plan Mode**:
```
普通模式:
用户输入 → Agent 直接执行 → 结果
Plan Mode:
用户输入 → Agent 先规划 → 展示计划 → 用户确认 → 执行 → 结果
```
**Plan Mode 的工作流程**:
```python
# 实现类似 Plan Mode 的效果
# 第一步:让 Agent 先规划
async with ClaudeSDKClient(
options=ClaudeAgentOptions(
model="claude-sonnet-4-6",
allowed_tools=["WebSearch"],
system_prompt=CLAUDE_MD + "\n\n请先输出计划,不要直接执行。"
)
) as agent:
await agent.query("为下周的行业展会做调研准备")
plan = await agent.receive_response()
print("计划内容:", plan)
# 第二步:用户确认后执行
confirm = input("确认执行?(y/n): ")
if confirm == "y":
await agent.query("按计划执行")
async for msg in agent.receive_response():
print(msg)
```
**Plan Mode 的价值**:
| 场景 | 普通模式 | Plan Mode |
|------|----------|-----------|
| 简单查询 | 高效 | 过度设计 |
| 复杂任务 | 容易跑偏 | 有条理 |
| 敏感操作 | 风险高 | 可审核 |
老张总结:**简单任务用普通模式,复杂任务用 Plan Mode。** 这是 Agent 开发中一条实用的原则。
---
## Slash Commands:高管们的“快捷键”(借鉴 Claude Code)
老张注意到,高管们有几个高频需求:
- “查一下华中自控最近动态”
- “对比三家竞品的技术路线”
- “生成下周例会材料”
每次都要输入完整的 prompt,太繁琐了。他发现 Claude Code 提供了 Slash Commands——预定义的命令模板,输入 `/competitor` 就能触发完整的 prompt。
老张决定在 Agent 里也实现类似的机制:一个命令解析层,把简短命令展开成完整的 prompt。
**Slash Commands 的实现思路**:
```python
# 命令模板定义
COMMANDS = {
"competitor": """
调研目标:{args}
请执行以下步骤:
1. 搜索目标公司近三个月的新闻动态
2. 整理产品更新、融资、人事变动
3. 生成简报,突出对我们公司的影响
""",
"compare": """
对比目标:{args}
请从以下维度对比:
1. 技术路线
2. 市场定位
3. 财务状况
4. 近期动态
""",
}
# 命令解析
def parse_command(user_input):
if user_input.startswith("/"):
cmd, *args = user_input[1:].split(maxsplit=1)
if cmd in COMMANDS:
return COMMANDS[cmd].format(args=args[0] if args else "")
return user_input # 普通输入,原样返回
```
**使用方式**:
```
用户:/competitor 华中自控
Agent:
正在搜索华中自控近三个月的动态...
- 3月:完成 B 轮融资 5000 万
- 2月:发布新一代 PLC 控制器
- 1月:挖走华东自动化技术总监
简报:华中自控近期融资充足,技术团队扩张,
建议关注其新产品发布节奏。
```
老张定义了十几个常用命令,高管们只需输入 `/` 就能看到所有选项。使用门槛大幅降低,大家用得也更顺手了。
---
## Hooks:给 Agent 的每个动作“上锁”(借鉴 Claude Code)
王总对老张提出了硬性要求:“Agent 执行的每一个操作,都要有日志。这是合规底线。”
老张发现 Claude Code 有 Hooks 机制——在工具调用前后自动执行自定义逻辑。虽然 SDK 没有内置 Hooks,但可以在 Agent 的工具调用层实现类似的功能。
**Hooks 的工作位置**:
```
用户输入
│
▼
┌─────────────┐
│ PreToolHook │ ← 工具调用前触发
└──────┬──────┘
│
▼
工具执行(WebSearch、Read、Bash...)
│
▼
┌──────────────┐
│ PostToolHook │ ← 工具调用后触发
└──────┬───────┘
│
▼
返回结果
```
**审计 Hook 的实现思路**:
Claude Agent SDK 的工具调用是流式的,可以在处理响应时拦截工具调用事件:
```python
# 在响应流中拦截工具调用
async for msg in agent.receive_response():
if hasattr(msg, 'tool_use'):
# 工具调用前:记录
log_entry = {
"timestamp": datetime.now(),
"user": current_user,
"tool": msg.tool_use.name,
"input": msg.tool_use.input,
}
await write_to_audit_log(log_entry)
if hasattr(msg, 'tool_result'):
# 工具调用后:记录结果
await update_audit_log(
tool_id=msg.tool_result.id,
output=msg.tool_result.content
)
```
**审计日志示例**:
```json
[
{
"timestamp": "2025-01-15T14:23:01",
"user": "王总",
"tool": "WebSearch",
"input": "华中自控 2024 财报",
"output": "找到 3 条结果..."
},
{
"timestamp": "2025-01-15T14:23:45",
"user": "王总",
"tool": "WebSearch",
"input": "华中自控 融资动态",
"output": "找到 5 条结果..."
}
]
```
**Hooks 的更多用途**:
| Hook 位置 | 用途 |
|-----------|------|
| 工具调用前 | 权限检查、敏感操作拦截 |
| 工具调用后 | 审计日志、结果缓存 |
| 响应开始前 | 输入过滤、安全检查 |
| 响应结束后 | 输出格式化、敏感信息脱敏 |
老张最终实现了一套完整的审计系统:每次工具调用都记录,敏感操作需要人工确认。王总看了很满意,称赞道:“这个靠谱。”
---
## Subagent 协调:让专家干专家的活
老张发现,单个 Agent 的能力有限。研究任务需要大量搜索,分析任务需要深度思考。让一个 Agent 同时干两件事,效率低,质量也差。
他想到了 Claude Code 的 Subagent 机制——让多个专家 Agent 各司其职。这个思路在 SDK 里同样可行:创建多个 Agent 实例,各自负责不同的任务。
**架构设计**:
```
┌─────────────────────────┐
│ 主协调 Agent │
│ (Chief of Staff) │
└───────────┬─────────────┘
│
┌───────────────────┴───────────────────┐
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ 研究 Agent │ │ 分析 Agent │
│ (负责搜索收集) │ │ (负责深度分析) │
└───────┬───────┘ └───────┬───────┘
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ WebSearch │ │ 思考模式 │
│ Read │ │ 对比分析 │
└───────────────┘ └───────────────┘
```
**实现思路**:
```python
# 主协调 Agent
async def chief_of_staff(user_request):
# 1. 分解任务
research_task = "搜索华中自控的公开信息"
analysis_task = "分析华中自控对我们公司的威胁"
# 2. 调用研究 Agent
research_result = await research_agent.query(research_task)
# 3. 调用分析 Agent(传入研究结果)
analysis_result = await analysis_agent.query(
f"基于以下信息,{analysis_task}\n\n{research_result}"
)
return analysis_result
```
**Subagent 的价值**:
| 特性 | 单 Agent | 多 Agent 协调 |
|------|----------|---------------|
| 任务复杂度 | 中低 | 高 |
| 专业程度 | 通用 | 专家化 |
| 可维护性 | 难调试 | 职责清晰 |
| 成本 | 低 | 高(多次调用) |
老张总结:**简单任务用单 Agent,复杂任务用 Subagent 协调。** 这本质上是一个成本和质量之间的权衡。
---
## 系统架构:从工具人到 Chief of Staff
老张把这一周学到的东西全部整合起来,形成了完整的系统架构。核心思路:用 Claude Agent SDK 作为 Agent 引擎,借鉴 Claude Code 的设计理念来增强能力。
```
┌─────────────────────────────────┐
│ CLAUDE.md │
│ (借鉴 Claude Code 记忆机制) │
└────────────────┬────────────────┘
│
┌────────────────────────────────▼────────────────────────────────┐
│ Output Styles │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 财务报告 │ │ 销售报告 │ │ 高管摘要 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└────────────────────────────────┬────────────────────────────────┘
│
┌────────────────────────────────▼────────────────────────────────┐
│ Claude Agent SDK 核心 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Slash Commands 解析层 │ │
│ │ /competitor /compare /weekly /report... │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────┼───────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Plan Mode │ │ 研究 Agent │ │ 分析 Agent │ │
│ │ (规划-确认模式) │ │ (搜索收集) │ │ (深度分析) │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
└────────────────────────────────┬────────────────────────────────┘
│
┌────────────────────────────────▼────────────────────────────────┐
│ Hooks 审计层 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 审计日志 │ │ 权限检查 │ │
│ │(拦截工具调用) │ │(敏感操作拦截) │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
**系统清单**:
| 能力 | 实现方式 | Claude Code 参考 | 解决的问题 |
|------|----------|-----------------|-----------|
| 持久化记忆 | 文件 + System Prompt 注入 | CLAUDE.md | Agent 不再“金鱼记忆” |
| 个性化输出 | 多套 System Prompt | Output Styles | 不同高管看不同格式 |
| 复杂任务规划 | 两步确认流程 | Plan Mode | 任务不跑偏 |
| 快捷操作 | 命令解析层 | Slash Commands | 降低使用门槛 |
| 审计合规 | 工具调用拦截 | Hooks | 满足合规要求 |
| 专家分工 | 多 Agent 实例 | Subagent 协调 | 提升任务质量 |
---
## 周五演示:高管们的反馈
老张把升级后的系统部署到公司内网,给高管们做演示。
**场景一:王总要一句话总结**
```
王总:/competitor 华中自控
Agent:华中自控近期融资 5000 万,技术团队扩张,
建议关注其新产品发布节奏。威胁等级:中。
```
**场景二:财务老刘要看表格**
```
老刘:分析华中自控的财务状况
Agent:生成表格如下:
| 指标 | 数值 | 同比变化 |
|--------|--------|----------|
| 营收 | 2.3亿 | +15% |
| 净利润 | 3200万 | +8% |
| 融资 | 5000万 | B轮 |
```
**场景三:审计日志查询**
```
合规部:查询昨天所有 Agent 操作记录
系统:返回 23 条操作记录,包含时间、用户、工具、输入输出。
```
演示结束,王总点点头:“这个能用。下周全公司推广。”
老张心里却有点打鼓——全公司 500 人同时用,系统撑得住吗?
---
## 老张学到了什么
**Agent 进化的三个层次**:
1. **工具人层次**:能干活,但没记忆、没个性、没痕迹
2. **助手层次**:有记忆、能定制、有审计,可靠但单点
3. **协调者层次**:能分工、会协调、可扩展,企业级能力
**关键技术点**:
| 技术点 | 来源 | 解决的问题 | 适用场景 |
|--------|------|-----------|----------|
| CLAUDE.md 思路 | 借鉴 Claude Code | 持久化记忆 | 需要背景知识的 Agent |
| Output Styles | 自己实现 | 个性化输出 | 多用户、多角色场景 |
| Plan Mode 思路 | 借鉴 Claude Code | 复杂任务规划 | 多步骤、高风险任务 |
| Slash Commands 思路 | 借鉴 Claude Code | 降低使用门槛 | 高频重复操作 |
| Hooks 思路 | 借鉴 Claude Code | 审计合规 | 企业级部署必备 |
| Subagent 协调 | 自己实现 | 专家分工 | 复杂研究分析任务 |
**老张的感悟**:
Claude Agent SDK 提供了 Agent 的核心能力,但 Claude Code 展示了这些能力如何组合成企业级产品。老张从 Claude Code 中学到的不仅是技术,更是设计思路——记忆、定制、规划、快捷、审计、分工,这些才是 Agent 从“能用”到“可靠”的关键。
**下一步的问题**:
全公司推广后,并发问题出现了——500 人同时使用,会话开始丢失数据,甚至崩溃。老张需要学习 Managed Agents、Session 持久化、Human-in-the-loop……
这些问题,生产篇会解答。
---
## 附:关键技术实现思路
以下代码展示了老张如何借鉴 Claude Code 的思路,在 Claude Agent SDK 上实现类似功能。这些是伪代码,展示核心思路。
### CLAUDE.md 实现
```python
# 读取记忆文件并注入到系统提示词
with open("CLAUDE.md", "r") as f:
company_context = f.read()
async with ClaudeSDKClient(
options=ClaudeAgentOptions(
system_prompt=company_context + "\n\n" + DEFAULT_PROMPT
)
) as agent:
await agent.query("分析竞品动态")
```
### Output Styles 实现
```python
OUTPUT_STYLES = {
"财务报告": "输出格式:表格。风格:简洁、数据导向。",
"销售报告": "输出格式:要点列表。风格:口语化、可复用。",
"高管摘要": "输出格式:一句话。风格:精炼、决策导向。"
}
# 根据用户角色选择输出风格
style = OUTPUT_STYLES[user_role]
system_prompt = CLAUDE_MD + "\n\n" + style
```
### Plan Mode 实现
```python
# 先让 Agent 输出计划
await agent.query("请先输出调研计划,不要直接执行")
plan = await agent.receive_response()
# 用户确认后执行
if user_confirm(plan):
await agent.query("按计划执行调研")
```
### Slash Commands 实现
```python
COMMANDS = {
"competitor": "调研 {args},包括近三月动态、产品更新、融资情况",
"compare": "对比 {args} 的技术路线、市场定位、财务状况",
}
def parse_command(user_input):
if user_input.startswith("/"):
cmd, *args = user_input[1:].split(maxsplit=1)
return COMMANDS.get(cmd, user_input).format(args=args[0] if args else "")
return user_input
```
### Hooks 审计实现
```python
async for msg in agent.receive_response():
if hasattr(msg, 'tool_use'):
await log_to_audit(
user=current_user,
tool=msg.tool_use.name,
input=msg.tool_use.input
)
```
### Subagent 协调实现
```python
# 研究 Agent
research_agent = ClaudeSDKClient(options=RESEARCH_OPTIONS)
research_result = await research_agent.query("搜索华中自控公开信息")
# 分析 Agent
analysis_agent = ClaudeSDKClient(options=ANALYSIS_OPTIONS)
analysis_result = await analysis_agent.query(f"分析:{research_result}")
```
---
**下一篇:全公司推广那天,Agent 崩了**
老张的系统通过了高管演示,获批全公司推广。但 500 人同时使用后,会话丢失、权限混乱、审计日志不全……老张需要学习 Managed Agents、Session 持久化、Human-in-the-loop——这些生产环境必备的能力。
生产篇,我们将看到老张如何把一个“可靠”的产品变成“稳定”的服务。