大多数 Claude Agent 教程都以“Hello World”告终。
它们教你如何让 Claude 调用工具,如何设置基本循环,如何在简单的玩具任务上获得自主响应。
然后,当你尝试构建真实的东西时,一切都会崩溃。
任务太模糊。Agent 卡住了。输出结果不一致。会话结束,什么都没保存。下次你又要从头开始重来。
教程中能用的 Claude Agent 与生产环境中能用的 Claude Agent 之间的差距,并非 Claude 能力上的差距。
而是 Agent 设计上的差距。
本指南将彻底弥合这一差距。
到最后,你将拥有一个能够可靠运行真实工作流程的 Claude Agent。不是演示,不是玩具任务。而是一个能够产生一致输出、优雅处理边缘情况、持续改进,并且无需你手动启动每一步的工作流程。
真正的 Agent 有何不同
在开始构建之前,先要理解真正的 Agent 与教程中的 Agent 有何区别。
教程中的 Agent 运行一个干净的任务,有干净的输入,产生干净的输出。任务定义明确,输入以预期格式提供,不会发生意外情况。成功是二元的、显而易见的。
真正的 Agent 运行的是杂乱的任务,输入杂乱,但仍要产生有用的输出。任务部分定义明确,输入格式多样,意外情况经常发生。成功是一个程度问题,需要判断评估。
决定 Agent 能否在现实世界中存活下来的四个特性:
稳健的任务定义。 Agent 不仅知道该做什么,还知道如何应对实践中会遇到的二十种任务变体。指令不仅涵盖理想路径,还包括边缘情况。
持久记忆。 Agent 跨会话积累上下文。上周做的工作会影响今天的工作。它不会每次都从零开始。
优雅的失败处理。 当出现问题时,Agent 会恢复而非停止。它记录发生了什么,尝试替代方案,只有在无法恢复时才通知人类。
质量自我验证。 Agent 在交付输出之前,会根据定义的标准检查自己的输出。它会闭合自身的反馈循环,而不是直接交回最初生成的内容。
大多数教程中的 Agent 不具备这些特性中的任何一个。本指南将构建所有四个特性。
Agent 架构
该架构包含四个协同工作的组件。
任务定义层
一个结构化的技能文件,定义任务、流程、边缘情况处理和质量标准。这不是一个提示词。它是一个完整的操作规范,Agent 在每次执行前都会读取它。
记忆层
一个持久化数据库,存储 Agent 已完成的工作、学到的内容以及跨会话需要记住的信息。通过 Hermes Agent 基于 SQLite 构建,或使用基于文件的日志手工实现。
执行层
实际的 Claude API 调用,完成具体工作。结构上使用正确的模型、正确的上下文和正确的工具来完成工作流程的每一步。
质量层
验证循环,在交付输出前根据定义的标准检查输出,并在输出未达标时使用特定更正重试。
打好基础
安装所需工具:
安装 Hermes Agent 用于编排和记忆
git clone https://github.com/NousResearch/hermes-agent
cd hermes-agent
npm install
安装 MCP 服务器以访问工具
npm install -g @modelcontextprotocol/server-filesystem
npm install -g @modelcontextprotocol/server-brave-search
配置环境:
核心配置
MODEL_PROVIDER=anthropic
MODEL_NAME=claude-opus-4-8
ANTHROPIC_API_KEY=your-api-key-here
记忆配置 —— 使用绝对路径
MEMORY_BACKEND=sqlite
MEMORY_PATH=/Users/yourname/agent-data/memory.db
调度器配置
ENABLE_SCHEDULER=true
SCHEDULER_TIMEZONE=America/New_York
输出配置 —— 结果存放位置
OUTPUT_PATH=/Users/yourname/agent-outputs
失败恢复
SKILL_RETRY_ENABLED=true
SKILL_RETRY_MAX=3
SKILL_RETRY_DELAY=300
通知
NOTIFICATION_GATEWAY=telegram
TELEGRAM_BOT_TOKEN=your-bot-token
TELEGRAM_CHAT_ID=your-chat-id
编写 CLAUDE.md:
这是整个设置中最重要的文件。每个 Agent 会话都从读取它开始。所有输出的质量都取决于这里内容的详细程度。
Agent 配置 —— CLAUDE.md
身份与目的
[用一段话描述该 Agent 的具体用途。
不是 Claude 的通用功能,而是该特定 Agent
配置用于该特定操作的具体任务。]
操作背景
[描述该 Agent 运行的业务或个人背景。
配置此 Agent 的人做什么工作?
他们的标准与优先级是什么?]
当前活跃任务
[列出该 Agent 运行的具体重复性任务。
对于每个任务:做什么、何时运行、好的输出是什么样的。]
工具权限
你有权限自主使用以下工具:
- 文件系统:读取和写入 [特定路径]
- 网络搜索:用于 [特定主题] 的研究
- [其他工具及具体范围]
你不可以:
- 写入配置输出目录之外的任何路径
- 进行上述清单之外的外部 API 调用
- 在未获得明确批准的情况下采取任何影响外部系统的行动
质量标准
[描述每种任务类型的良好输出是什么样的。
尽可能提供示例。
具体到 Agent 能够自我评估的程度。]
记忆指令
在记忆中存储:
- 每次重要输出及其日期和质量评估
- 遇到的每个边缘情况及其处理方式
- 每次质量失败及其原因
- 跨输出识别出的每个模式
错误处理
工具失败时:重试一次,记录失败,继续使用可用工具。
质量失败时:使用特定修正重试,而不是完全重写。最多三次重试。
无法恢复的失败时:保存部分工作,记录具体失败,发送通知,优雅停止。
构建任务定义层
任务定义层是大多数真实 Agent 失败的地方。
人们只写了一个描述理想路径的提示词就停手了。Agent 能很好地处理理想路径,但遇到其他情况就会崩溃。
一个健壮的任务定义涵盖了任务的完整操作现实。以下是模板:
[任务名称]
目的
[一句话:该技能完成什么?]
触发条件
[导致此任务运行的确切条件:
定时、文件出现、手动命令等。]
执行前检查
开始前验证:
- [所需输入存在且可访问]
- [所需工具已连接并响应]
- [输出路径可写]
- [记忆可访问且最新]
如果任何检查失败:记录失败并停止。
不要缺少先决条件就继续。
主要流程
步骤 1:加载上下文
读取 CLAUDE.md 获取完整操作上下文。
读取记忆中标记为 [任务标签] 的相关历史。
注意之前执行中可能影响本次执行的模式。
步骤 2:处理输入
[准确描述如何处理输入。
涵盖主要格式以及实践中出现的替代格式。]
对于标准输入格式:
[准确处理步骤]
对于替代输入格式 A:
[如何处理]
对于替代输入格式 B:
[如何处理]
对于格式错误或缺失的输入:
[如何处理 —— 切勿静默失败]
步骤 3:核心执行
[技能的实际工作。
分解为子步骤。每个子步骤应足够具体,
以至于一个新的 Claude 实例无需额外上下文就能执行。]
步骤 4:质量验证
在保存输出前,对照以下标准验证:
必需的:[不可协商的输出属性]
优选的:[能提升输出质量的属性]
禁止的:[不应出现在输出中的内容]
如果输出未通过必需的检查:
- 具体指出失败点
- 使用针对性修正重试
- 最多三次重试
- 如果三次后仍失败:以失败标志保存
步骤 5:输出与存储
保存输出到:[具体路径和文件名格式]
存储在记忆中,标记:[任务标签, 日期]
如果当前信息发生变化,更新 CLAUDE.md
发送通知:[通知中包含什么内容]
边缘情况
[边缘情况 1 名称]
条件:[何时发生]
检测:[如何识别]
响应:[做什么]
[边缘情况 2 名称]
条件:[何时发生]
检测:[如何识别]
响应:[做什么]
[边缘情况 3 名称]
条件:[何时发生]
检测:[如何识别]
响应:[做什么]
质量标准
优秀的输出:[具体描述]
可接受的输出:[最低标准]
不可接受的输出:[应触发重试的情况]
记忆指令
每次执行后存储:
- 执行日期和时长
- 输出质量评估(优秀/可接受/失败)
- 遇到的任何边缘情况及其处理方式
- 值得为未来执行记录的任何模式
你的第一个真实 Agent:研究与简报 Agent
这是一个使用此架构构建的完整真实 Agent。该 Agent 每天监控一组来源,研究工作相关的主题,并在每个早晨提供一份结构化简报。
这不是一个玩具任务。这是一个真正的工作流程,每天可替代四十五分钟的手动研究整理工作。
创建 skills/research-brief.md:
research-brief
目的
监控已配置的来源,生成一份结构化情报简报,
涵盖与当前项目和优先级相关的进展。
触发条件
定时:每天早上 6:00。
手动:"Research brief" 或 "Morning brief"
执行前检查
开始前验证:
- CLAUDE.md 在 07-SYSTEM/CLAUDE.md 可读
- Brave Search MCP 正在响应
- 输出路径 outputs/briefings/ 可写
- 记忆数据库可访问
主要流程
步骤 1:加载上下文
完整读取 CLAUDE.md。注意:
- 当前活跃项目及其状态
- 标记为待监控的主题
- 需要情报的待定决策
- 本简报的质量标准
读取标记为 research-brief 的记忆。
注意:最近简报中已涵盖的内容,避免重复。
步骤 2:来源研究
针对 CLAUDE.md 监控列表中的每个主题:
搜索查询:"[主题] news last 24 hours"
收集:标题、来源、日期、关键声明
应用信号过滤器:
包括:新进展、数据、产品发布、重要声明、研究发现
排除:对已有报道的重复、无新信息的观点、最近 3 份简报中已涵盖的内容
对于每个通过信号过滤器的结果:
如果初始结果暗示重大进展,则进行跟进搜索以深入研究。
步骤 3:综合
按主题对发现进行分组。
对于每个主题组,确定:
- 最重要的一项进展
- 为何对当前项目重要
- 暗示了什么行动(如果有的话) 跨主题综合:
- 是否有两个或更多发现相互关联,暗示更大模式?
- 是否有任何发现直接影响活跃项目或待定决策?
步骤 4:质量验证
最终确定前验证:
必需的:
- 至少 3 个信号项(非噪声)
- 每个项都有具体来源
- 每个项都解释了对当前工作的相关性
- 没有项在过去 5 份简报中出现过 优选的:
- 至少一个跨主题关联
- 至少一个项暗示具体行动
- 如果当天新闻较少,诚实承认 禁止的:
- 缺乏具体证据的泛泛分析
- 有趣但不相关的项
- 为了让简报看起来更全面而填充内容
如果简报未通过必需检查:具体指出缺少什么,
在重试前搜索额外来源。不要用弱信号填充。
步骤 5:生成输出
按以下确切格式生成简报:
早间情报简报 —— [日期]
今日最重要事项
[最重要的进展及其对当前工作的重要性。具体且有依据。]
信号项
[主题 1]
进展: [发生了什么]
来源: [出版物,日期]
相关性: [为何对当前项目重要]
启示: [暗示了什么行动]
[主题 2]
[相同格式]
[继续每个信号项]
关联
[如果两个或更多项相互关联,暗示更大模式,
在此描述。若无真正关联则跳过。]
决策相关性
[如果有任何项与 CLAUDE.md 中待定决策直接相关,
在此具体标注。]
覆盖说明
[诚实评估:全面日 / 新闻淡日。
搜索的来源数量。]
步骤 6:存储与通知
保存到:outputs/briefings/[日期]-morning-brief.md
存储在记忆中:
- 日期:[今天]
- 涵盖项:[主题列表]
- 质量:[优秀/可接受/失败]
- 备注:[任何边缘情况或模式]
- 标签:research-brief
发送 Telegram 通知:
"早间简报已就绪:[N] 个信号项。
[今日最重要一行]"
边缘情况
某主题未发现信号
条件:搜索未返回新进展
检测:所有结果均超过 48 小时
响应:该主题标记为"无新进展"。不要编造或填充。转向下一个主题。
来源返回冲突信息
条件:两个来源报告矛盾事实
检测:在具体声明上直接矛盾
响应:报告两个版本,引用两个来源,标记为冲突。不要选择其一。
搜索工具不可用
条件:Brave Search MCP 未响应
检测:工具调用返回错误
响应:记录失败。通过 Telegram 通知。保存部分简报并注明:"搜索不可用——简报仅基于记忆上下文"。不要静默失败。
简报会重复昨天的主要项
条件:最重要进展与昨天相同
检测:与记忆中昨天的简报交叉引用
响应:注明"来自 [日期] 的持续进展",并聚焦今天具体的新内容。
质量标准
优秀简报:4-6 个信号项。每项都相关。至少一个跨主题见解。5 分钟内可读完。
可接受简报:3 个信号项。全部相关。无跨主题见解。5 分钟内可读完。
不可接受简报:少于 3 个信号项。任何泛泛或与当前工作不相关的项。最近 3 份简报中的重复项。
构建质量验证层
质量验证层是区分输出一致的 Agent 与输出多变的 Agent 的关键。
大多数 Agent 完全跳过这一层。它们生成输出就直接返回。输出质量完全取决于生成时的好坏。有些会话优秀,有些平庸。你永远不知道会得到哪个。
质量验证层通过对照定义的标准检查每个输出,并在未达标时使用特定修正重试,从而使输出质量保持一致。
以下是实现质量验证的 Claude API 调用模式:
async function executeWithQualityVerification(prompt, qualityStandard, maxRetries = 3) {
let attempt = 0;
let lastOutput = null;
let lastFailure = null;
while (attempt < maxRetries) {
// 生成输出
const response = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.ANTHROPIC_API_KEY,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-opus-4-8',
max_tokens: 4096,
messages: [
{
role: 'user',
content: attempt === 0
? prompt
: ${prompt}
上一轮尝试未通过质量检查:${lastFailure}
针对此失败进行具体修正。不要重写所有内容。
}
]
})
});
const data = await response.json();
lastOutput = data.content[0].text;
// 验证质量
const verificationResponse = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.ANTHROPIC_API_KEY,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-opus-4-8',
max_tokens: 1000,
messages: [
{
role: 'user',
content: `你是一个质量检查员。对照以下标准评估此输出:
${qualityStandard}
要评估的输出:
${lastOutput}
仅回复:
PASS 如果输出满足所有必需标准
FAIL: [具体描述失败项] 如果不满足必需标准
不要解释。不要建议改进。只需 PASS 或 FAIL 加上具体的失败描述。`
}
]
})
});
const verificationData = await verificationResponse.json();
const verificationResult = verificationData.content[0].text.trim();
if (verificationResult.startsWith('PASS')) {
return { output: lastOutput, attempts: attempt + 1, passed: true };
}
lastFailure = verificationResult.replace('FAIL:', '').trim();
attempt++;
}
// 所有重试均已耗尽
return {
output: lastOutput,
attempts: maxRetries,
passed: false,
failure: lastFailure
};
}
此模式生成输出,对照定义的标准检查,并在失败时使用特定修正重试。如果所有重试均失败,则返回带有失败标志的最佳输出,而不是崩溃。
记忆集成模式
记忆是将一个有能力但有限的 Agent 转变为不断学习的 Agent 的关键。
没有记忆,每个会话都从零开始。Agent 不知道之前做过什么,无法应用过去执行中学到的经验,也无法避免已经犯过的错误。
有了记忆,每个会话都建立在前一次的基础上。Agent 知道什么有效、什么无效,并应用累积的上下文来改进当前输出。它会随着时间推移在特定任务上变得更好。
以下是任何 Claude Agent 的记忆集成模式:
每次执行开始时:
读取标记为 [任务标签] 的记忆条目。
限制:20 条最相关的条目。
策略:相关性(不仅仅是时间先后)。
应用此上下文:
- 注意先前执行中的模式
- 注意之前遇到的边缘情况
- 注意之前发现的质量问题
- 将经验应用于当前执行
每次执行结束时:
在记忆中存储:
- 日期:[今天]
- 任务:[任务名称]
- 质量:[优秀/可接受/失败]
- 备注:[任何值得记住的内容]
- 边缘情况:[遇到的任何边缘情况]
- 模式:[观察到的任何模式]
- 标签:[任务标签],[日期]
每月整合:
读取标记为 [任务标签] 的所有记忆条目。
识别:
- 跨多个条目出现的模式
- 重复出现的边缘情况
- 重复出现的质量问题
- 优秀输出与可接受输出之间的关联因素 整合为单个更新的上下文条目。 将超过 90 天的单个条目存档。
失败恢复系统
真实世界的 Agent 会遇到失败。来源离线,API 限流,文件不在预期位置,输出在最大重试次数后仍无法通过质量检查。
失败恢复系统决定了这些失败是不可见的短暂波动,还是灾难性的停滞。
三个层级的失败处理:
第一层级:自动恢复
可重试解决的暂时性失败。工具不可用、网络超时、触发限流。
第一层级恢复协议
任何工具调用失败:
- 等待 60 秒
- 重试完全相同的调用
- 如果重试成功:正常继续,记录短暂异常
- 如果重试失败:升级到第二层级
第二层级:优雅降级
无法解决但允许部分完成的失败。一个来源不可用、一个工具无响应、输出中的某个部分未通过质量检查。
第二层级恢复协议
对于无法解决的部分失败:
- 完成可以完成的部分
- 具体说明跳过了什么及原因
- 在文件名中标记输出为部分输出
- 在输出本身中包含明确说明
- 发送通知:"部分输出 —— [具体原因]"
- 不要因一个组件失败而让整个任务失败
第三层级:优雅停止
使整个任务不可能的失败。未找到 CLAUDE.md、输出路径不可写、记忆数据库无法访问。
第三层级恢复协议
完全失败时:
- 识别具体失败点
- 将已完成的任何工作保存到临时位置
- 记录完整的失败上下文
- 发送通知:"任务失败 —— [具体原因]"
- 干净停止,不破坏任何现有输出
- 不要自动重试 —— 等待人工干预
部署前测试 Agent
真实 Agent 部署中最常见的错误是跳过结构化测试。
在任何 Agent 上线前需要三个测试阶段:
阶段 1:组件测试
在测试整个工作流程之前,单独测试每个组件。
测试记忆是否持久化
hermes chat
你存储的最早的记忆条目是什么?
预期:应报告一个条目或报告数据库为空
如果返回错误:记忆配置错误
测试工具访问
列出 [输出路径] 中的文件
预期:应列出实际文件
如果返回错误:文件系统 MCP 配置不正确
测试搜索
搜索"AI news today"并告诉我最热门的结果
预期:应返回实际搜索结果
如果返回错误:Brave Search MCP 配置不正确
阶段 2:理想路径测试
手动运行技能,使用干净的标准输入,验证输出是否符合质量标准。
手动运行技能
hermes run research-brief
检查输出
cat outputs/briefings/[今天日期]-morning-brief.md
对照质量标准验证:
- 最少 3 个信号项?
- 每项都与当前工作相关?
- 无泛泛分析?
- 5 分钟内可读完?
阶段 3:边缘情况测试
故意触发每个已记录的边缘情况,验证恢复行为。
测试:无网络访问
在 .env 中禁用 Brave Search
运行技能
预期:第三层级失败,干净停止,通知已发送
测试:输出路径不可写
将 OUTPUT_PATH 更改为不存在的目录
运行技能
预期:第三层级失败,干净停止,通知已发送
测试:新闻淡日
在周末或节假日运行
预期:第二层级输出,包含指示当日新闻较少的 COVERAGE NOTE
在生产环境中运行 Agent
一旦所有三个测试阶段都通过,配置调度器并投入生产。
{
"schedules": [
{
"skill": "research-brief",
"cron": "0 6 *",
"description": "每天早 6 点",
"timeout_minutes": 15,
"on_failure": "notify_and_stop"
}
]
}
在后台模式下启动 Hermes:
npm run start -- --daemon
验证第一次定时运行:
检查 6 点后的日志
cat logs/hermes-[日期].log
检查是否生成了输出
ls outputs/briefings/
检查记忆是否已更新
hermes chat
你有多少条 research-brief 记忆条目?
如果第一次自动运行产生了良好输出,则 Agent 已投入生产。
到第 3 个月会发生什么
第一个月:Agent 运行可靠。输出一致。失败处理优雅。你每天早上节省四十五分钟。
第二个月:记忆层开始产生明显的改进。Agent 已处理了六十天的信息来源,并积累了关于哪些来源产生高信号内容与噪音的上下文。信号过滤的质量提高了,因为 Agent 已经学会哪些来源值得关注。
第三个月:记忆整合已经运行了两次。Agent 识别出跨越 90 天研究的模式。简报引用了累积的上下文,使得它们比任何单次研究都更加扎实和具体。
第三个月的 Agent 已经不是在执行与第一个月相同的工作流程了。
它正在运行一个改进版本的工作流程,基于 90 天积累的操作智能。
这就是教程 Agent 与真实世界 Agent 的区别。
教程 Agent 执行任务。
真实世界 Agent 学会更好地执行任务。
这个周末打好基础。
运行一周。修复出问题的地方。
运行一个月。观察它改进。
运行三个月。注意它掌握的知识,是你在第一天无法告诉它的。
这就是构建一个真正能在现实世界中运行的 Claude Agent 的样子。
关注 @cyrilXBT,获取每个 Agent 架构、技能模板和生产部署模式,让你的 Claude Agent 在现实世界中存活下来。





