项目全景与分层架构
今天不写一行业务代码,但会翻开好几个真实文件(README.md / AGENTS.md / 两个 pyproject.toml),亲眼确认"这框架分几层、层与层之间谁能依赖谁"。目标:在脑子里建立地图,并且这张地图上的每一条线都能在源码里指出出处。今天是全课起点,往后每天开头都有这条进度条帮你定位。
它到底是什么
先破一个最容易踩的误解——项目名叫 gov-agents-platform,但它跟"政务/政府"没有半点关系。这里的 gov 是 governance(治理)的缩写,意思是"给 AI Agent 上护栏、做可信工程化"。
不用听我下定义,直接看核心包的自我介绍。打开 packages/ai-trust-toolkit/pyproject.toml 最上面几行:
[project]
name = "ai-trust-toolkit"
version = "0.6.0"
description = "AI-Trust Engineering Toolkit — Critic, Failsafe, Eval, Memory Protocol for LangGraph Agents"
readme = "README.md"
license = {text = "Apache-2.0"}
requires-python = ">=3.10"
authors = [
{name = "SRE Architecture Team"},
]
keywords = ["langgraph", "agent", "ai-safety", "critic", "evaluation", "rca"]
- description 那行是全仓最诚实的一句话定义:它是一套给 LangGraph Agent 用的"可信工程"工具箱 —— Critic(防幻觉)、Failsafe(失败闸门)、Eval(评测)、Memory(记忆)。这四个词就是 Day 06–11 的主线。
- keywords 里 ai-safety / critic / rca 揭示了它的出身:这套东西是 SRE(故障根因 RCA)场景打磨出来的护栏,后来抽成通用底座。
- version = "0.6.0" —— 记住这个号,等下 L09 你会看到
README.md里还写着 v0.5.0,两个数字对不上,这不是笔误,是"文档漂移",今天会专门讲怎么应对。
一句话给它下定义:
🎯 它是架构组内部的「多 Agent 开发框架 + 平台」——让任何人开发一个新 AI Agent 时,只写业务逻辑、调几个 API,而"防幻觉 / 失败兜底 / 自动评测 / 成本管控"这些可信能力开箱即有,不必每个 Agent 重复造轮子。
所以这个仓库本质上是四大块拼起来的:
一套可信底座
packages/ai-trust-toolkit——防幻觉、闸门、评测、记忆、成本,全平台共享。
二十来个业务 Agent
apps/*——每个基于底座开发,如故障根因、上线风控、文档检查。
把它们跑起来的运行时
server / cli / mcp——HTTP 服务、命令行、以及接入 IDE 的 MCP。
一个 Web 管理门户
gov-agents-portal——看 agent 资产、成本、闸门、回放、评测。
{"case_id":"c-1","alert":"支付超时率突增到 8%"}→ sre-rca Agent 自己去查 trace/日志/最近发布 → 分层取证 → Critic 挑刺防编造
→ 输出:
{"case_id":"c-1","root_cause":"14:02 的 v1.7 发布把连接池从 50 调成 5","evidence":[...],"trace_id":"..."}你作为 Agent 作者,只写"查什么、怎么分析";防幻觉、算钱、兜底全由底座包办。
它解决什么痛点
想象一下:团队里每个人都在写自己的 AI Agent。如果没有统一框架,会发生什么?大模型会一本正经地编造不存在的证据(业界叫"幻觉"),某个工具接口挂了整个 Agent 就崩,没人知道这个 Agent 靠不靠谱、这个月烧了多少钱……于是每个人都得自己写一遍"防幻觉、防崩溃、评测、算钱"的代码。
这个框架就是把这些横切关注点抽出来做成公共能力:
❌ 没有框架时(每个 Agent 各写一遍)
- 大模型编造证据,没人拦
- 工具报错 → 整个 Agent 崩溃
- 没有评测,改坏了也不知道
- 成本失控,月底账单吓一跳
- 换个大模型厂商要改一堆代码
✅ 有了 ai-trust-toolkit(一处实现,处处继承)
- Critic 双层防幻觉,编造的证据 ID 直接拦
- 失败闸门兜底,某步挂了降级不崩
- 评测样本入库,CI 自动跑分不达标就拦合并
- 成本自动归因,预算快烧光自动降级到便宜模型
get_llm()统一入口,换厂商不动业务代码
v0.2 抽 Specialist(2 个 Agent 95% 重复)/ v0.3 抽 business_critic_l1。朴素做法:产品经理一拍脑袋,先把"未来可能用到的所有护栏"都设计好 → 结果大部分能力没人用、还锁死了错误的抽象。
本仓做法:宁可先重复一次,等第二个 Agent 真的抄了同一段代码,才把它"下沉"到 toolkit。代价是短期有重复,收益是每个抽象都是被真实需求逼出来的、不会抽错。这是全仓库最值得偷师的思维,Day 06 会拿
reporter/factory.py(真·三次重复后才上移,见 AGENTS.md:200)细讲。动手前,先认识几个词
后面几天会反复出现这些词,今天先混个脸熟,不用记住细节:
| 名词 | 大白话解释 | 哪天细讲 |
|---|---|---|
| LLM | 大语言模型,就是 Claude、GPT 这种。Agent 的"大脑"。 | Day 03 |
| LangGraph | 一个把 Agent 逻辑画成"流程图"来跑的开源库。图里每个方框叫节点。 | Day 03 |
| State(状态) | 整张流程图共享的一块"黑板",节点从上面读数据、往上面写结果。 | Day 03/05 |
| Node(节点) | 流程图里的一个方框 = 一个处理步骤,比如"查日志"。 | Day 03/05 |
| Specialist(专家) | 一种特殊节点,负责"从某个视角取证分析",比如 trace 专家、metric 专家。 | Day 05/14 |
| Critic(评审员) | 专门给 Agent 结论"挑刺"的节点,防止大模型胡说。 | Day 07 |
| 闸门 Gate | 流程里的"安检口",不达标就拦下来(防崩溃、防超预算)。 | Day 08 |
| envelope(信封) | 所有 Agent 统一的返回格式外壳:case_id + 结果 + 指标 + trace_id。 | Day 12 |
| uv workspace | 把 monorepo 里几十个 Python 包用一条命令统一装好的工具。 | Day 02 |
分层总图:源码说 3 层,教程拆成 5 层
先给你看一个"文档 vs 教程"的诚实对照。仓库 README.md:24 的小标题就叫 「三层分层」——它只官方承认 3 层:
┌─────────────────────────────────────────────┐
│ L3 业务实现层 · apps/sre-rca-agent/ │ 每个 Agent 写 State/Specialists/Prompts
├─────────────────────────────────────────────┤
│ L2 应用脚手架层 │ langgraph-supervisor(pip) + ai-trust-toolkit⭐(自研)
├─────────────────────────────────────────────┤
│ L1 框架/Runtime 层 · langchain-ai/langgraph │ (pip 依赖)
└─────────────────────────────────────────────┘
那为什么我们的教程要画成 5 层?因为源码里还有两块东西不属于这 3 层、但你迟早要碰:gov-agents-portal/(研发门户)和 skills/(给 IDE AI 用的一句话 SOP)。AGENTS.md:119-130 的分层表就把它们补上了——多出 L2.5 DevX 和 L4 工具生态。所以"5 层"是我们为了讲清楚、在源码 3 层骨架上加的两层"标注",不是我编的。
下图里那颗发光的小球,代表一次真实请求"从上往下穿过每一层"。你现在只需要建立一个直觉:越往下越通用、越稳定(很少改);越往上越贴业务、越常改。
逐层拆解:读真依赖,确认每层管什么
L1 · 框架 / Runtime 层
大白话:Agent 的"操作系统"。真正负责"跑流程图、管状态、按顺序执行节点"的底层引擎。
关键点:这一层全是外部开源库,本仓库一行都不改,通过 uv/pip 装进来。别只信我说——直接看 toolkit 的依赖清单:
dependencies = [
# 仅依赖 langgraph runtime 本身,不依赖 supervisor-py
# 这是核心解耦原则
"langgraph>=0.2.0",
"langchain-core>=0.3.0",
"pydantic>=2.0",
- 第 2-3 行的注释是作者亲手写下的设计承诺:"仅依赖 langgraph runtime 本身,不依赖 supervisor-py"。也就是说 L1 只有 langgraph 引擎 + langchain-core 的基础类型。
- langgraph>=0.2.0 就是 L1。toolkit 把它当地基用,但从不改它的源码——升级它只需要
uv lock --upgrade-package langgraph。 - pydantic>=2.0 用来做数据校验(后面 config、envelope 全靠它),不是 Agent 引擎,属于工具依赖。
langgraph-supervisor 是"多个 Agent 怎么协作"的库(Day 04 讲)。它本可以被 toolkit 依赖,但作者刻意不依赖。README.md:117-121 那张"解耦设计原则"表给了原因:·
supervisor-py 升级 → 不影响 ai-trust-toolkit;·
ai-trust-toolkit 升级 → 不影响 supervisor。两块能力互不牵连,各自升级、各自测试。代价是 toolkit 不能直接调 supervisor 的便利函数;收益是"防幻觉/闸门"这套护栏,就算你根本不用多 Agent 协作也能单独用——解耦买来了"能单独复用"。
L2 · 应用脚手架层 ⭐(框架的灵魂)
大白话:一组"横切的护栏能力",让任何业务 Agent 开箱即有防幻觉/闸门/评测/记忆/成本治理。这就是 packages/ai-trust-toolkit/,是本教程 Day 06–11 的主战场。它内部的模块划分不是我编的,是 ls 出来的真实目录:
critic/ failsafe/ eval/ memory/ specialists/
cost/ api/ tools/ testing/ reporter/ sensitivity/
config.py llm.py effect.py observability.py handoff.py portal_telemetry.py
这一层还包含 3 个"运行载体"包:gov-agents-server(多 agent 同进程 host)、gov-agents-cli(命令行 agentctl)、gov-agents-mcp(把 agent 暴露给 IDE)。Day 12–13 细讲。
L3 · 业务实现层
大白话:每个具体 Agent 自己写的业务代码,在 apps/<agent>/。规矩写死在 AGENTS.md:121——L3 只写四样东西:
L3 业务 apps/ ← 每个 Agent 只写:State / Specialists / Prompts / DAG
护栏能力全部从 L2 import 进来,不重复实现。Day 03 讲清 State/DAG 是什么,Day 05 拆解结构,Day 14 逐文件精读旗舰 Agent sre-rca。
L2.5 · 研发体验层 (DevX) + L4 · 工具生态层
这两层是后来补上的,AGENTS.md:120-122 明确了它们各自"只服务谁":
- L2.5 =
gov-agents-portal/:脚手架 CLI + Web Wizard + 开发工具,AGENTS.md:138 硬性规定"SHALL 只服务 R&D 工程师",目标"写新 agent 快 10×"。Day 16 讲。 - L4 =
skills/:给 IDE 里的 AI(Claude Code / Cursor)用的 SOP——你说一句人话"帮我审下这个 PR 的上线风险",它就自动去调对应的 agent。Day 19 讲。
一条贯穿全书的铁律:依赖方向(读真源码)
这是整个框架最重要的一条约束。它不是口号,而是写进了两个文件、措辞几乎一样——先看 README.md:
**关键约束**:
1. ai-trust-toolkit **不依赖** supervisor-py(toolkit 是 supervisor 之下的横切能力)
2. ai-trust-toolkit **只依赖** langgraph runtime 自身(State / Node / Edge / Reducer)
3. 业务 app 同时依赖 supervisor + toolkit + langgraph
再看 AGENTS.md 给新人/AI 的"铁律"版本,说得更狠:
**铁律**:
1. L2 不许 import L3 —— toolkit 不知道业务域存在
2. L3 不许重复实现 toolkit 已有的能力 —— 缺什么先去 toolkit 抽
3. 跨 L3 复用走 toolkit,**不许** apps 互相 import
4. L4 单向向下:skills/ 调 MCP tools / agentctl / OpenAPI · L1-L3 不许 import skills/
- 铁律 1(L2 不许 import L3):翻译成大白话——底座不许知道有哪些业务。toolkit 里你永远不会看到
import sre_rca。因为一旦底座认识了某个业务,它就不通用了。 - 铁律 3(apps 不许互相 import):
apps/A不许import apps/B。两个业务要复用一段逻辑,唯一合法路径是"下沉到 toolkit,再各自 import 底座"。 - 铁律 4(skills 单向向下):L4 只能调下面的东西,下面 L1-L3 绝不能反过来 import
skills/。方向永远朝下。
把这几条画成一张"谁能指向谁"的依赖 DAG(有向无环图),你就永远不会记反:
👨🏫 老师:不行——那等于"3 楼住户为了用个东西,把管子直接接到 5 楼住户家里",两户就绑死了。正确做法是把这段公共逻辑下沉到承重层(toolkit),两户各自从楼下取用。这正是 L02 讲的"渐进抽象"的由来:出现第二次重复,就把它沉下去。
import anthropic 绕过 get_llm()。AGENTS.md:286 甚至记着一笔"历史欠账":bmc-agent 曾经直接 from anthropic import Anthropic 破了规矩,后来在 2026-05-17 才修回走 get_llm()。启示:真实代码库里"理想规范"和"历史现实"会并存,读代码要能分清哪些是当下约定、哪些是待还的债。仓库目录地图 & workspace 成员表
打开仓库根目录,你会看到这些文件夹。先建立"哪个文件夹装什么"的地图,后面就知道去哪找:
gov-agents-platform/
├── apps/ ★ L3 业务 Agent,每个一个独立包(实测 21 个)
├── packages/ ★ L2 toolkit + starter 包 + server/cli/mcp
│ ├── ai-trust-toolkit/ ⭐⭐ 可信底座,全仓灵魂
│ ├── ai-trust-toolkit-bom/ 依赖版本清单(Bill of Materials)
│ ├── ai-trust-toolkit-starter-* 各类 agent 的"快速起手包"
│ ├── gov-agents-server/ 多 agent 同进程 HTTP 服务
│ ├── gov-agents-cli/ 命令行 agentctl
│ └── gov-agents-mcp/ 把 agent 暴露给 IDE 的 MCP
├── gov-agents-portal/ L2.5 Web 管理门户(Next.js 前端 + FastAPI 后端)
├── skills/ L4 给 IDE AI 用的一句话 SOP
├── openspec/ 规格驱动开发的契约(Day 20 讲)
├── configs/ 分环境 YAML:base/dev/staging/prod/test(Day 02 讲)
├── deploy/ K8s 部署清单 + Grafana 面板
├── scripts/ 运维/CI 脚本(ci/ canary/ infra/)
├── docs/ 平台文档 40+ 篇(含 learn-langgraph 入门 demo)
├── examples/ 独立仓 agent 脚手架模板
├── Dockerfile 一个镜像 + ENABLED_AGENTS 跑任意 agent 组合
├── docker-compose.yml 本地全栈(redis + platform)
├── pyproject.toml ⭐ uv workspace 根:把所有包串成一个整体
├── README.md 总说明
└── AGENTS.md ⭐ 给新人/AI 的 30 秒 ramp-up 指南
"把所有包串成一个整体"这句话,落地就是根 pyproject.toml 里的 [tool.uv.workspace]。这是一张真实的清单——数一下有 31 个成员:
[tool.uv.workspace]
members = [
"packages/ai-trust-toolkit", # ← L2 灵魂
"packages/gov-agents-server", # ← 运行时
"packages/gov-agents-cli",
"apps/sre-rca-agent", # ← L3 旗舰
"apps/risk-reviewer",
# … 一直到 apps/supervisor-router-agent,共 31 条
"gov-agents-portal/backend", # ← 连门户后端也进了 workspace
]
[tool.uv.sources]
ai-trust-toolkit = { workspace = true } # ← 关键!从本地 workspace 取,不去 PyPI 下载
gov-agents-mcp = { workspace = true }
- members 列出了要被"当成一个大项目一起装"的所有子包。Day 02 会讲,一条
uv sync --all-packages就把这 31 个包全部以 editable(可编辑)方式装好。 - [tool.uv.sources] 里
ai-trust-toolkit = { workspace = true }是画龙点睛:它告诉 uv"当某个 app 声明依赖 ai-trust-toolkit 时,用本地这份源码,而不是去 PyPI 下载同名包"。这就是为什么你改一行 toolkit 源码,21 个 app 立刻用上新代码。
pip install ai-trust-toolkit==0.6.0。好处是隔离彻底;坏处是——改 toolkit 一行要发版、21 个 Agent 逐个升级锁版本,"渐进抽象"根本转不动。本仓做法(monorepo):一份源码、一个
uv.lock 锁死所有版本,toolkit 改动当场对全平台生效并被全套测试覆盖。代价是仓库大、CI 要跑全量。对一个"底座还在快速演进、要频繁下沉公共逻辑"的平台,这个取舍是划算的。(注:平台也提供 examples/ 脚手架支持"独立仓 Agent",见 Day 21——两种形态并存。)packages/ai-trust-toolkit/(灵魂)、apps/sre-rca-agent/(旗舰范本)、docs/learn-langgraph/(4 个能跑的入门 demo,Day 03 就用它)。技术栈一览(每一项都能在依赖里指出出处)
不用现在全懂,先知道"这个项目用了什么"。下表右列不是我编的,都能在 packages/ai-trust-toolkit/pyproject.toml:24-56 那段 dependencies 里逐行找到:
| 类别 | 选型 | 依赖里的出处(真行) |
|---|---|---|
| 语言 | Python ≥ 3.10(Docker 运行时用 3.12) | pyproject.toml:11 requires-python |
| Agent 框架 | langgraph ≥ 0.2、langchain-core ≥ 0.3 | :27-28(L1 层) |
| 数据校验 | pydantic ≥ 2.0 | :29(config/envelope 全靠它) |
| ID 生成 | python-ulid(case_id/trace_id 用 ULID,字典序=时间序) | :30-31 |
| Web 服务 | FastAPI ≥ 0.110(v1 API 是一等公民,非 optional) | :34-36 |
| 可观测 | prometheus-client(每次 invoke 都推指标) | :37-39 |
| 外部工具 | mcp(让 agent 调外部 MCP server) | :40-41 |
| 记忆存储 | psycopg + pgvector(向量检索)、redis checkpoint | :42-44 |
| DB 迁移 | alembic + SQLAlchemy 2.0 + asyncpg(schema 单一真相) | :45-52 |
| 配置 | pyyaml(load_config 的 yaml profile loader) | :53-55(Day 02 精讲) |
[project.optional-dependencies]),你不用 pgvector 就不装。这体现了"核心必装、后端按需"的分层依赖设计。三条学习主线 & 一个必知的坑
读这份代码的三条主线
纵向一条:跟一次请求走完全程
从"用户提问"进 server → 走 agent 的 LangGraph 图(triage→取证→综合→critic)→ 出统一 envelope。这是理解"运行时"的主线(Day 12 + Day 14)。
横向一条:吃透一个能力
选 Critic 防幻觉,从"业务怎么调"到"toolkit 内部两层怎么拦"看透。这是理解"可信底座"的主线(Day 07)。
元一条:平台如何"自己开发自己"
requirement-discoverer 发现需求 → spec-author 写规格 → spec-executor 改代码 → release-coordinator 评审。这是最有意思的进阶主线(Day 15 + Day 20)。
⚠️ 一个必须知道的坑:文档版本漂移
这是一个真实、活跃演进中的项目,所以文档里的数字经常对不上。这不是 bug,是"文档是某天的快照、代码在持续动"的必然结果。用真实数字给你排一排:
| 说法来源 | toolkit 版本 | Agent 数量 | 你该信哪个 |
|---|---|---|---|
README.md:72 | v0.5.0 | 9 个 apps | ❌ 旧快照 |
packages/.../pyproject.toml:7 | v0.6.0 | — | ✅ 版本以此为准 |
ls apps/ | wc -l | — | 21 个 | ✅ 数量以此为准 |
pyproject.toml workspace members | — | 31 个成员(含 packages) | ✅ 装什么以此为准 |
记住一条原则:代码/配置是 ground truth(唯一真相),文档只是某一天的快照。 遇到数字对不上,别慌,以 grep 代码 + 看 pyproject.toml 为准——这正是 Day 20 讲的 openspec/specs/ 被称为"契约 ground truth"(AGENTS.md:340)的原因。
${VAR}",但实际 dev.yaml 里硬编码了明文数据库密码和真实网关密钥(Day 02 会看到原文)。这是"理想规范 vs 落地现实"的活教材——学习时要能一眼识别"这是它自己都不推荐的写法,别照抄"。今日小结 + 动手
🧠 今天你应该能回答这几个问题
gov是什么意思?(治理 governance,不是政务;证据:toolkit pyproject 的 description)- 这个框架解决什么痛点?靠什么方法论演进?(横切护栏做成公共底座;渐进抽象——第 2 次重复才抽)
- 分层与依赖铁律?(README 说 3 层,教程补成 5 层;依赖只能上→下,L2 不认识 L3,apps 不互相 import)
- toolkit 为什么不依赖 supervisor?(解耦:各自升级互不牵连,护栏能单独复用)
- 遇到文档数字对不上怎么办?(以代码 / pyproject / openspec 为准)
✋ 动手 5 分钟(可选,但强烈建议)
如果你手边能打开这个仓库,跟着敲一遍——把"地图"落到真实文件上,顺便亲手验证今天引用的每一处:
# 1. 看核心包的自我介绍(对照 L01 的 description)
grep -A3 "name = \"ai-trust-toolkit\"" packages/ai-trust-toolkit/pyproject.toml
# 2. 亲眼确认"toolkit 只依赖 langgraph 不依赖 supervisor"(对照 L05)
sed -n '24,29p' packages/ai-trust-toolkit/pyproject.toml
# 3. 读依赖铁律(对照 L06)
sed -n '124,137p' AGENTS.md
# 4. 数一数到底有几个业务 Agent(验证"文档漂移")
ls apps/ | wc -l # 你会看到 21,而不是 README 说的 9
# 5. 看 workspace 把哪些包串在了一起(对照 L07)
grep -A 40 "tool.uv.workspace" pyproject.toml
config.py 的 _deep_merge / load_config,用一个真实的 base.yaml + dev.yaml 合并例子把配置系统焊死。