基于Claude Agent SDK构建具备自我修复能力的AI内容代理系统
1. 项目概述:一个能自我修复的AI内容代理
每天花两三个小时,重复着写稿、排版、发帖、剪视频的机械劳动,这种“内容苦力”的日子我过了很久。直到有一天,我决定把这一切交给一个永不疲倦的助手。我构建了一个基于Claude Agent SDK的AI内容代理,它不仅能自动完成跨平台内容创作与发布的全流程,更重要的是,它具备“自我修复”能力——当任务出错时,它能自己分析问题并尝试解决。这个代理24小时运行在我的一台Mac mini上,成本近乎为零(主要利用已有的Claude订阅),却替代了原本需要大量人力投入的工作。这不是一个简单的脚本或聊天机器人,而是一个拥有持久记忆、能进行上下文决策、并通过Discord与我协同的智能工作流中枢。如果你也厌倦了重复的内容运营,希望将创造力从执行中解放出来,那么这套架构和思路或许能给你带来一些切实的启发。
2. 核心架构设计:从临时任务到持久智能体
最初的版本是一个简单的Python守护进程,它为每个任务(比如发推、生成视频)单独启动一个Claude进程。虽然能跑起来,但有个致命缺陷:每个任务都是“失忆”的。代理不知道昨天发了什么,也不知道上周哪个视频爆了,每次执行都像是第一次工作。这种设计无法积累经验,更谈不上优化。
2.1 持久化会话:智能体的“记忆核心”
现在的架构核心是一个永不终止的TypeScript智能体会话。无论是来自Discord的指令、定时触发的任务,还是Webhook事件,所有输入都汇入同一个代理循环。这意味着代理能在所有交互中保持完整的上下文记忆。
实现这一点的关键是Anthropic的Claude Agent SDK,特别是其流式输入模式。代理启动后便持续运行,随时准备接收新消息,而不是每次处理完请求就关闭。这为构建复杂的、有状态的自动化提供了可能。
// agent.ts - 持久化会话与消息队列的核心 import { Agent } from '@anthropic-ai/agent-sdk'; const agent = new Agent({ model: 'claude-sonnet-4-20250514', tools: [...mcpTools, ...agentTools], // 集成的所有工具 systemPrompt: loadFile('SOUL.md'), // 代理的“人格”与指令 }); // 统一的消息队列:Discord、定时器、Webhook都向这里推送 const messageQueue: Message[] = []; export async function sendMessage(content: string, source: string) { messageQueue.push({ content, source, timestamp: Date.now() }); await processQueue(); // 顺序处理队列,保证上下文连贯 }这种设计带来了几个关键优势:
- 上下文连贯性:代理在起草推文时,能参考昨天同类内容的互动数据;在生成视频脚本时,能记住哪些话题更受观众欢迎。
- 错误恢复与自我修复:当任务失败时,代理是在完整的会话上下文中看到错误信息的。它知道之前执行了哪些步骤、调用了什么工具,因此能做出更有针对性的修复尝试,而不是盲目重试。
- 会话持久化:即使进程因意外崩溃重启(由pm2自动处理),代理也能从磁盘加载之前的会话ID,恢复几乎全部的历史上下文,工作不会中断。
2.2 事件驱动与统一入口
整个系统的入口点index.ts非常简洁,它初始化了代理,并连接了所有输入源:
// index.ts — 系统入口 async function main() { const agent = await startAgent(); // 启动持久化Agent SDK会话 const bot = await startDiscord(agent); // 启动Discord机器人,将消息转发给agent startScheduler(agent); // 启动node-cron定时任务,将任务提示词喂给agent startWebhooks(agent); // 启动GitHub等Webhook监听器 // 代理上线通知 await bot.sendMessage('general', 'Koda已上线,等待任务中。'); }所有外部事件(消息、定时任务、Webhook)都被转化为统一的“消息”格式,推入代理的消息队列。代理按顺序处理,确保了任务执行的原子性和上下文的一致性。这种架构模仿了人类的工作方式:一个持续运转的大脑,处理来自不同渠道的异步请求。
3. 任务调度与风险管控:让自动化安全可控
一个全自动的内容系统,最大的风险莫过于失控。你绝对不想一觉醒来,发现AI因为误解了某个热点,发布了一条不合时宜的内容。因此,精细化的任务调度与风险分类机制是系统安全的基石。
3.1 基于node-cron的智能调度
我使用了node-cron库来管理所有定时任务。目前系统里有17个定时任务,从数据分析到内容创作,覆盖了日常运营的各个方面。关键设计在于,每个任务本质上是一个发送给持久化代理的“提示词”,代理在完整的上下文中执行它。
// scheduler.ts - 任务调度配置 const tasks: ScheduledTask[] = [ { name: 'youtube_analytics', cron: '0 7 * * *', // 每天上午7点 prompt: '拉取过去7天的YouTube数据分析,并与上一周期进行对比。', type: 'silent' // 静默执行,无需批准 }, { name: 'viral_scan', cron: '0 10 * * *', // 每天上午10点 prompt: '扫描X(原Twitter)上AI/自动化领域的病毒式推文,并起草引用推文(quote tweet)进行战术分析。', type: 'approval' // 需要我在Discord上批准 }, { name: 'social_post', cron: '0 12 * * *', // 每天中午12点 prompt: '遵循brand-voice-skill.md中的品牌语调,为X平台起草一篇帖子。', type: 'approval' }, { name: 'goal_check', cron: '0 8 15 * * *', // 每天上午8点15分 prompt: '检查GOALS.md中设定的目标。如果有任何目标落后于计划,提出应对行动建议。', type: 'silent' } ];任务去重机制:为了防止意外重复执行(比如手动触发了一个本该定时执行的任务),系统会检查.task-results/YYYY-MM-DD.json目录下的记录。如果某个任务当天已经成功运行过,再次触发时会被自动跳过。这个简单的机制避免了很多数据混乱和资源浪费。
3.2 YOLO风险分类器:为每把“刀”装上刀鞘
不是所有自动化操作的风险等级都一样。读取数据是安全的,但发布内容则是高风险的。我实现了一个简单的“风险分类器”,为每一个工具调用(Tool Call)标注风险等级。
// 风险等级分类器 const riskLevels = { HIGH: ['post_tweet', 'publish_video', 'delete_tweet', 'gmail_send'], // 发布、删除、发送邮件 MEDIUM: ['generate_image', 'skool_airtable_sync', 'create_record'], // 生成内容、同步数据 LOW: ['youtube_analytics', 'gsc_search_analytics', 'gmail_search'] // 只读操作 };- 高风险操作:如发布推文、上传视频,会触发Discord审批流程。我必须点击✅,操作才会继续。
- 低风险操作:如拉取数据分析,完全静默执行,完成后结果会汇总报告给我。
- 中风险操作:行为是动态的。如果检测到我在Discord上活跃(近期有互动),它可能会直接执行并通知我;如果我在空闲状态,则会转为等待批准。这种设计在效率和安全之间取得了很好的平衡。
实操心得:风险分类的粒度:一开始我把所有写操作都设为高风险,后来发现像“在Airtable中创建一条草稿记录”这种操作,即使出错也容易回滚,完全没必要审批,徒增我的操作负担。所以,风险分类需要根据操作的实际影响面和回滚成本来仔细界定,这是一个持续优化的过程。
3.3 自我修复:从“报错”到“疗伤”
旧系统(Python守护进程)在任务失败时,只是记录错误日志然后通知我。新系统的“自我修复”能力是质的飞跃。当定时任务失败时,完整的错误堆栈信息会作为上下文反馈给同一个持久化代理会话。
由于代理“记得”它刚才试图做什么、调用了哪些工具、传入了什么参数,因此它能进行更有针对性的修复尝试。例如,如果是因为X(Twitter)API速率限制导致的失败,代理可能会在提示词中分析出这一点,然后自动在代码中为相关工具调用添加指数退避重试逻辑,并重新执行任务。
系统为每个失败任务提供最多2次自我修复尝试。如果修复成功,我会在Discord收到一条“🔧 已自我修复”的通知,并附上错误原因和修复措施。如果修复后仍然失败,才会升级为需要我人工介入的警报。这大大减少了需要我处理的琐碎故障。
4. 基础设施与进程管理:确保7x24小时稳定运行
一个需要长期在后台运行的服务,稳定性是第一位的。你不能让它运行几天就自己崩溃,或者日志文件把磁盘撑满。
4.1 使用PM2进行进程管理
我选择了pm2作为Node.js的进程管理器,它完美地解决了生产环境下的几个核心问题:
- 自动重启:通过
ecosystem.config.js配置,可以设定当应用崩溃或达到内存限制时,自动重启进程。我设置了最大重启次数为10次,超过后停止重启并报警,防止陷入崩溃循环。 - 日志管理:
pm2可以自动将标准输出和错误输出重定向到日志文件,并支持按日期或大小进行日志轮转(log rotation)。所有日志都存储在data/logs/koda-*.log路径下,方便排查问题。 - 监控与状态查看:通过简单的命令
pm2 status就能一眼看清所有进程的状态、运行时间、内存和CPU占用,非常直观。
# 启动代理(守护进程模式) npm run daemon # 这背后执行的是:pm2 start ecosystem.config.js # 查看状态 pm2 status # 查看实时日志 pm2 logs koda --lines 100 # 重启应用(比如在更新代码后) pm2 restart koda注意事项:环境变量与配置:在pm2的生态配置文件中,务必正确设置NODE_ENV=production以及所有必要的API密钥等环境变量。我推荐使用pm2的--env参数或配置文件来管理不同环境,避免将敏感信息硬编码在代码或启动命令中。
4.2 Discord作为控制平面:移动端的高效协同
为什么选择Discord而不是自己开发一个Web控制台?原因很简单:触达效率和交互丰富性。Discord App几乎永远在我手机的通知栏里,支持富文本嵌入、表情反应、线程对话,而且完全免费。
我使用discord.js库搭建了一个双向通信的机器人:
- 我 -> 代理:我可以在任何时间、任何地点,直接在Discord频道里输入指令,例如“检查一下YouTube数据”、“起草一篇关于AI代理的帖子”。机器人会将这些消息转发给代理处理。
- 代理 -> 我:代理将所有关键信息结构化地推送回Discord。
- 内容审批:当生成好一篇帖子或视频时,会发送一个包含详情(标题、内容、平台)的富文本消息,我只需点击附带的✅或❌表情即可完成审批。
- 分析摘要:每日或每周的数据报告会以清晰的格式呈现。
- 系统警报:包括自我修复成功/失败的通知、错误预警等。
这种基于聊天界面的交互,比登录一个Web面板、点击按钮要自然和快捷得多,真正实现了“在手机上点一下就能管理一切”。
5. 自动化视频生产管线:从脚本到多平台发布
内容创作中最耗时的环节之一就是视频制作。我的代理实现了一套全自动的短视频(特别是YouTube Shorts)生产线,从选题到发布,完全自动化,单条视频成本仅几美分(主要用于Gemini生成图像)。
5.1 六步流水线拆解
整个管线被设计成一个可独立执行也可按需调用的工作流,以下是其核心步骤:
- 脚本生成:代理根据当前热点或既定主题(例如“中子星的密度”),利用Claude生成一段适合短视频口播的叙事脚本。脚本会明确分段,为后续的图像匹配做准备。
- 图像生成:针对脚本的每一段叙述,代理调用Gemini AI的图像生成API,创建与之精确匹配的场景图。例如,说到“一茶匙中子星物质重达60亿吨”时,会生成一个展现超高密度物质的抽象科幻图像。这是主要的可变成本,但每张图成本极低。
- 语音合成:使用微软的Edge TTS服务,选择
en-US-AndrewNeural这类听起来自然的人声,将脚本合成为音频文件。Edge TTS免费、质量高,是本地部署的理想选择。 - 字幕与时间轴:利用Whisper.cpp(一个高效的Whisper语音识别C++移植版,特别优化了Apple Silicon性能)对生成的音频进行语音识别,并输出带精确到词级时间戳的SRT字幕文件。这为后续的视频合成提供了准确的文字同步基础。
- 视频渲染:使用Remotion这个基于React的编程式视频生成库。我定义了一个
TechTutorial的React组件,它将音频、按时间轴序列化的图像列表、字幕文件作为输入,渲染出垂直比例(1080x1920)的MP4视频。Remotion运行在Node.js环境下,渲染速度快,且完全可控。 - 缩略图与发布:代理再次调用Gemini生成一个吸引眼球的背景图,然后用Python的PIL库叠加上有发光效果的标题文字,生成视频缩略图。最后,调用YouTube Data API和Instagram Graph API(通过各自的MCP服务器),将视频、标题、描述、缩略图一并发布。
# 一体化执行命令示例 python orchestrate_video.py --topic "neutron_star_density" # 或者分步执行,便于调试 python generate_voiceover.py script.json npx remotion render TechTutorial output/video.mp4 --props=/tmp/props.json python publish.py output/video.mp4 --platforms youtube,instagram5.2 关键工具选型与避坑指南
- Remotion vs. FFmpeg:为什么选择Remotion?因为它是声明式的。我用React组件定义视频的每一帧,可以轻松实现复杂的动画、文字效果和转场。而用FFmpeg命令行拼接图片和音频,想要实现精细的图文同步和动画非常痛苦。Remotion的学习曲线稍陡,但换来的是无与伦比的灵活性和可维护性。
- Whisper.cpp的重要性:自动生成字幕不仅是可访问性的要求,也是短视频平台算法的推荐因素。Whisper.cpp本地运行,速度快,精度高,避免了调用云端API的延迟和成本。确保你的字幕时间轴准确,否则音画不同步会非常影响观感。
- 图像生成的提示词工程:让Gemini生成与脚本强相关的图像是关键。我的经验是,在提示词中不仅要描述场景,还要指定“短视频风格”、“动态构图”、“高对比度”、“适合文字叠加”等特性。可以建立一个图像风格的“提示词库”供代理选择,能显著提升出图质量。
一个常见的坑:平台规格。YouTube Shorts、Instagram Reels、TikTok对视频格式、时长、大小、封面图比例都有细微差别。我的做法是在渲染环节,就根据目标平台生成对应规格的最终视频文件,而不是用一个通用文件去所有平台发布,这样可以获得更好的播放体验和平台推荐。
6. 记忆系统:让AI代理真正“积累经验”
一个没有记忆的AI代理,就像金鱼,只有7秒的记忆。对于内容创作这种高度依赖历史数据和经验积累的工作来说,这是不可接受的。我为此设计了一个六层记忆系统,让代理能够学习、总结并应用经验。
6.1 记忆系统的六个层级
- 引导文件:这是代理每次启动时都会加载的“人格内核”。包括:
SOUL.md:定义了代理的核心身份、价值观和使命(例如,“你是一个专注于科技知识分享的创作者助手”)。SKILL.md:描述了代理掌握的所有技能和工具的使用规范。USER.md:关于我的偏好、写作风格、禁止事项等上下文信息。CLAUDE.md:给Claude模型的操作性指令,如思考链格式、输出要求等。
- 观察记录:代理在运行过程中,随时使用一个
observe()工具记录下它的“所见所闻”。例如:“关于‘太空’的短视频观看量是‘自然奇观’类的10倍”、“在X平台上,使用‘否定式清单’的帖子比‘功能列表’式帖子互动率更高”。每条观察都会被打上类型标签(rule,preference,fact,habit,event)。 - 梦境周期:这是一个在夜间运行的批处理任务,可以说是记忆系统的“消化”过程。它会:
- 去重:合并相似的观察记录。
- 衰减:根据类型应用重要性衰减。例如,一条
rule(规则)可能保留365天,而一个event(事件)14天后就过期。 - 提炼:将频繁出现(例如,出现超过3次)的模式,从零散的“观察”提升到下一层的“精选心得”。
- 每日日志:以时间线形式记录当天发生的所有重要行动、结果、决策和错误。这不是在一天结束时批量写的,而是在事件发生时持续追加,保证了记录的实时性和准确性。
- 精选心得:这是经过“梦境周期”提炼后的、浓缩的长期记忆,通常不超过100行。里面是像“短视频必须控制在60秒以内”、“图像必须与叙述句精确匹配”、“每周三发布技术教程类内容效果最好”这样的硬核经验。这些心得会直接作为上下文,影响代理未来的内容决策。
- 记忆检索:在代理需要做出任何决策(比如“今天写什么主题”)之前,它会自动在所有记忆层中搜索相关的历史信息。这确保了每一次创作都不是从零开始,而是站在过去经验的肩膀上。
6.2 “梦境周期”的设计价值
如果没有“梦境周期”,观察记录会无限制地堆积,很快代理就会被海量的、可能矛盾的、过时的信息淹没,导致“记忆污染”和决策瘫痪。“梦境周期”模拟了人脑的睡眠记忆巩固过程,它完成了三件关键事:
- 信息压缩:将冗余信息合并,节省上下文窗口。
- 知识提纯:将偶然事件与普遍规律区分开,只有被多次验证的模式才会进入长期记忆。
- 垃圾清理:让不重要的、过时的信息自然“遗忘”,保持记忆库的健康和相关性。
实现上,“梦境周期”本身也是一个由定时任务触发的代理工作。它会读取原始的observations.json,运行一个Claude任务来分析、归纳、清理,然后更新curated_learnings.md文件。这个过程完全自动化,是系统能够持续进化的核心。
7. MCP服务器:标准化工具集成
如何让AI代理安全、方便地调用各种外部API(如YouTube、Twitter、Gmail)?我选择了Anthropic提出的模型上下文协议。它为AI模型与外部工具/数据源的交互提供了一个标准化、类型安全、可发现的接口。
7.1 什么是MCP及其优势
简单说,MCP服务器就是一个中间层,它将对某个服务(如YouTube API)的所有复杂操作,封装成一系列带有清晰描述和参数定义的“工具”(Tools)。AI代理不需要知道OAuth 2.0流程、API速率限制或响应数据解析,它只需要调用像youtube_upload_video(title, filePath)这样的工具。
我为每个主要服务都建立了一个MCP服务器:
- YouTube MCP:上传视频、获取分析、管理播放列表、读取评论。
- X (Twitter) MCP:发布推文、获取互动指标、删除帖子。
- Bluesky MCP:发布、转发、点赞、获取时间线。
- Gmail MCP:搜索邮件、发送邮件、创建草稿、管理日历。
- Airtable MCP:读写表格,用于内容规划和CRM。
- Google Search Console MCP:获取搜索分析、索引状态。
- n8n MCP:触发和管理自动化工作流。
优势对比传统集成:
- 安全性:API密钥和令牌只存储在MCP服务器端,代理完全接触不到。MCP服务器可以实现精细的权限控制和审计日志。
- 可维护性:当某个API更新时,我只需要修改对应的MCP服务器,而不用改动代理的核心代码。
- 可发现性:代理在启动时能动态发现MCP服务器提供了哪些工具,并理解它们的用途,这使得工具集可以灵活扩展。
7.2 代理如何与MCP交互
在代码中,我只需将MCP服务器的工具列表注入到Claude Agent的初始化参数中。之后,代理就可以在思考过程中,像使用内置函数一样自然地调用它们。
// 在代理思考过程中,它可能会生成这样的“内心独白”并执行: // “我需要检查昨天的YouTube表现。让我调用'youtube_analytics_overview'工具,日期设为昨天。” const analytics = await callTool('youtube_analytics_overview', { start_date: '2026-04-04' }); // 然后它基于返回的结构化数据继续推理: // “数据显示观看量上升了23%,关于磁星的短视频开局不错,24小时内有847次观看。”这种交互模式非常符合LLM的“思考-行动”模式,让代理能够自主地使用复杂的外部系统来完成目标,而不是仅仅进行文本对话。
8. 从零开始构建的实践指南
如果你对这个架构感兴趣,也想尝试构建自己的AI代理,以下是我从实战中总结出的、按优先级排序的起步建议:
- 从Claude Agent SDK开始,而非封装CLI:我的第一个版本是封装Claude Code CLI的Python脚本,这是一个弯路。直接使用Claude Agent SDK,它能为你提供类型化的工具、流式输入、会话持久化等开箱即用的能力,是构建复杂代理的坚实基础。
- 尽早接入Discord作为控制平面:不要先埋头把全部自动化逻辑写完,再考虑怎么控制。一开始就搭建一个简单的Discord机器人(
discord.js很简单),让每一个重要动作都向Discord发送消息,每一个高风险操作都等待Discord上的批准。这会迫使你思考人机交互的界面,并让你从第一天起就能安全地测试和监控系统。 - 使用PM2管理进程:不要自己写守护进程或重启脚本。
pm2是经过时间检验的Node.js进程管理工具,能为你处理崩溃重启、日志轮转、性能监控这些繁琐但至关重要的事情。直接用它。 - 实施风险分类:在编写每一个工具函数时,就思考它的风险等级。建立一个类似前文提到的
riskLevels映射表。这不仅仅是安全措施,也是一种设计规范,它能帮你厘清哪些操作是核心的、不可逆的。 - 哪怕先做一个简单的记忆系统:即使只是一个
LEARNINGS.md文件,让代理在每次启动时读取,并在运行中追加新的心得,也会让它的表现随着时间产生肉眼可见的提升。记忆是智能体区别于普通自动化脚本的灵魂。
构建这样一个系统更像是在培育一个数字助手,而不是编写一段程序。你需要为它设定目标、提供工具、建立沟通机制,并设计学习反馈循环。过程中会遇到无数细节问题,比如API限流、错误处理、上下文管理,但每解决一个,系统的稳健性和智能性就增加一分。当它第一次成功自我修复了一个你未曾预料到的错误时,那种感觉是非常奇妙的。这不仅仅是节省了时间,更是创造了一个能够持续学习和成长的合作伙伴。
