基于Docker与Claude SDK构建AI代理:Nagi项目架构解析与实战
1. 项目概述构建你的个人AI副驾如果你和我一样每天的工作流被Slack、Discord、Asana等工具切割得支离破碎总是在不同应用间切换重复着“复制-粘贴-提问-等待”的循环那么你大概也幻想过能有一个“数字副驾”。它不需要你打开复杂的控制台就在你日常沟通的聊天窗口里你它一下它就能理解你的意图调用合适的工具在后台默默地把事儿给办了最后把结果干净地呈现在对话线程里。这就是Nagi凪项目试图解决的问题——它不是另一个需要你单独登录的AI平台而是一个能嵌入到你现有工作流中的、静默而强大的AI代理基盘。Nagi的核心设计理念非常明确“无感集成静默执行”。它的名字“凪”在日语中意为“风平浪静”完美诠释了其定位——一个不会打乱你现有工作节奏却能帮你平息各种繁琐事务“风波”的伙伴。技术上它选择在Docker容器中运行基于Claude Agent SDK构建的AI代理并通过插件系统与Slack、Discord、Asana等消息通道通信。这意味着AI的能力被封装在隔离、可复现的环境里而与你交互的界面就是你早已熟悉的团队协作工具。我最初被这个项目吸引是因为它干净利落地解决了一个痛点上下文割裂。当我在Asana的任务评论里和同事讨论一个功能需求时突然需要AI帮忙写段代码或查个数据传统做法是切到另一个AI工具描述一遍背景再把结果复制回来。这个过程不仅低效还容易丢失上下文。Nagi让我可以直接在Asana任务里ai它能看到整个任务的历史、描述和评论基于完整的上下文给出响应甚至把执行过程和结果都作为子任务更新保持主任务的整洁。这种“在哪提问就在哪解决”的体验一旦用上就回不去了。2. 架构设计与核心思路拆解Nagi并非从零开始的发明它被明确标注为对开源项目NanoClaw的一次“洁净室”重新实现。理解这一点对把握其设计精髓很重要。NanoClaw本身是一个优秀的AI代理框架而Nagi在汲取其核心思想容器化AI代理、消息通道集成的同时在工程架构上做了更具现代感和可维护性的选择。2.1 为什么选择Turborepo单体仓库架构打开Nagi的代码仓库你会发现它是一个标准的Turborepo结构。这意味着它将前端仪表板apps/ui、后端核心服务apps/api、各种通道适配器packages/channel-*、工具插件packages/tool-*以及共享的类型定义和工具函数packages/core全部组织在一个仓库中。这种选择背后有几点关键的考量开发体验与重构安全AI代理项目涉及前端、后端、多个通道客户端以及共享的业务逻辑。在单体仓库中你可以轻松地跨包进行代码引用和重构TypeScript能提供跨包的完整类型安全避免了在多仓库间同步类型和API定义的痛苦。当你需要修改一个共享类型时所有依赖它的包会立即在IDE中报错而不是在运行时才崩溃。构建与部署优化Turborepo的核心价值在于其智能的增量构建和缓存。假设你只修改了Discord通道适配器的代码Turborepo能精准地只重新构建依赖于该适配器的应用而跳过UI、API等其他未受影响的部分。这极大加速了本地开发测试和CI/CD流水线的速度。依赖管理一致性使用pnpm作为包管理器配合workspace:协议可以确保所有子包引用的是相同版本的第三方库彻底杜绝了“在我的机器上能用”这类因依赖版本不一致导致的问题。实操心得在搭建类似的多模块项目时我强烈建议从一开始就采用Turborepo pnpm的组合。初期可能会觉得配置稍显复杂但它为项目长期演进带来的可维护性收益是巨大的。一个常见的坑是忘记在根目录的turbo.json中正确配置dependsOn关系导致构建顺序错误。务必理清包之间的依赖图。2.2 依赖注入DI容器与插件系统Nagi的另一个核心设计是采用依赖注入DI来管理其复杂的内部组件。你可以在代码中看到大量使用injectable、inject装饰器的类。这不仅仅是追赶技术潮流而是为了解决AI代理系统固有的复杂性问题。一个AI代理运行时需要消息接收器Channel Adapter、AI模型客户端如Claude、工具执行器Tool Runner、会话管理器Session Manager、日志服务等。这些组件之间耦合度高且可能需要根据配置动态替换例如为测试替换真实的AI客户端为Mock客户端。传统的直接new实例的方式会让代码难以测试和扩展。DI容器Nagi使用了tsyringe充当了一个“智能工厂”。你只需要在类上标记injectable并在构造函数中声明你依赖的接口inject(Tokens.MessageService)容器会在启动时自动解析所有依赖关系并创建实例。这样做的好处是可测试性单元测试时你可以轻松注入模拟对象Mock。可配置性通过更换容器的注册绑定就能切换整个系统的实现比如将生产环境的Claude客户端切换为开发用的模拟客户端。松耦合组件之间依赖于抽象接口而非具体实现符合面向对象设计原则。插件系统则建立在DI之上。每一个“技能”Skill比如ai-changelog本质上就是一个实现了特定接口的插件。它声明自己需要的工具如浏览器操作、文件读写并在被调用时执行一系列动作。系统通过DI容器动态发现和加载这些技能插件实现了功能的即插即用。2.3 容器化隔离与复现性的基石“AI代理在Docker容器中运行”是Nagi区别于许多云端AI API调用的关键。这不仅仅是技术选型更是一种产品哲学。环境隔离每个代理任务都在一个全新的、干净的容器中启动。这意味着任务之间不会相互干扰一个任务把Python环境搞乱了完全不影响下一个任务。也杜绝了依赖冲突问题。复现性保障Docker镜像定义了完整的运行环境操作系统、语言运行时、系统依赖。今天能在你机器上成功运行的任务明天在服务器上、下个月在新同事的电脑上只要镜像相同就能以完全相同的方式运行。这对于自动化任务的可靠性至关重要。安全性边界尽管容器不是虚拟机的完全安全隔离但它提供了一个比直接在主机上运行脚本更强的安全层。你可以限制容器的网络、文件系统访问权限降低恶意或错误代码对主机造成损害的风险。Nagi使用了一个精心构建的基础镜像里面预置了Node.js、Python、浏览器用于自动化以及常用的CLI工具。当你触发一个任务时后端服务会docker run这个镜像将技能代码、必要的上下文如对话历史、文件作为卷Volume或环境变量注入然后在容器内启动代理执行。3. 核心组件与配置实战要真正让Nagi运转起来你需要配置好几个核心组件。下面我将以最常用的Slack集成和基础CLI为例拆解每一步的实操要点和背后的逻辑。3.1 通道集成以Slack为例的深度配置Nagi支持多种通道但Slack的集成因其“Socket Mode”而显得格外优雅——它不需要你的服务器有一个公网可访问的URL。1. 创建Slack应用首先前往 api.slack.com/apps 创建一个新的应用。这里有几个关键选择应用名称这就是将来在Slack里的机器人名字比如nagi-ai。工作区选择你要安装的Slack工作区。创建后进入“OAuth Permissions”页面在“Scopes”部分添加以下机器人令牌作用域Bot Token Scopesapp_mentions:read- 读取提及机器人的消息。chat:write- 以机器人的身份发送消息。channels:history(或groups:history如果是私密频道) - 读取频道历史用于获取上下文。im:history- 读取直接消息历史。im:write- 向用户发送直接消息。2. 启用Socket Mode这是避免配置公网URL的关键。在应用设置侧边栏找到“Socket Mode”启用它。启用后系统会生成一个“应用级令牌”App-Level Token。这个令牌以xapp-开头它不同于我们常见的机器人令牌xoxb-。为这个令牌添加connections:write作用域。3. 安装应用与获取令牌进入“OAuth Permissions”页面点击“Install to Workspace”按照指引将应用安装到你的工作区。安装成功后你会得到两个关键令牌Bot User OAuth Token(xoxb-...): 这是机器人令牌用于代表机器人执行大多数API操作如发消息。将其保存为SLACK_BOT_TOKEN。App-Level Token(xapp-...): 这是上一步生成的Socket Mode令牌用于建立长连接。将其保存为SLACK_APP_TOKEN。4. 在Nagi中配置Nagi项目提供了便捷的Claude Code技能来引导配置。在项目根目录运行claude命令这假设你已配置好Claude Code然后在Claude Code界面中输入/add-channel-slack。这个技能会交互式地引导你输入上面获取的SLACK_BOT_TOKEN和SLACK_APP_TOKEN。它会帮你测试连接并在成功后自动更新Nagi的配置文件通常是config/default.yml或环境变量。技能还会指导你如何在Slack频道中邀请机器人/invite 你的机器人名。背后的原理启用Socket Mode后你的Nagi服务端作为Slack客户端会主动与Slack服务器建立一个持久的WebSocket连接而不是Slack向你的公网URL发送HTTP请求。连接建立后当有人在频道中你的机器人时事件会通过这个长连接推送到你的Nagi服务端。这种方式完美解决了开发或内网部署没有固定公网IP/域名的难题。注意事项SLACK_APP_TOKEN(xapp-) 权限很高务必妥善保管不要泄露。如果Slack频道是私密的确保已将创建的应用机器人邀请进该频道。本地开发时确保防火墙或网络策略允许出站连接到wss://wss-primary.slack.com。3.2 CLI工具不依赖消息通道的快速交互除了通过Slack等通道触发Nagi也提供了强大的命令行界面CLI这对于调试、一次性任务或集成到其他脚本中非常有用。安装并构建项目后你可以使用pnpm nagi命令# 运行一个简单的查询 pnpm nagi 东京今天会下雨吗 # 运行一个特定的技能并传递参数 pnpm nagi run skill:ai-changelog --provider openai --provider anthropic --days 7 # 列出所有可用的技能 pnpm nagi --list # 查看特定技能的帮助信息 pnpm nagi run skill:ai-changelog --helpCLI的工作流程是解析你的命令和参数。根据配置初始化一个“直接通道”Direct Channel会话这模拟了一个消息通道的环境但输入输出是终端。同样在Docker容器中启动AI代理执行对应的技能或处理自然语言请求。将代理的思考过程、工具调用和最终结果流式地输出到终端。CLI的实用场景技能开发与调试在将技能部署到Slack之前先用CLI快速测试其逻辑和参数解析是否正确。自动化脚本你可以将pnpm nagi命令写入cron作业或CI/CD流水线定期执行报告生成、数据抓取等任务。复杂任务探索有些任务可能需要多轮对话。在终端里与AI交互可以更自由地尝试不同的指令而不必在团队频道里刷屏。3.3 技能Skill系统剖析技能是Nagi执行具体工作的单元。一个技能本质上是一个包含元数据名称、描述、参数模式和执行逻辑的模块。以项目示例中的ai-changelog技能为例它的工作流程是触发用户在Slack中发送ai ai changelog。解析Nagi的路由器将消息匹配到ai-changelog技能并解析可能的参数如--provider anthropic。准备容器系统创建一个临时目录将技能代码、必要的上下文当前对话线程注入。容器内执行在Docker容器中Claude Agent被启动。它读取技能指令开始“思考”调用浏览器工具打开Anthropic、OpenAI等AI提供商的官方博客或更新日志页面。抓取过去一周或指定天数的发布内容。对内容进行总结、提炼。调用代码工具生成一个简单的静态网站可能是用Next.js或纯HTML将总结内容格式化展示。调用部署工具如Vercel CLI将网站部署到临时地址。回复容器执行完毕将结果部署成功的URL和过程中的关键日志token消耗、工具调用传回给Nagi主服务。消息发送Nagi将最终结果和摘要发送回原始的Slack线程。如何创建一个自定义技能Nagi的插件系统使得添加技能相对简单。通常步骤是在packages/目录下创建一个新的包例如skill-my-custom。定义一个主类实现ISkill接口需要提供name、description和一个execute方法。在execute方法中你可以通过注入的AgentExecutor来与Claude交互并声明本技能可以使用的工具如UseTool(BrowserTool)。在包的index.ts中使用container.register将你的技能类注册到DI容器。最后在核心应用的配置或模块中导入你的技能包使其被自动发现和加载。4. 监控与管理Dashboard UI详解一个在后台默默工作的AI代理如果无法观察其状态和历史会让人感到不安。Nagi内置的Dashboard UI正是为了解决可视化和可观测性问题。通过运行pnpm ui:dev你可以同时在本地启动前端SPA端口5174和后端API服务器端口3001。访问http://localhost:5174即可打开仪表板。仪表板核心功能模块解析概览Overview以数据卡片形式展示系统关键指标已注册的代理组Groups、活跃的消息通道Channels、执行过的任务Tasks、进行中的会话Sessions以及日志条目数量。这让你对系统整体负载和健康状态一目了然。组与通道Groups / Channels组GroupsNagi可以将代理逻辑上分组例如“数据分析组”、“客服自动化组”。这里管理这些组的配置。通道Channels这里列出所有已配置的集成通道Slack工作区、Discord服务器、Asana项目。每个通道会显示其连接状态在线、离线、错误、最后活动时间等。点击进入可以查看更详细的配置和连接日志。会话Sessions这是最有用的页面之一。它以聊天界面的形式完整重现了AI代理与用户的一次次交互。每条用户消息和AI回复都被记录。更重要的是你可以点击展开AI回复的“思考过程”看到一个清晰的时间线Timeline展示了Claude在生成最终回复前内部进行了哪些“思考”Reasoning调用了哪些工具Tool Calls以及每次工具调用的输入和输出是什么。这对于调试复杂技能和理解AI决策逻辑至关重要。如果结果不符合预期你可以回溯查看是工具调用失败了还是AI误解了指令。任务Tasks展示所有计划任务和已执行任务的历史列表。对于周期性任务如每天早晨生成报告你可以在这里查看其执行计划、上次执行时间、下次执行时间以及历史执行记录成功/失败。日志Logs聚合了系统层和容器层的日志。你可以按日志级别Info, Warn, Error进行过滤搜索特定的任务ID或会话ID。当容器内执行出错时这里的错误堆栈信息是排查问题的第一手资料。设置Settings目前主要是UI主题切换深色/浅色。未来可能会扩展更多的系统配置项。技术栈选择考量仪表板采用React 19 Vite Tailwind CSS 4 Hono用于API。这是一个非常现代、高效的全栈JavaScript组合。Vite提供极速的开发服务器和构建体验Tailwind CSS 4在性能和功能上都有提升Hono作为一个轻量级但功能强大的Web框架非常适合构建这种RESTful API。选择React 19而非更轻量的方案可能是考虑到仪表板未来交互复杂度会增长需要成熟组件生态的支持。5. 部署考量与生产环境实践将Nagi从本地开发环境移至生产环境需要考虑几个关键方面稳定性、安全性、可维护性和成本。5.1 部署架构建议对于个人或小团队使用一个简单可靠的部署架构如下[ Slack/Discord/Asana ] -- WebSocket/Webhook -- [ Nagi Server (Docker Host) ] | [ Docker Daemon ] | [ Agent Container 1, 2, ... ]服务器选择选择一家云服务商如AWS EC2, Google Cloud Compute Engine, DigitalOcean Droplet或国内的阿里云ECS、腾讯云CVM。建议选择至少1核2GB内存的配置因为需要运行Docker容器。操作系统选择一款稳定的Linux发行版如Ubuntu 22.04 LTS或Alpine Linux。关键服务Docker Engine这是运行AI代理容器的基石。Node.js环境用于运行Nagi的主服务。进程管理使用systemd或pm2来管理Nagi主进程确保其崩溃后能自动重启。反向代理可选但推荐使用nginx或Caddy作为反向代理可以方便地管理域名、SSL证书HTTPS以及为多个服务路由流量如果你在同一台服务器上还运行了其他服务。5.2 安全性加固配置令牌与密钥管理绝对不要将Slack Bot Token、Discord Token、Anthropic API Key等硬编码在代码或配置文件中。使用环境变量或专业的密钥管理服务如AWS Secrets Manager, HashiCorp Vault。在Linux服务器上可以将其写入/etc/environment或使用.env文件确保文件权限为600并由非root用户读取。在Nagi的配置文件中使用环境变量引用例如slack: botToken: ${SLACK_BOT_TOKEN} appToken: ${SLACK_APP_TOKEN}Docker容器安全非Root用户运行在Dockerfile中创建并使用非root用户来运行应用进程。资源限制在docker run时使用--memory、--cpus等参数限制单个容器的资源使用防止某个失控的代理任务拖垮整个主机。只读文件系统对于大多数代理任务容器不需要写入主机文件系统。使用--read-only标志启动容器并结合--tmpfs为需要临时文件的目录挂载内存文件系统。网络限制使用--network none或自定义的桥接网络限制容器的网络访问只允许其访问必要的服务如AI API端点。API访问控制Dashboard UI的API服务器默认3001端口不应该直接暴露在公网。应该通过反向代理nginx进行访问并配置HTTP Basic认证或OAuth等身份验证层。考虑将Dashboard的访问限制在内网或通过VPN访问。5.3 运维与监控日志收集将Nagi应用日志和Docker容器日志统一收集到像Fluentd、Loki或云服务商提供的日志服务中便于集中查询和设置告警。健康检查为Nagi主服务添加健康检查端点/health并配置进程管理器或负载均衡器定期检查。成本监控AI代理的核心成本是Claude API的调用费用。务必在Anthropic控制台设置用量预算和告警。Nagi自身应该在日志中详细记录每次会话的Token使用量和估算成本定期审查这些日志。备份定期备份Nagi的配置文件、数据库如果使用了持久化存储会话以及重要的技能代码。6. 常见问题与故障排查实录在实际部署和使用Nagi的过程中你几乎一定会遇到一些问题。下面是我在搭建和运行过程中遇到的一些典型问题及解决方法。6.1 通道连接失败问题现象Slack/Discord机器人无响应Dashboard上显示通道状态为“离线”或“错误”。排查步骤检查令牌首先确认你使用的Bot Token和App Token对于Slack是正确的且未过期。令牌泄露或失效是最常见的原因。检查权限Scopes确认你在创建应用时为机器人添加了所有必需的作用域Scopes。缺少某个权限如chat:write会导致连接成功但无法执行操作。网络与防火墙对于Slack Socket Mode确保你的服务器可以访问wss://wss-primary.slack.com。在服务器上运行curl -v https://wss-primary.slack.com/测试连通性。对于Discord它使用Gateway Intents也需要稳定的出站连接。检查服务器防火墙如ufw或云服务商的安全组规则是否放行了必要的出站连接。查看服务端日志运行Nagi时确保日志级别设置为DEBUG或INFO查看启动时连接通道的日志信息通常会有具体的错误提示。6.2 Docker容器启动失败或执行错误问题现象任务触发后一直处于“等待”或“执行中”最后失败。Dashboard日志显示容器相关错误。排查步骤Docker服务状态首先运行sudo systemctl status docker或docker info确认Docker守护进程正在运行。镜像拉取Nagi需要基础镜像来运行代理。运行docker pull nagi-base:latest或项目指定的镜像名手动拉取看是否有网络问题。资源不足运行docker stats查看容器资源使用情况。如果内存不足容器会被OOM Killer终止。考虑增加服务器内存或在docker run命令中降低内存限制。容器内日志Nagi应该将容器内的标准输出和错误输出捕获并记录到自己的日志系统。在Dashboard的“Logs”页面筛选对应任务ID的日志查看具体的错误信息。常见问题包括依赖缺失技能需要的某个Python包或系统工具在基础镜像中不存在。权限问题容器内进程试图写入只读文件系统或没有权限执行某个操作。网络问题容器内无法访问外部API如Claude API需要检查主机的网络配置和代理设置。6.3 Claude API调用超时或配额不足问题现象AI代理长时间无响应或返回认证错误、额度不足错误。排查步骤API密钥确认配置的ANTHROPIC_API_KEY环境变量有效且未过期。速率限制Anthropic API有每分钟/每天的请求次数和Token数量限制。如果短时间内触发大量任务可能会被限流。需要在代码中实现简单的退避重试机制或者错峰执行任务。模型可用性检查你是否使用了正确的模型名称如claude-3-5-sonnet-20241022并且该模型在你的API计划中是可用的。请求超时某些技能操作如网页抓取可能导致Claude的“思考”和工具调用链非常长超过默认的HTTP超时时间。需要在Nagi的HTTP客户端配置或Agent SDK配置中适当增加超时时间。6.4 技能执行不符合预期问题现象技能被触发了但结果不对或者AI理解错了意图。排查步骤利用会话日志这是最重要的调试工具。在Dashboard的“Sessions”页面找到这次执行展开AI的“思考过程”时间线。一步一步看AI是否正确解析了你的指令它计划调用哪些工具顺序对吗每次工具调用的输入是什么返回的输出又是什么是不是某个工具调用失败了或者返回了意外数据AI基于工具返回的结果做出了怎样的推理检查技能描述和参数技能的description和参数模式schema是AI理解该技能用途的关键。确保描述清晰、无歧义参数定义准确。提供更明确的上下文有时AI表现不佳是因为上下文信息不足。在Asana任务中确保任务描述清晰在Slack中可能需要在前面的消息中提供更多背景。你也可以尝试在指令中更明确地指出技能名和参数例如ai 请运行‘ai-changelog’技能查看过去3天OpenAI的更新。6.5 性能优化与成本控制随着使用频率增加你可能会关心性能和成本。容器池预热频繁创建和销毁Docker容器是有开销的。对于高性能场景可以考虑实现一个简单的“容器池”预先启动并维护几个空闲的容器任务到来时直接使用减少冷启动延迟。会话缓存对于多轮对话AI需要完整的上下文历史。如果历史很长每次都会消耗大量Token。可以考虑对历史消息进行智能摘要或选择性缓存只保留最相关的部分。设置预算告警如前所述务必在Anthropic控制台设置硬性的月度预算和告警阈值。对于非关键任务可以考虑使用更便宜的模型如claude-3-haiku。技能超时与熔断为每个技能设置执行超时时间。如果一个技能运行时间过长可能陷入死循环应主动终止它并防止短时间内重复触发该问题技能熔断机制。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2591525.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!