摘要
传统单LLM Agent代码审查存在逻辑单一、无法分层校验缺陷。本文基于LangGraph 0.3.x最新StateGraph架构,采用主管Supervisor + 语法/安全/优化三类专家子Agent + 静态规则工具前置三层Supervisor模式,搭建完整自动化代码审查流水线。全套代码包含状态类型安全、全局异常重试、日志持久化、Token成本优化方案,附带线上高频踩坑完整修复方案,同时横向对比CrewAI/AutoGen多Agent框架选型,适配研发CI自动化、代码评审机器人落地场景。
关键词:LangGraph;Supervisor多智能体;Agent流水线;代码审查;LLM工程化;StateGraph
目录
5.1 类型安全State状态定义
5.2 静态规则校验工具(零LLM消耗)
5.3 三类专家子Agent节点
5.4 Supervisor汇总统筹节点
5.5 图编排&完整执行入口
一、行业痛点:单Agent代码审查的固有缺陷
直接使用单个大模型完成全量代码审查存在三大无法规避问题:
采用LangGraph Supervisor分层多智能体架构,将静态规则工具前置,拆分三类专业子Agent,由主管统一调度汇总,实现分层、可控、低成本自动化代码评审。
二、Supervisor架构底层原理&框架横向选型对比
2.1 Supervisor核心架构定义
Supervisor模式采用中央统筹+专业化工作者分层设计:
2.2 主流多Agent框架横向对比
| LangGraph Supervisor | 有向图自定义路由、循环中断 | TypedDict强类型、支持断点 | ★★★★★ 分层可控 | 中等,需自定义节点 |
| CrewAI | 固定串行/并行流程,无自定义图 | 内置简易记忆 | ★★★ 流程固化难拓展 | 低,开箱即用 |
| AutoGen | 对等Agent协商,无中央主管 | 消息列表弱状态 | ★★ 无统一汇总逻辑 | 高,调度逻辑复杂 |
结论:代码审查、合规校验这类多维度分层汇总场景,LangGraph Supervisor是最优选型。
三、三层分工整体架构
流程逻辑:先通过零成本静态规则扫描基础问题,再由专用子Agent做深度LLM分析,最后主管统一汇总、分级给出修复建议。
四、全环境标准化部署
4.1 虚拟环境&依赖安装
python3 -m venv .venv
source .venv/bin/bash
pip install –upgrade pip
# 固定兼容LangGraph 0.3.x稳定版本
pip install langgraph==0.3.15 langchain-openai python-dotenv tenacity
4.2 项目标准目录
code_review_agent/
├── .env # LLM密钥统一存放
├── .gitignore
├── main.py # 完整流水线主代码
├── review_logs/ # 每次审查日志持久化
└── README.md
4.3 .env环境配置(兼容OpenAI/DeepSeek/智谱等兼容接口)
OPENAI_API_KEY=sk-xxxxxxx
OPENAI_API_BASE=https://api.deepseek.com/v1
# 子Agent低成本小模型,主管使用强推理模型
SUB_AGENT_MODEL=gpt-4o-mini
SUPERVISOR_MODEL=gpt-4o
4.4 .gitignore
.venv/
.env
review_logs/
__pycache__
*.log
五、完整分层可运行工程代码
5.1 导入依赖、全局日志、异常重试封装
from typing import Annotated, Sequence, TypedDict, Optional
import operator
import os
import re
import ast
import datetime
from dotenv import load_dotenv
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
# 加载环境变量
load_dotenv()
# 全局日志持久化
LOG_DIR = "review_logs"
os.makedirs(LOG_DIR, exist_ok=True)
def write_log(content: str):
log_path = os.path.join(LOG_DIR, f"{datetime.date.today()}.log")
with open(log_path, "a", encoding="utf-8") as f:
f.write(f"[{datetime.datetime.now()}] {content}\\n")
# 统一LLM异常重试装饰器(限流/超时自动退避)
llm_retry = retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=2, max=8),
retry=retry_if_exception_type(Exception)
)
# 模型初始化区分成本
sub_llm = ChatOpenAI(
model=os.getenv("SUB_AGENT_MODEL", "gpt-4o-mini"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_API_BASE"),
temperature=0.3
)
sup_llm = ChatOpenAI(
model=os.getenv("SUPERVISOR_MODEL", "gpt-4o"),
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_API_BASE"),
temperature=0.2
)
5.2 强类型共享State(字段隔离,避免覆盖)
class CodeReviewState(TypedDict):
code: str # 待审查源码
language: str # 编程语言
lint_report: Optional[str] # 语法规范报告(独立字段)
security_report: Optional[str] # 安全审计报告
optimization_report: Optional[str] # 优化建议报告
final_report: Optional[str] # Supervisor汇总最终报告
messages: Annotated[Sequence, operator.add] # 对话自动追加
error_logs: Annotated[Sequence, operator.add] # 全局异常日志
5.3 前置零LLM静态规则校验工具
def safe_check_syntax(code: str) –> str:
"""AST语法校验,捕获异常不中断流程"""
try:
ast.parse(code)
return "✅ 语法无错误"
except SyntaxError as e:
return f"❌ 语法异常 行{e.lineno}: {e.msg}"
except Exception as e:
return f"⚠️ 语法检测工具异常: {str(e)}"
def scan_security_rule(code: str) –> str:
findings = []
if re.search(r'\\beval\\s*\\(', code):
findings.append("🚨 高危eval代码注入风险")
if re.search(r'\\bexec\\s*\\(', code):
findings.append("🚨 exec执行任意代码严重漏洞")
if re.search(r'password\\s*=["\\']', re.IGNORECASE, code):
findings.append("⚠️ 硬编码密钥存在泄露风险")
if re.search(r'f["\\'].*SELECT.*\\{', re.IGNORECASE, code):
findings.append("🚨 SQL字符串拼接注入漏洞")
if re.search(r'os\\.chmod.*0o777', code):
findings.append("⚠️ 过度开放文件权限")
return "\\n".join(findings) if findings else "✅ 无明显安全规则风险"
def scan_performance_rule(code: str) –> str:
tips = []
if re.search(r'for\\s+\\w+\\s+in\\w+:\\s*\\n\\s+\\w+\\.append\\(', code):
tips.append("💡 建议使用列表推导式替代循环append")
line_list = code.split("\\n")
func_lines = 0
in_func = False
for line in line_list:
if re.match(r"\\s*def\\s+\\w+\\(", line):
in_func = True
func_lines = 0
elif in_func and line.strip() and not line.startswith("#"):
func_lines += 1
if func_lines > 50:
tips.append(f"💡 函数超过50行,建议拆分")
in_func = False
imports = re.findall(r'^import |^from ', re.MULTILINE, code)
if len(imports) != len(set(imports)):
tips.append("💡 存在重复导入语句")
return "\\n".join(tips) if tips else "✅ 代码结构性能良好"
5.4 三类专家子Agent节点(带重试、日志)
@llm_retry
def lint_agent(state: CodeReviewState) –> dict:
write_log("【启动语法规范Agent】")
code = state["code"]
lang = state["language"]
# 先执行静态工具
static_res = safe_check_syntax(code)
prompt = f"""你是{lang}代码规范专家,基于静态检测结果做深度代码审查:
静态检测结果:{static_res}
审查维度:命名规范、注释、边界异常、代码异味
代码:
```{lang}
{code}
输出分:【问题】【对应修改方案】,分级标注严重程度"“”
resp = sub_llm.invoke(prompt)
full_report = f"## 静态AST检测\\n{static_res}\\n## Lint深度分析\\n{resp.content}"
write_log(f"【Lint Agent完成,报告长度{len(full_report)}字符】")
return {“lint_report”: full_report, “messages”: [(“system”, “语法审查完成”)]}
@llm_retry
def security_agent(state: CodeReviewState) -> dict:
write_log(“【启动安全审计Agent】”)
code = state[“code”]
static_sec = scan_security_rule(code)
prompt = f"""安全审计专家,结合规则扫描结果深度排查漏洞:
规则扫描:{static_sec}
排查:注入、密钥泄露、权限、反序列化风险
代码:
{code}
按严重程度排序,每条给出修复代码示例"“”
resp = sub_llm.invoke(prompt)
full_report = f"## 规则安全扫描\\n{static_sec}\\n## LLM深度安全分析\\n{resp.content}"
write_log(“【安全Agent执行完毕】”)
return {“security_report”: full_report, “messages”: [(“system”, “安全审计完成”)]}
@llm_retry
def optimization_agent(state: CodeReviewState) -> dict:
write_log(“【启动性能优化Agent】”)
code = state[“code”]
static_opt = scan_performance_rule(code)
prompt = f"""代码性能优化专家,基于静态规则给出重构方案:
规则检测:{static_opt}
关注循环、IO、内存、并发、语言特性优化
代码:
{code}
每项优化附带重构后的完整代码片段"“”
resp = sub_llm.invoke(prompt)
full_report = f"## 静态性能扫描\\n{static_opt}\\n## LLM优化建议\\n{resp.content}"
write_log(“【优化Agent执行完毕】”)
return {“optimization_report”: full_report}
### 5.5 Supervisor主管汇总节点
```python
@llm_retry
def supervisor_agent(state: CodeReviewState) -> dict:
write_log("【Supervisor开始汇总全维度审查报告】")
parts = []
if state.get("lint_report"):
parts.append("# 一、代码规范审查\\n" + state["lint_report"])
if state.get("security_report"):
parts.append("# 二、安全漏洞审计\\n" + state["security_report"])
if state.get("optimization_report"):
parts.append("# 三、性能优化建议\\n" + state["optimization"])
all_text = "\\n—\\n".join(parts)
prompt = f"""资深研发主管,整合三份代码审查报告输出综合结论:
要求:
1. 总体评级:PASS / WARN / FAIL
2. 严重问题从高到低排序
3. 分紧急修复/优化两类清单
4. 一句话总结代码可合并标准
全部审查内容:
{all_text}"""
final = sup_llm.invoke(prompt).content
write_log(f"【审查完成,最终报告生成完毕】")
return {"final_report": final, "messages": [("system", "主管汇总完成")]}
5.6 构建图&执行入口
def build_review_workflow() –> StateGraph.compile:
workflow = StateGraph(CodeReviewState)
# 注册全部节点
workflow.add_node("lint", lint_agent)
workflow.add_node("security", security_agent)
workflow.add_node("optimization", optimization_agent)
workflow.add_node("supervisor", supervisor_agent)
# 串行固定流程:语法→安全→优化→汇总
workflow.add_edge("lint", "security")
workflow.add_edge("security", "optimization")
workflow.add_edge("optimization", "supervisor")
workflow.add_edge("supervisor", END)
workflow.set_entry_point("lint")
return workflow.compile()
if __name__ == "__main__":
# 测试含多重漏洞示例代码
test_code = """
import os
import os
DB_PASSWORD = "admin123"
def query_user(uid):
sql = f"SELECT * FROM user WHERE id={uid}"
conn = os.popen(f"psql -c '{sql}'")
res = []
for line in conn:
res.append(line)
return res
def long_func(a,b,c,d,e,f,g,h,i,j):
x=a+b;x+=c;x+=d;x+=e;x+=f;x+=g;x+=h;x+=i;x+=j
return x
eval("print(123)")
"""
graph = build_review_workflow()
result = graph.invoke({
"code": test_code,
"language": "python",
"messages": [],
"error_logs": []
})
print("="*70)
print("📋 自动化代码审查综合报告")
print("="*70)
print(result["final_report"])
六、运行输出效果示例
======================================================
📋 自动化代码审查综合报告
======================================================
总体评级:FAIL(存在高危注入漏洞,禁止合并)
一、高优先级紧急修复项
1. 代码第4行f-string拼接SQL,存在SQL注入风险,改用参数化查询
2. 第14行eval执行任意代码,存在远程代码执行漏洞
3. 硬编码数据库明文密码,存在仓库泄露风险
二、优化改进项
1. long_func函数超过50行,建议拆分为多个子函数
2. 循环append可替换列表推导式,提升运行效率
三、总结
代码存在可被外部攻击者利用的高危安全漏洞,必须完成修复后才能合并至主分支。
七、线上高频踩坑完整根因+修复方案
坑1:State字段互相覆盖
根因:不同节点返回同名字典key,覆盖已有报告
修复:每个Agent仅返回自身专属字段(lint_report/security_report互不重叠),状态分层隔离。
坑2:LLM接口限流、超时直接中断流程
根因无重试机制,单次API失败整条流水线作废
修复:统一tenacity指数退避重试装饰,捕获网络/限流异常。
坑3:无日志,线上故障无法回溯
修复:全局write_log持久化每日日志文件,记录每个Agent执行节点。
坑4:Token消耗过高,单轮审查成本昂贵
优化方案:
坑5 代码过长导致上下文溢出
拓展:增加代码分片子Agent,超长文件分块审查后汇总。
八、生产级高阶拓展方案(创新性工程升级)
无依赖模块改用并行边,同时执行安全、语法、优化Agent,缩短总耗时。
引入langgraph-checkpoint-redis,流程中断可恢复审查进度。
增加文件哈希缓存,相同代码无需重复调用LLM,大幅降低Token开销。
增加HumanInterrupt,高危漏洞触发人工审核再输出报告。
封装脚本接入GitLab/GitHub Actions,提交代码自动触发审查。
九、落地标准化最佳实践总结
#LangGraph #多智能体 #Supervisor #AI代码审查 #LLM工程化 #Python自动化



