1. 项目概述一个拥有“灵魂”的AI助手如果你厌倦了那些只会机械回复的聊天机器人想拥有一个真正能理解你、帮你处理日常琐事、甚至有点个性的数字伙伴那么Kairo这个项目绝对值得你花时间研究。它不是一个简单的问答脚本而是一个基于Claude Agent SDK构建的、功能强大的AI智能体并以Telegram作为主要交互界面。简单来说你可以把它理解为你手机里的一个“超级管家”它不仅能和你聊天还能通过一系列“工具”帮你操作你的Gmail邮箱、管理Spotify歌单、在Notion里记笔记甚至帮你搜索网页、设置提醒。最有趣的是它的“性格”完全由一份名为SOUL.md的文档定义这意味着你可以把它塑造成任何你喜欢的角色——从严谨的私人助理到幽默的吐槽朋友。这个项目的核心价值在于它将前沿的大语言模型LLM能力与真实世界的工具连接了起来。开发者FujiwaraChoki巧妙地利用了Anthropic推出的Claude Agent SDK和MCPModel Context Protocol架构让Claude模型不仅能“思考”还能“动手”去调用外部API。对于开发者而言这是一个绝佳的、可以深入学习的AI Agent实战案例涵盖了从架构设计、上下文管理到多工具集成的完整链路。对于普通用户一旦部署成功你将获得一个7x24小时在线、能力远超普通ChatGPT的私人助手。2. 核心架构与设计哲学拆解2.1 为什么选择Claude Agent SDK MCP在构建AI Agent时一个核心挑战是如何让大语言模型安全、可靠地使用外部工具。Kairo选择了Claude Agent SDK作为基石这背后有几个关键考量。首先Claude Agent SDK提供了原生的、结构化的工具调用Tool Use能力。与通过函数调用Function Calling或ReAct提示工程来让模型“思考”使用哪个工具不同Claude的Tool Use是模型输出的一个原生类型。这意味着模型在生成回复时可以明确地“决定”并“声明”要调用哪个工具、传入什么参数。SDK则负责解析这个声明执行对应的工具函数并将结果返回给模型继续处理。这种设计使得工具调用的意图更清晰错误处理也更直接。其次MCPModel Context Protocol是连接模型与工具的“桥梁”。你可以把MCP想象成一个标准化的插件协议。在Kairo的架构中每一个功能模块如whatsapp/、gmail/、spotify/本质上都是一个独立的MCP服务器。这些服务器向Claude Agent声明自己提供了哪些工具Tools、有哪些可用的资源Resources。Claude Agent SDK则作为MCP客户端动态地发现并加载这些工具。这种解耦带来的巨大好处是可扩展性。如果你想为Kairo增加一个新功能比如控制智能家居你只需要按照MCP规范编写一个新的服务器模块并将其注册到主程序中即可无需大幅修改核心逻辑。这种模块化设计正是现代软件工程所倡导的。2.2 核心组件交互流程理解了SDK和MCP的角色后我们来看一次完整的用户交互在Kairo内部是如何流转的。假设用户向Telegram里的Kairo发送消息“帮我查一下明天北京的天气然后创建一个Notion页面记录出行计划。”消息接收与路由src/index.ts作为入口点通过node-telegram-bot-api库接收到这条Telegram消息。上下文加载conversation/模块被触发。它会基于当前聊天对话的ID从SQLite数据库中加载历史消息记录。这是实现“长对话记忆”的关键。构造提示词系统会将以下几部分内容组合发送给Claude模型系统提示System Prompt默认来自SOUL.md文件定义了Kairo的“人格”和行为准则。工具描述Tool Descriptions从所有已激活的MCP服务器天气、Notion等动态获取当前可用的工具列表及其使用说明。对话历史Conversation History从数据库加载的、经过处理的过往消息为模型提供上下文。用户当前消息User Message“帮我查一下明天北京的天气然后创建一个Notion页面记录出行计划。”模型推理与工具调用Claude模型分析请求识别出需要按顺序执行两个工具get_weather查询天气和notion_create_page创建Notion页面。它会先输出一个Tool Use请求调用get_weather。工具执行Claude Agent SDK截获这个请求找到对应的MCP工具函数可能在info/模块的天气工具中传入参数{location: “北京”, date: “明天”}并执行。执行结果例如“明天北京晴15-25°C”被返回给模型。模型继续处理Claude收到天气结果后结合最初的用户指令意识到还需要创建Notion页面。于是它可能输出第二个Tool Use请求调用notion_create_page并将天气信息作为页面内容的一部分。结果生成与回复在完成所有必要的工具调用后Claude生成最终的自然语言回复例如“已为您查询到明天北京天气晴朗气温15-25°C非常适合出行。我已在您的Notion‘旅行计划’数据库中创建了一个新页面包含了天气信息和行程建议模板。” 这个回复通过Telegram Bot API发送给用户。上下文保存整个交互过程中的用户消息、工具调用、模型回复都会被结构化地保存回SQLite数据库供下次对话使用。注意这个过程是高度并发的。Kairo需要处理来自多个用户的并发请求每个对话都有独立的上下文会话。这就要求conversation/模块的数据库操作和状态管理必须是线程安全的。2.3 对话记忆与上下文管理的精妙设计让AI记住漫长的对话历史是一个经典难题。直接无脑地拼接所有历史消息会迅速耗尽模型的上下文窗口Token限制导致成本飙升甚至无法处理。Kairo的conversation/模块提供了一套优雅的解决方案其核心是基于Token预算的自动压缩Compaction与摘要Summarization。工作流程如下Token计数与预算检查每次准备向模型发送消息时系统会计算当前会话所有历史消息包括系统提示、工具描述、过往对话的总Token数。这个上限由环境变量MAX_CONTEXT_TOKENS控制默认16000。触发压缩如果总Token数超过预算系统不会直接报错而是启动自动压缩流程。策略性遗忘压缩不是简单的“掐头去尾”。一个常见的策略是滑动窗口保留最近N轮对话的完整内容因为最近的对话通常与当前问题最相关。智能摘要对于被移出窗口的早期对话Kairo会调用模型本身或一个更小、更快的摘要模型对这些消息生成一个简短的、概括性的摘要。例如将十轮关于“规划周末聚餐”的讨论摘要成一句话“用户曾讨论本周末与朋友聚餐初步意向是周六晚上吃火锅但地点未定。”替换历史用生成的摘要替换掉那十轮原始对话再与保留的最近对话拼接。这样模型既保留了早期对话的“精髓”又极大地节省了Token占用。结构化存储所有这些消息、工具调用记录、摘要都以结构化的格式存储在SQLite中方便快速检索和更新。实操心得设置MAX_CONTEXT_TOKENS时需要权衡。设置太高如32000虽然能让模型记住更多细节但每次推理的成本会显著增加响应速度也可能变慢。设置太低如4000则可能导致对话连续性差模型容易“失忆”。对于日常助手类应用默认的16000是一个比较平衡的起点。你可以根据实际使用感受和API成本预算进行调整。3. 从零开始环境搭建与深度配置指南3.1 基础运行环境准备Kairo是一个Node.js项目对运行环境有明确要求。以下是详细的准备步骤不仅仅是运行安装脚本更要理解每一步的作用。1. 安装Node.js与pnpm项目要求Node.js版本 20.6并推荐使用pnpm作为包管理器。我强烈建议使用nvmNode Version Manager来管理Node.js版本这可以让你在不同项目间轻松切换。# 安装nvm如果尚未安装 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # 重启终端或运行 source ~/.bashrc (或 ~/.zshrc) # 安装并启用所需的Node.js版本 nvm install 20.6.0 nvm use 20.6.0 # 验证安装 node --version # 应输出 v20.6.0 或更高 npm --version # 全局安装pnpm npm install -g pnpm pnpm --version # 应输出 9.0.0为什么是Node 20.6这个版本引入了对.env文件的原生支持通过--env-file标志虽然Kairo可能使用dotenv库但保持环境统一有助于避免兼容性问题。此外更新的Node版本在ES模块支持、性能和安全补丁上更有优势。2. 获取项目代码使用git clone拉取代码是最直接的方式。建议在拉取后立即检查最新的分支或标签因为主分支可能处于活跃开发状态。git clone https://github.com/fujiwarachoki/kairo.git cd kairo # 可选查看最近发布的稳定版本 git tag -l | sort -V | tail -5 # 可选切换到某个稳定版本例如 v1.2.0 # git checkout v1.2.03.2 两种部署方式详解脚本安装 vs. 手动配置项目提供了./install.sh快速安装脚本但对于想深入了解或进行定制化部署的开发者手动配置是必经之路。我们来剖析两者。方式一使用安装脚本推荐新手运行./install.sh脚本会依次执行检查系统依赖如git, node, pnpm。运行pnpm install安装所有Node.js依赖包。复制.env.example为.env。以交互式问答的方式引导你填写最重要的环境变量如Telegram Bot Token。询问你是否要启用并配置其他集成功能如Gmail、Spotify。完成后尝试启动Bot。踩坑提示安装脚本虽然方便但在某些Linux发行版或macOS上可能会因权限问题执行失败。如果遇到Permission denied可以尝试chmod x install.sh给它添加执行权限。另外脚本的交互式配置可能无法覆盖所有高级选项最终你还是需要手动编辑.env文件。方式二手动配置推荐进阶用户手动配置让你能完全掌控每一步。# 1. 安装依赖 pnpm install # 这个过程会读取package.json安装所有dependencies和devDependencies。 # 如果网络不佳可以尝试设置国内镜像pnpm config set registry https://registry.npmmirror.com # 2. 配置环境变量 cp .env.example .env # 使用你喜欢的编辑器如vim, nano, VSCode打开 .env 文件 code .env此时你会看到一个包含大量配置项的.env.example文件被复制为.env。接下来就是最关键的环节获取并填写各个服务的API密钥。3.3 核心与扩展服务API密钥获取全攻略1. Telegram Bot Token必需最核心没有这个项目根本无法运行。步骤在Telegram中搜索BotFather发送/newbot按提示操作。最终你会获得一个形如1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ的令牌。填写在.env中找到BOT_TOKEN将令牌填入。高级配置BOT_NAME给你的Bot起个显示名默认是Kairo。ENABLE_GROUPS设置为true后Bot才能在群聊中响应。请注意在群聊中Bot默认只会回复提及它BotName的消息这是为了避免在活跃群组中刷屏。如果需要改变此行为需要修改src/index.ts中的消息过滤逻辑。2. Anthropic Claude API Key必需驱动大脑Kairo的核心是Claude模型你需要Anthropic的API密钥。步骤访问Anthropic官网注册账号并进入Console在API Keys部分创建新密钥。填写找到ANTHROPIC_API_KEY并填入。成本注意Claude API是收费服务具体价格需查阅Anthropic官网。Kairo的对话记忆和工具调用都会产生Token消耗请关注使用量。3. 扩展集成配置可选按需启用以下是一些常用集成的配置详解Exa AI (Web搜索)作用让Kairo能进行实时网页搜索。获取注册Exa AI原名Exa并创建API Key。填写EXA_API_KEY心得Exa的搜索质量很高特别是对近期内容的索引。对于需要最新信息的查询如“今天科技圈有什么大新闻”非常有用。Notion作用读写Notion页面和数据库。获取在Notion中进入 My Integrations 创建一个新的内部集成。为集成命名如Kairo Bot并关联到你希望Bot访问的工作区。复制生成的Internal Integration Token以secret_开头。关键一步在你希望Bot管理的Notion页面或数据库的右上角点击...-Add connections搜索并添加你刚刚创建的Kairo Bot集成。填写NOTION_TOKEN填入刚才复制的Token。权限Bot只能访问你明确与之“连接”的页面和数据库安全性较好。Spotify作用控制播放、搜索音乐、管理歌单。获取登录 Spotify Developer Dashboard 。创建一个新应用设置名称和描述如Kairo Music Controller。在应用设置中点击Edit Settings在Redirect URIs一栏添加http://localhost:8888/callback这是Kairo项目默认的OAuth回调地址如果修改了代码中的端口此处需同步。保存后你将看到Client ID和Client Secret。填写SPOTIFY_CLIENT_ID你的Client ID SPOTIFY_CLIENT_SECRET你的Client Secret首次授权启动Bot后当你第一次使用Spotify相关指令时Kairo会回复一个授权链接。你需要在浏览器中访问此链接登录你的Spotify账号并授权给这个应用。授权成功后刷新令牌Refresh Token会被自动保存后续无需重复操作。Gmail作用读取和发送邮件。获取这是配置最复杂的一环涉及Google Cloud Platform项目创建、OAuth 2.0凭据配置和API启用。强烈建议参考项目源码中gmail/目录下的详细说明或README。通常需要在GCP创建项目启用Gmail API。配置OAuth 2.0同意屏幕。创建OAuth 2.0客户端ID类型为“桌面应用”。下载包含client_id,client_secret等的JSON文件并将其内容转换为环境变量。安全警告授予Bot Gmail权限意味着它可以访问你的邮件请确保只在可信的环境部署并妥善保管.env文件。3.4 启动、验证与守护进程完成.env配置后就可以启动Bot了。# 开发模式启动带TS编译和热更新需看项目配置 pnpm start # 或直接运行编译后的JS如果项目有build步骤 pnpm build pnpm run prod启动后控制台应显示成功连接Telegram和加载MCP工具的信息。在Telegram中找到你的Bot发送/start或/help你应该能收到回复。让Bot在后台稳定运行 对于生产环境我们不会直接在前台运行pnpm start。推荐使用进程管理工具如PM2。# 全局安装PM2 pnpm add -g pm2 # 使用PM2启动Kairo并命名为kairo-bot # 假设你的启动命令定义在package.json的scripts里名为start:prod pm2 start pnpm --name kairo-bot -- start:prod # 或者直接指定运行编译后的入口文件 # pm2 start dist/index.js --name kairo-bot # 设置开机自启根据系统生成对应配置 pm2 startup # 保存当前进程列表 pm2 save # 常用PM2命令 pm2 status # 查看状态 pm2 logs kairo-bot # 查看日志 pm2 restart kairo-bot # 重启 pm2 stop kairo-bot # 停止 pm2 delete kairo-bot # 删除使用PM2可以确保Bot在服务器重启后自动恢复并能集中查看日志管理异常崩溃重启是部署的标配。4. 核心模块深度解析与二次开发4.1 灵魂文件定制你的AI人格SOUL.md是Kairo项目的精髓所在。它不是一个配置文件而是一份用自然语言写给Claude模型的“角色设定说明书”。系统启动时会将这个文件的内容作为系统提示词System Prompt加载从根本上塑造Bot的言行。默认SOUL.md剖析 打开文件你可能会看到类似这样的内容# Kairo的灵魂 你是一个乐于助人、知识渊博且高效的AI助手。你的名字是Kairo。你的核心使命是帮助用户处理信息、完成任务、提升效率同时保持对话的自然与友好。 ## 沟通风格 - 使用清晰、简洁的语言。 - 在提供信息时尽量结构化如使用列表、要点。 - 可以带有轻微的幽默感但避免轻浮。 - 当用户提出复杂或多步骤请求时主动拆解并确认步骤。 ## 能力与边界 - 你可以使用连接的工具如Gmail、Notion来帮助用户。 - 你无法访问用户未明确授权给你的信息。 - 如果某项请求超出你的能力范围或涉及安全风险礼貌地解释原因。 - ...如何深度定制改变语气与性格你可以把它重写成一个“严谨的学术顾问”、“热血的中二伙伴”或“毒舌的吐槽役”。关键在于在提示词中详细描述这些特质。例如要塑造一个“科幻风格助手”可以写“你是一个来自22世纪的赛博助手代号‘Kairo’。你习惯用‘指令已接收’、‘正在分析协议’、‘执行完毕’等措辞。你对人类文化充满好奇常以未来视角评论当前科技。”定义特殊能力与限制在SOUL.md中明确告诉模型它能做什么、不能做什么。例如“你被允许在用户请求时使用幽默的比喻来解释复杂概念。” 或者 “你绝不可以生成或讨论任何涉及暴力、仇恨的虚构内容。”设定响应格式你可以要求模型在特定情况下使用固定格式。例如“当为用户总结文章时请按照以下格式回复【标题】、【核心观点】、【关键论据】、【我的疑问】。”环境变量覆盖如果你觉得维护一个.md文件不方便或者想动态切换人格可以直接使用SYSTEM_PROMPT环境变量。在.env中设置SYSTEM_PROMPT其内容会完全替代SOUL.md。你可以将很长的提示词压缩成一行字符串注意换行符\n。实操心得修改SOUL.md后需要重启Bot才能生效。人格设定对Bot行为影响巨大。一个常见的问题是“人格泄露”即当用户要求Bot扮演另一个角色时它可能会与SOUL.md中的基础人格产生冲突。你可以在SOUL.md中加入指令来处理这种情况例如“如果用户要求你扮演特定角色你可以暂时进入角色模式但你的核心帮助性和安全性准则不变。”4.2 工具开发为Kairo添加新能力Kairo的强大之处在于其基于MCP的可扩展架构。假设我们想为它添加一个“查询加密货币价格”的新功能。步骤1创建新的MCP服务器模块在src/目录下创建一个新文件夹例如crypto/。mkdir src/crypto cd src/crypto步骤2实现工具逻辑创建一个index.ts文件实现具体的工具函数。这里我们使用一个假想的免费API。// src/crypto/index.ts import { Server } from modelcontextprotocol/sdk/server/index.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; import { CallToolRequestSchema, ListToolsRequestSchema, } from modelcontextprotocol/sdk/types.js; import axios from axios; // 1. 定义工具列表 const tools [ { name: get_crypto_price, description: 获取指定加密货币的当前价格以美元计。, inputSchema: { type: object, properties: { symbol: { type: string, description: 加密货币符号例如BTC, ETH, SOL, }, }, required: [symbol], }, }, ]; // 2. 创建MCP服务器实例 const server new Server( { name: crypto-tools, version: 1.0.0, }, { capabilities: { tools: {}, }, } ); // 3. 处理工具列表请求 server.setRequestHandler(ListToolsRequestSchema, async () { return { tools, }; }); // 4. 处理工具调用请求 server.setRequestHandler(CallToolRequestSchema, async (request) { if (request.params.name get_crypto_price) { const { symbol } request.params.arguments as { symbol: string }; const upperSymbol symbol.toUpperCase(); try { // 这里使用CoinGecko API示例需注册获取免费API Key const response await axios.get( https://api.coingecko.com/api/v3/simple/price?idsbitcoin,ethereum,solanavs_currenciesusd ); // 简化映射实际应更完善 const coinMap: { [key: string]: string } { BTC: bitcoin, ETH: ethereum, SOL: solana, }; const coinId coinMap[upperSymbol]; if (!coinId || !response.data[coinId]) { return { content: [ { type: text, text: 未找到加密货币 ${symbol} 的价格信息。请检查符号是否正确。, }, ], }; } const price response.data[coinId].usd; return { content: [ { type: text, text: 加密货币 ${symbol} 的当前价格约为 $${price} USD。, }, ], }; } catch (error) { console.error(获取加密货币价格失败:, error); return { content: [ { type: text, text: 查询 ${symbol} 价格时出现网络或API错误。, }, ], }; } } throw new Error(未知工具: ${request.params.name}); }); // 5. 启动服务器通过stdio传输 async function main() { const transport new StdioServerTransport(); await server.connect(transport); console.error(Crypto MCP server running on stdio); } main().catch((error) { console.error(Server error:, error); process.exit(1); });步骤3在主程序中注册新模块你需要修改src/index.ts或项目的主启动逻辑将新的crypto MCP服务器启动并注册到Claude Agent中。具体方式需要参考项目中其他模块如src/spotify/是如何被集成的。通常这涉及到动态生成子进程或连接到服务器。步骤4更新工具声明确保Claude Agent能感知到这个新工具。这通常在构造系统提示词时动态地从所有已连接的MCP服务器获取工具列表来实现。你新增的服务器在启动后会自动提供get_crypto_price工具的描述。步骤5测试重启你的Kairo Bot然后尝试在Telegram中发送“Kairo现在比特币价格多少” 理论上Claude模型会识别出这个请求需要调用get_crypto_price工具并传入symbol: “BTC”。开发注意事项错误处理工具函数中必须有完善的错误处理try-catch并向模型返回友好的错误信息而不是直接抛出异常导致整个会话中断。速率限制调用外部API时务必遵守其速率限制必要时在代码中添加延迟或使用令牌桶算法。安全性任何接受用户输入并用于API调用的参数都要进行严格的验证和清理防止注入攻击。4.3 对话记忆系统的内部机制与调优conversation/模块是Kairo的“大脑皮层”负责存储和提取记忆。其核心是SQLite数据库表结构可能类似于字段名类型说明idINTEGER PRIMARY KEY自增主键chat_idTEXT唯一标识一个对话如Telegram Chat IDroleTEXT‘user’, ‘assistant’, ‘tool’, ‘system’contentTEXT消息或工具调用的具体内容tokensINTEGER该条内容估算的Token数created_atDATETIME创建时间戳is_compactedBOOLEAN是否已被摘要压缩自动压缩策略的调优点压缩触发阈值MAX_CONTEXT_TOKENS是硬性上限。你还可以设置一个“软阈值”比如当Token数达到上限的90%时就开始尝试轻度压缩如只摘要最老的一条消息避免每次都在极限边缘操作。摘要质量摘要的生成质量直接影响模型对早期对话的理解。你可以调整用于摘要的提示词Prompt例如要求摘要必须包含“用户的核心意图”、“达成的结论”和“悬而未决的问题”。在Kairo的代码中可能有一个专门的函数generateSummary(messages)来实现这一点。保留完整对话的轮数在滑动窗口策略中决定保留最近多少轮完整对话是一个平衡艺术。保留太多如20轮会占用大量Token保留太少如3轮可能导致上下文断裂。这个参数可能在代码中是硬编码的你可以根据自己对话的平均长度找到合适的值并修改它。一个高级技巧基于重要性的记忆筛选除了简单的“最近优先”还可以尝试更复杂的策略。例如在保存每条消息时让模型为其打上一个“重要性分数”1-5分。在需要压缩时优先摘要掉低分例如日常寒暄的对话而保留高分例如用户设定的重要偏好、关键任务指令的对话即使它们发生得比较早。这需要更复杂的逻辑但能显著提升对话的连贯性和智能感。5. 实战应用场景与高级技巧5.1 打造你的个性化工作流Kairo的真正威力在于将多个工具串联起来形成自动化工作流。以下是一些灵感信息收集与整理你可以对Kairo说“搜索最近三天关于‘AI Agent架构’的5篇高质量英文文章把它们的标题、链接和核心摘要整理成一个新的Notion数据库页面。” Kairo会调用Exa搜索工具获取文章然后调用Notion工具创建页面并填充内容。邮件智能处理“查一下我收件箱里所有来自‘GitHub’且标题包含‘security alert’的未读邮件把最重要的3封的摘要发到Telegram给我并把它们标记为已读。” Kairo会使用Gmail工具搜索和读取邮件进行内容摘要然后通过Telegram回复你并更新邮件状态。娱乐与创作“根据我今天听的Spotify歌单的风格生成一个‘专注编程’的新歌单推荐并把歌单链接和理由发给我。” Kairo可以分析你的收听历史通过Spotify工具利用Claude的创作能力生成推荐理由并可能调用Spotify工具创建或推荐歌单。5.2 性能优化与成本控制1. 响应速度优化工具调用超时为每个MCP工具调用设置合理的超时时间如10秒。如果某个外部API如天气服务响应慢不应让用户一直等待。在工具实现中加入超时逻辑超时后向模型返回“工具暂时无响应”的信息让模型决定是重试、跳过还是告知用户。异步处理长任务对于耗时较长的任务如处理一个非常大的Notion数据库不要让Telegram同步等待。可以让Bot先回复“已开始处理完成后通知您”然后在后台异步执行任务完成后再通过Telegram主动推送结果。这需要更复杂的任务队列设计。缓存常用数据对于一些不常变化的数据如城市列表、固定指令的帮助信息可以在内存或Redis中进行缓存避免重复计算或查询。2. API成本控制监控Token使用密切关注Anthropic API的Token消耗。在conversation/模块的保存日志中可以记录每条消息的估算Token数。定期分析看看是哪些类型的对话或工具调用最“烧钱”。设置对话预算可以为每个用户或每个对话设置每日Token预算。当接近预算时让Bot提醒用户或者切换到更精简的回复模式例如让模型在生成回复时“尽可能简洁”。使用更便宜的模型处理摘要上下文压缩时的摘要生成不一定非要使用昂贵的Claude Opus模型。如果项目支持可以配置为使用更小、更快的模型如Claude Haiku来生成摘要这能大幅降低成本。精细化工具权限不是所有用户都需要所有工具。可以在.env或数据库配置中为不同用户或群组启用/禁用某些高成本或高风险的集成如Gmail、Web搜索。5.3 安全与隐私加固将个人数据邮件、笔记交给AI处理安全是重中之重。环境变量管理.env文件包含所有API密钥绝不能提交到Git仓库。确保.gitignore文件中包含.env。在生产环境中使用安全的密钥管理服务如Vault、AWS Secrets Manager或服务器环境变量注入。数据库加密SQLite数据库文件可能位于项目目录下存储了所有对话历史。建议对数据库文件进行加密或者将敏感信息如邮件内容片段在存储前进行加密。用户隔离确保对话记忆严格按chat_id隔离。一个用户绝对无法访问另一个用户的对话历史。在实现任何“共享”或“广播”功能时要格外小心。输入验证与过滤对所有从用户端传入、最终用于工具调用的参数进行严格的验证和清理防止SQL注入、命令注入或跨站脚本XSS攻击。例如在调用Notion创建页面时对用户输入的页面标题进行无害化处理。审计日志记录所有工具调用的关键操作如“用户A通过Bot发送了一封邮件给B”便于事后审计和排查问题。6. 常见问题与故障排查实录在实际部署和运行Kairo的过程中你几乎一定会遇到下面这些问题。这里是我踩过坑后总结的排查思路和解决方法。6.1 启动与连接问题问题1启动时报错Cannot find module ‘modelcontextprotocol/sdk/...’可能原因依赖未正确安装或者Node.js版本不兼容。排查步骤删除node_modules文件夹和pnpm-lock.yaml文件rm -rf node_modules pnpm-lock.yaml。清除pnpm缓存pnpm store prune。重新安装依赖pnpm install。确认Node.js版本node --version确保是20.6.0或更高。问题2Bot在Telegram无响应但进程运行正常可能原因ABOT_TOKEN填写错误。检查在.env中确认Token格式正确没有多余空格。可以尝试在浏览器中访问https://api.telegram.org/botYOUR_BOT_TOKEN/getMe如果返回{ok:false,error_code:401,description:Unauthorized}说明Token无效。可能原因B网络问题服务器无法连接Telegram API。检查在服务器上运行curl https://api.telegram.org看是否能通。如果使用代理需要在Node.js中配置代理环境变量如HTTP_PROXY/HTTPS_PROXY。可能原因CBot未启动或设置了隐私模式。检查在Telegram中通过BotFather发送/mybots选择你的Bot进入Bot Settings-Group Privacy确保是Disabled状态这样Bot才能在群聊中被。同时确认你已经向Bot发送过/start命令来初始化聊天。6.2 工具集成故障问题3Notion集成报错 “Notion API error: unauthorized”可能原因ANOTION_TOKEN无效或已过期。解决在Notion集成页面重新生成Token并更新.env。可能原因B集成未与目标页面/数据库连接。解决这是最常见的原因。你必须在你希望Bot访问的每个Notion页面或数据库的右上角点击...-Add connections然后选择你为Kairo创建的集成。只有连接后集成才有权限操作该页面。可能原因C页面或数据库的ID错误。排查当你在Notion中复制页面链接时URL中会包含一个长ID。确保在向Bot发出指令时使用的ID是正确的。Notion的页面ID和数据库ID格式不同不要混用。问题4Spotify集成授权失败回调地址报错可能原因在Spotify开发者后台设置的Redirect URI与Kairo代码中实际使用的回调地址不匹配。解决检查Kairo项目中Spotify OAuth模块的代码通常在src/spotify/auth.ts或类似文件中找到redirect_uri的值默认可能是http://localhost:8888/callback。登录Spotify Developer Dashboard进入你的应用设置在Redirect URIs列表中精确地添加这个URI。确保没有尾随斜杠或协议、端口不匹配。http://localhost:8888/callback和http://localhost:8888/callback/被认为是两个不同的URI。问题5Gmail集成配置复杂OAuth流程出错难点Gmail API的OAuth 2.0配置是最复杂的。标准流程核对清单Google Cloud项目已创建且已关联结算账户即使使用免费额度。Gmail API已在“库”中启用。OAuth同意屏幕已配置为“外部”或“内部”如果是Workspace并添加了测试用户你自己的邮箱。凭据已创建“OAuth 2.0 客户端ID”应用类型选择“桌面应用”。环境变量已将下载的JSON文件中的client_id、client_secret、redirect_uris等信息正确转换为.env文件中的变量如GMAIL_CLIENT_ID,GMAIL_CLIENT_SECRET,GMAIL_REDIRECT_URI。首次授权启动Bot后使用Gmail相关指令点击Bot回复的授权链接完成授权流程。授权后产生的refresh_token需要被安全地保存项目代码应已处理。6.3 模型与对话问题问题6Bot回复慢尤其在进行网页搜索或复杂操作时原因Claude模型推理需要时间加上工具调用如网络请求的延迟。优化设置超时在代码中为Claude API调用设置一个总超时例如30秒超时后向用户返回“处理超时请稍后再试或简化您的请求”。使用流式响应如果node-telegram-bot-api和Claude SDK支持可以实现流式响应让用户看到Bot是“正在输入”状态并逐步收到回复体验更好。异步处理如前所述将长任务丢到后台队列。问题7Bot“忘记”了很早之前的对话内容原因这是对话上下文压缩导致的。为了节省Token早期的对话被摘要替代了。控制调高MAX_CONTEXT_TOKENS环境变量例如到32000但这会增加每次API调用的成本。修改conversation/模块中的压缩策略增加“完整保留”的对话轮数。对于特别重要的信息可以教导用户使用“记住这个[信息]”这样的指令你可以在代码中实现一个特殊处理将这类信息存入一个不会被压缩的“长期记忆”区域。问题8Bot有时会拒绝执行合理的任务或者说“我不能做这个”原因这很可能来自SOUL.md中定义的人格或安全准则或者Claude模型自身的安全策略被触发。调试检查SOUL.md中是否有过于严格的限制性描述。查看日志中Claude API返回的完整响应。有时模型会提供一个stop_reason为max_tokens或content_filter并附带更多信息。尝试用更清晰、更具体的方式重新表述你的请求。模糊的请求更容易被模型的安全层拦截。6.4 部署与运维问题问题9使用PM2守护进程后日志文件巨大解决PM2默认会将所有日志输出到~/.pm2/logs/目录。你可以配置日志轮转。# 安装PM2日志管理模块 pm2 install pm2-logrotate # 配置例如每个文件最大10M保留30个备份 pm2 set pm2-logrotate:max_size 10M pm2 set pm2-logrotate:retain 30 pm2 set pm2-logrotate:compress true # 压缩旧日志问题10如何更新Kairo到最新版本步骤# 1. 停止当前进程 pm2 stop kairo-bot # 2. 拉取最新代码注意可能会覆盖你的本地修改如自定义的SOUL.md git pull origin main # 3. 更新依赖 pnpm install # 4. 如果有新的环境变量更新.env文件 # 5. 重新构建如果项目有TypeScript编译 pnpm build # 6. 重启 pm2 restart kairo-bot重要提示在更新前最好备份你的.env文件和数据库文件如果有独立的SQLite文件。