手写一个AI代码审查员:Claude Agent SDK + MCP 深度实战(TaoToken 统一 Key 接入版)
1. 为什么我要自己写一个 AI 代码审查员团队里代码评审经常卡在同一个环节PR 提上来谁有空谁看看的人状态好坏直接决定漏掉多少问题。空指针、资源没关、SQL 拼接这些老毛病靠人眼盯久了必然疲劳。我试过用纯 Prompt 调模型把 diff 贴进去让它找问题结果每次都要自己拼上下文、自己解析返回、自己判断哪条建议能落地写到最后发现我维护的是一堆胶水代码不是审查能力。后来我把思路换成 Claude Agent SDK 的 Agentic Loop我不再告诉模型你看到这段代码后返回什么而是给它一个目标——审查这个文件找出会导致崩溃或安全风险的问题并给出修复建议。它自己决定先 Read 哪个文件、要不要 Grep 搜索调用方、要不要 Edit 验证。MCP 则负责把手伸到代码库之外比如查工单系统、查数据库字段定义。模型接入这一层我用 TaoToken 的统一 Key 和 API 通道一个 Key 覆盖对话与 Agent 调用省掉多套凭证来回切换的麻烦。这篇就按能跑起来的标准走先给可复制的 settings.json 和 config.toml 骨架再注册 MCP server最后提交一段含缺陷的 diff看 Agent 是否按规则输出问题定位和修复建议。适合已经会写 Python、想把手动 Review 变成自动流水线的后端或平台同学。2. TaoToken 前置统一 Key 与接入通道在写 Agent 之前先把模型通道固定下来。Claude Agent SDK 默认读环境变量里的凭证我们把它指向 TaoToken 的 API 地址即可。TaoToken 在这里的角色是统一入口对话、Agent、后续的 Coding Plan 共用一套 Key不用为每个工具单独申请。你需要准备两样东西一个 API Key以及确认 base URL 指向https://taotoken.net/api。Key 在控制台的 API Keys 页面创建建议按项目命名方便后面轮换。注意Key 只放在本地.env或 CI 的 secrets 里不要提交进仓库。Agent 有 Edit 和 Bash 权限凭证泄露的后果比普通脚本大得多。创建 Key 的入口在这里API Keys 管理。如果你还没决定用哪个模型跑审查可以先去模型对话里手动贴一段代码试试效果确认输出风格符合预期再写进 Agent。3. 可复制配置settings.json 与 config.toml 骨架Agent SDK 的配置分两层一层是 SDK 运行参数模型、工具白名单、轮次上限一层是 MCP server 注册。我把它们拆成两个文件settings.json 管 Agent 行为config.toml 管 MCP 与项目路径避免所有东西堆在一个 Python 文件里。3.1 settings.jsonAgent 行为骨架{ model: claude-sonnet-4-6, max_turns: 8, permission_mode: acceptEdits, allowed_tools: [Read, Glob, Grep, Edit], system_prompt: 你是资深 Python 代码审查专家。只输出 JSON 格式结果不做无关修改。, env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: ${TAOTOKEN_API_KEY} } }这里几个参数值得说明。max_turns限制 Agent 最多交互 8 轮防止它在某个文件上反复读改停不下来。permission_mode设为acceptEdits表示文件编辑自动批准但 Bash 不在白名单里审查阶段不需要执行命令。allowed_tools只给读和改不给执行这是审查 Agent 的安全底线。3.2 config.tomlMCP 与项目路径[project] root ./my_project include [**/*.py] exclude [.venv, tests, __pycache__] [mcp.github] command npx args [-y, modelcontextprotocol/server-github] env { GITHUB_PERSONAL_ACCESS_TOKEN ${GITHUB_TOKEN} } [mcp.review_tools] command python args [review_mcp_server.py]config.toml里我把 MCP server 分成两类一类是现成的 GitHub server用来在发现问题后创建 Issue一类是自定义的review_tools后面会写它。项目路径和文件过滤规则也放这里Agent 启动时读一次不用每次改代码。3.3 读取配置的 Python 骨架import json import os import tomllib from pathlib import Path from claude_agent_sdk import ClaudeAgentOptions def load_settings(path: str settings.json) - dict: raw Path(path).read_text(encodingutf-8) raw raw.replace(${TAOTOKEN_API_KEY}, os.environ.get(TAOTOKEN_API_KEY, )) return json.loads(raw) def load_config(path: str config.toml) - dict: with open(path, rb) as f: return tomllib.load(f) def build_options(settings: dict, config: dict) - ClaudeAgentOptions: mcp_servers {} for name, spec in config.get(mcp, {}).items(): mcp_servers[name] { command: spec[command], args: spec[args], env: spec.get(env, {}), } return ClaudeAgentOptions( modelsettings[model], max_turnssettings[max_turns], permission_modesettings[permission_mode], allowed_toolssettings[allowed_tools], system_promptsettings[system_prompt], mcp_serversmcp_servers, )这段代码把两个配置文件合成 SDK 需要的ClaudeAgentOptions。注意env里的占位符替换实际运行时ANTHROPIC_BASE_URL会指向 TaoTokenSDK 发出的请求就走统一通道了。4. MCP server 注册与自定义审查工具MCP 的价值在于让 Agent 能调用代码库之外的能力。审查场景里最实用的两个查工单系统确认某个改动是否已有记录查数据库确认字段是否可空。下面写一个最小可用的自定义 MCP server。4.1 自定义 review_mcp_server.pyfrom mcp.server import Server import requests server Server(review-tools) server.tool() async def query_ticket(keyword: str) - dict: 按关键词查询工单系统确认改动是否已有记录 resp requests.get( https://ticket.internal/api/search, params{q: keyword}, headers{Authorization: Bearer internal-token}, timeout10, ) return resp.json() server.tool() async def get_column_meta(table: str, column: str) - dict: 查询数据库字段元信息判断是否允许为空 resp requests.get( fhttps://meta.internal/api/columns/{table}/{column}, timeout10, ) return resp.json() if __name__ __main__: server.run()两个工具都很薄但作用明确query_ticket让 Agent 在报问题前先看有没有已知工单避免重复告警get_column_meta让它在判断空指针风险时有依据而不是凭猜测。4.2 注册到 Agent前面config.toml里已经写了[mcp.review_tools]build_options会自动把它塞进mcp_servers。启动后 Agent 的工具列表里会多出query_ticket和get_column_meta它会在需要时自己调用。提示MCP server 的command和args要写绝对路径或确保在 PATH 里否则 Agent 启动时会报找不到命令。我踩过一次坑python在虚拟环境里没激活结果 server 起不来Agent 静默降级成只用内置工具。5. 端到端验证提交含缺陷的 diff配置齐了现在做一次真实验证。准备一个故意埋了缺陷的文件让 Agent 审查检查它是否按规则输出问题定位和修复建议。5.1 缺陷样本# order_service.py def get_order_total(order_id): order db.query(fSELECT * FROM orders WHERE id {order_id}) items order[items] total 0 for item in items: total item[price] * item[qty] return total / len(items) def apply_discount(user, amount): if user[vip]: return amount * 0.8 return amount这段代码有三个明显问题SQL 字符串拼接存在注入风险items为空时除零user为 None 时取vip会抛异常。5.2 审查入口脚本import asyncio import json from claude_agent_sdk import query, AssistantMessage, ResultMessage from config_loader import load_settings, load_config, build_options REVIEW_PROMPT 审查 order_service.py按以下标准逐项检查 1. 安全漏洞SQL 注入、硬编码密钥 2. 空指针/None 引用 3. 资源泄露 4. 错误处理 输出 JSON { file: order_service.py, issues: [ {severity: critical|high|medium|low, line_range: 10-15, category: 安全漏洞|空指针|资源泄露|错误处理, description: 问题描述, fix_suggestion: 修复建议} ], summary: 整体评价 } async def main(): settings load_settings() config load_config() options build_options(settings, config) async for message in query(promptREVIEW_PROMPT, optionsoptions): if isinstance(message, AssistantMessage): for block in message.content: if hasattr(block, text): try: result json.loads(block.text) print(json.dumps(result, ensure_asciiFalse, indent2)) except json.JSONDecodeError: print(block.text) elif isinstance(message, ResultMessage): print(f[完成] {message.subtype}) asyncio.run(main())5.3 预期输出与检查点运行后Agent 应该先 Read 文件然后输出类似这样的结构{ file: order_service.py, issues: [ { severity: critical, line_range: 2-2, category: 安全漏洞, description: SQL 语句使用 f-string 拼接 order_id存在注入风险, fix_suggestion: 改用参数化查询db.query(SELECT * FROM orders WHERE id %s, (order_id,)) }, { severity: high, line_range: 7-7, category: 空指针, description: items 为空列表时 len(items) 为 0除法会抛 ZeroDivisionError, fix_suggestion: 在循环前加 if not items: return 0 } ], summary: 存在一处严重注入风险和一处除零风险建议优先修复 }检查点有三个问题定位是否精确到行号修复建议是否可直接落地severity 分级是否合理。如果 Agent 只输出泛泛的建议检查输入说明 system_prompt 约束不够需要把输出格式写得更死。6. 本篇常见错排查6.1 报错thinking.type.enabled is not supported这是 SDK 版本过旧导致的。Agent SDK 在较新版本才支持部分模型的 thinking 配置升级即可pip install --upgrade claude-agent-sdk升级后确认版本号在 0.2.111 以上再重跑审查脚本。6.2 Agent 不调用 MCP 工具先确认config.toml里的command能在当前 shell 直接执行。如果python review_mcp_server.py手动跑报 ModuleNotFoundErrorAgent 那边也会静默失败。另一个原因是allowed_tools没包含 MCP 工具名虽然多数情况下 SDK 会自动合并但显式加上更稳。6.3 输出不是合法 JSON模型有时会在 JSON 前后加解释文字。两个办法一是把system_prompt改成只输出 JSON不要任何前后缀二是在解析失败时用正则提取第一个{到最后一个}之间的内容再解析。我倾向后者容错更好。6.4 审查轮次超限max_turns设太小Agent 读到一半就被截断。审查单文件建议 8 轮审查整个项目建议拆成多文件循环每个文件独立跑一次而不是让一个 Agent 从头读到尾。7. 把审查接进日常流程单次跑通只是开始。真正省时间的是把它接进 PR 流程每次提交触发一次审查报告直接贴到评论区。这一步用 GitHub Actions 就能做把前面的脚本包成命令在 workflow 里调用凭证从 secrets 注入。如果你后面想让 Agent 承担更多编码任务比如自动修复加跑测试可以了解 Coding Plan它和本篇的 Key 是同一套不用重新配置通道。接入细节和参数说明在接入文档里遇到 SDK 版本或 MCP 注册问题可以先翻那里。最后留一个我实际用下来的习惯审查 Agent 的allowed_tools永远不要给 Bash修复 Agent 才给而且修复 Agent 跑在容器里。审查只读修复才写这条边界守住自动化才敢放心开。

相关新闻

前端测试自动化:用 Claude Skills 构建高质量测试体系,告别 Bug 烦恼

前端测试自动化:用 Claude Skills 构建高质量测试体系,告别 Bug 烦恼

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 12:19:02 阅读更多 →
老胡的周刊(第177期):用 TaoToken 统一 Key 打通 Cline 与 CC Switch 配置

老胡的周刊(第177期):用 TaoToken 统一 Key 打通 Cline 与 CC Switch 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 11:23:25 阅读更多 →
为编码代理引入 MongoDB 代理技能和插件:TaoToken 统一 Key 接入 Claude Code 的 config.toml 骨架

为编码代理引入 MongoDB 代理技能和插件:TaoToken 统一 Key 接入 Claude Code 的 config.toml 骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 11:24:08 阅读更多 →

最新新闻

Strands Agents Harness SDK:从原型到生产级Agent开发实战

Strands Agents Harness SDK:从原型到生产级Agent开发实战

Agent 开发这件事,很多人第一次接触时都会有一种"我是不是把它想复杂了"的错觉。你打开一个主流框架的文档,跟着写一个 ReAct 循环,跑通了,感觉挺好;然后你想加个工具调用、加个多轮记忆、加个流式输出、加个…

2026/10/1 12:51:58 阅读更多 →
音乐流行趋势预测:大数据与机器学习的工程实战

音乐流行趋势预测:大数据与机器学习的工程实战

帮一家音乐平台做流行趋势预测项目的经历,到现在我依然觉得是这几年最有价值的一次实战。目标听起来很简单:在歌曲发布后的前两周内,判断它能不能冲进热歌榜前100,顺便预测上榜后的热度走势。但真跑起来我才发现,这个任…

2026/10/1 12:51:58 阅读更多 →
UML用例图怎么画?参与者、include/extend与图书管理系统实战

UML用例图怎么画?参与者、include/extend与图书管理系统实战

带过几届做课程设计的学生之后,我发现一个相当稳定的规律:用例图画得最花哨的那组,需求文档往往写得最烂;而真正把系统想明白了的那组,用例图看起来反而朴素得有点丑。用例图这个东西门槛极低,画图工具里拖…

2026/10/1 12:51:58 阅读更多 →
两级冲击时间控制制导律的Matlab仿真实现与调参解析

两级冲击时间控制制导律的Matlab仿真实现与调参解析

做协同制导仿真的同学,看到“冲击时间控制”这个词应该都知道分量。简单说就是让多枚导弹在同一个时刻命中目标——这在饱和攻击、时间协同这类场景里是硬需求,而对单枚导弹而言,就是要让它的实际飞行时间精确收敛到一个预先设定的期望冲击时…

2026/10/1 12:51:58 阅读更多 →
16组实验复现判定模型失败:rerank配合小模型的边界与取舍

16组实验复现判定模型失败:rerank配合小模型的边界与取舍

两天的实验排期,16 组配置,从 rerank 权重到小模型选型再到判定阈值,我几乎把能想到的组合都跑了一遍。结果很直接:没有复现出那个判定模型。但这个过程里踩到的坑、看到的边界、摸清的取舍逻辑,比一个"成功复现&…

2026/10/1 12:51:58 阅读更多 →
连点器全攻略:鼠标自动连点、键盘输入与免费工具筛选

连点器全攻略:鼠标自动连点、键盘输入与免费工具筛选

连点器这三个字一出来,很多人第一反应是"游戏挂机脚本",但说实话我用了这么多年,鼠标自动连点真正帮我省下大把时间的场景,反而是那些枯燥到让人怀疑人生的重复工作:一遍遍点"下一步"、批量填表、…

2026/10/1 12:50:58 阅读更多 →

日新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/30 13:14:22 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/30 18:13:06 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/30 13:14:49 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 0:00:30 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/1 1:01:17 阅读更多 →