标签:AI Agent 系统架构 分层设计 LangGraph 工业AI 架构设计
起点:单文件脚本的极限
AgentClaw 的第一个版本只有一个文件:react_agent.py。
里面塞了 LLM 调用、工具定义、对话记忆、API 服务——所有东西混在一起。能跑,但每次加新功能都要改核心代码,改一处崩一片。更糟的是,项目里后来出现了两套完全独立的体系:Track A 用 LangGraph 做 Agent 编排,Track B 用自建的工具注册系统管理工具。两套体系各自能跑,但互不通信,工具代码无法复用。
当工具数量从2个增长到18个,当功能从问答扩展到多模态、OS操作、自主进化,单文件脚本和双轨并行都走到了极限。
我需要一套架构——不是“把代码分几个文件”,而是让每个模块有明确的职责边界、清晰的通信协议、独立可测试、可替换。
设计原则:从产线学到的三条铁律
在搭架构之前,我先定了三条原则。它们不是从软件工程教科书上抄的,而是从产线设计中学到的。
原则一:单一职责。 产线上每个工位只做一件事——贴片机只管贴片,检测机只管检测。软件架构也应该如此。ToolRegistry 只管工具注册,SecurityGuard 只管安全检查,ReActDispatcher 只管推理调度。每个模块只有一个理由需要修改。
原则二:接口标准化。 产线上不同供应商的设备通过统一的协议通信。软件架构也应该如此。所有层之间通过 JSON 格式通信,工具返回统一格式 {"success": bool, "result": any, "error": str}。上层不需要关心下层实现,只要接口不变,内部随便改。
原则三:默认拒绝。 产线上的安全设计是“宁可误拦一千,不漏放一个”。软件架构也应该如此。不是“检查到危险再说”,而是“只有明确允许的才放行”。
这三条原则,构成了六层架构的设计基础。
六层架构全景
text
L6 检测层(health.py)
└─ 三维健康检查: ChromaDB / LLM API / 内存
↑
L5 服务层(api_server.py + demo_ui.py)
└─ FastAPI REST API + Gradio Web UI
↑
L4 编排层(agent_core.py)
└─ LangGraph ReAct 循环 + 单例注册
↑
L3 安全与可靠性层(security.py + retry.py + rate_limiter.py)
└─ SQL/XSS检测 + 指数退避重试 + 令牌桶限流
↑
L2 工具层(tool_registry.py + registry_adapter.py)
└─ 18个工具的单例注册中心 + LangGraph桥接适配器
↑
L1 基础层(core/config.py + logger.py)
└─ 配置验证 + 结构化日志
每层只依赖下一层,不跨层调用,不反向依赖。
逐层拆解:为什么每一层都存在
L1 基础层:不是“工具包”,是“地基”
很多人把配置管理和日志记录写成工具函数,需要时 import 调用。我选择把它们提升为独立的一层。
原因有二。第一,所有上层模块都依赖配置和日志——配置管理启动时加载、日志系统需要统一格式。如果它们是零散的工具函数,每个模块可能用不同的日志格式、不同的配置来源,排查问题时需要在多种格式之间切换。第二,如果未来要从 .env 文件迁移到配置中心,只需要修改 L1 层的实现,所有上层代码不受影响。
L2 工具层:注册-发现-检查-执行的流水线
工具层是整个架构的核心。它解决了两个问题:工具怎么注册、怎么调用。
注册用 @registry.register 装饰器——声明式注册,一行代码搞定。调用用 registry.execute()——统一入口,支持字典传参和关键字传参两种风格。
还有一个隐藏设计:RegistryAdapter。它把自研的工具注册中心转换为 LangGraph 兼容的格式,让 Track A 和 Track B 无缝融合。这不是修修补补,而是在不修改两套系统核心代码的情况下,用一个适配器完成桥接。
L3 安全与可靠性层:Agent 的“刹车”
L1 和 L2 让系统能跑。L3 让系统不会跑崩。
- 安全中间件:令牌桶全局限流 + SQL注入检测 + XSS检测 + 敏感词过滤 + 请求体长度限制。五层检查,一层失败就拒绝。
- 重试机制:指数退避 + 随机抖动。API调用失败时自动重试最多3次,每次等待时间翻倍,加上随机因子防止重试风暴。
- 令牌桶限流:三层部署。全局HTTP限流保护系统不被过载,LLM调用限流保护API配额,工具执行限流防止恶性循环。
这层的设计哲学来自产线的“防呆设计” ——不是相信操作员不会犯错,而是设计一个让操作员没法犯错的系统。
L4 编排层:Agent 的“大脑”
L4 是推理引擎。它负责接收用户输入,调用 LLM 进行思考,决定调用哪些工具,处理工具返回结果,最终给出答案。
为什么不用 LangGraph 自带的编排?LangGraph 的 StateGraph 是优秀的图编排工具,但抽象层级太高——节点内部发生了什么、某个节点失败后应该怎么回滚,被框架封装了。对于需要精确控制每个环节的生产系统来说,这种“黑盒式”抽象在出问题时让人束手无策。
所以 L4 在 LangGraph 之上封装了 agent_core.py 作为统一入口:懒加载单例、工具初始化、进化系统管理、速率限制器就绪检查——这些是框架不会帮你做的工程化细节。
L5 服务层:对外窗口
L5 是最薄的一层——只做协议转换,不做业务逻辑。
FastAPI 提供 REST API,Gradio 提供 Web UI。两者共享同一个 Agent 实例,通过 get_react_agent()单例获取。
L6 检测层:运维的眼睛
L6 是 v6.1 新增的。它暴露两个端点:/health 返回基础状态(版本、运行时间、内存),/health/detailed 检测依赖服务(ChromaDB 心跳、LLM API 可达性、系统内存)。
设计目标是兼容 Kubernetes 探针:LivenessProbe 用 /health,ReadinessProbe 用 /health/detailed。进程挂了 Pod 自动重启,依赖服务不可用时 Pod 从负载均衡摘除。
三条核心数据流
架构不是静态的层级图,而是数据流动的管道。AgentClaw 有三条核心数据流:
主线一:请求-响应流。 用户输入 → SecurityMiddleware 安全校验 → LLM 推理 → 工具选择 → 工具执行(含限流+重试)→ 观察结果 → 继续推理或返回答案。这是系统最核心的数据流,每个用户请求都会走这条路径。
主线二:反馈采集流。 每次工具执行后 → RegistryAdapter 自动采集 FeedbackSignal(工具名、成败、延迟、错误类型)→ FeedbackCollector 写入缓冲区 → 每50条持久化到 JSONL 文件。这条流完全异步,不阻塞主链路。
主线三:进化优化流。 EvolutionManager 后台线程每小时触发一次 → 从反馈数据中挖掘成功模式 → 经验学习器生成优化策略 → 自适应优化器用 EMA 算法更新路由权重和 Prompt 模板 → 新策略在下一次请求中生效。这条流是“零侵入”的——不修改核心代码,只是旁路监听和后台优化。
架构的代价
没有完美的架构,六层架构也有代价。
理解成本变高了。新人需要先理解六层分别做什么,才能定位问题。调用链路变长了,一次请求要穿过 L5 → L4 → L3 → L2 → L3 → L4 → L5。但换来的是每个模块可以独立测试、独立替换——换一个 LLM 提供商,只改 L4;换一个向量数据库,只改 L2。
从AME视角看这件事
产线布局和软件架构,本质上是同一件事。
产线上每个工位有明确的输入、输出、节拍、质量标准。软件架构中每个模块也应该有明确的输入、输出、接口、异常处理。产线上的设备通过标准协议通信。软件架构中层与层之间也应该通过标准协议通信。产线上的安全是“默认拒绝”。软件架构中的安全也应该是“默认拒绝”。
AgentClaw 的六层架构,不是从软件工程教科书上抄的。它是AME的系统思维在软件领域的自然延伸。
我不是在“设计软件架构”,我是在用AME的方法论,为Agent系统设计一条“数字产线”。