你有没有被多 Agent 的混乱折磨过?我有。而且被折磨了很久。
从一次翻车说起
去年某天深夜,我盯着屏幕上 5 个 AI Agent 吐出来的一坨不知所云的结果,整个人是崩溃的。
事情是这样的:我用 CrewAI 搭了一个"自动代码审查+安全扫描+测试用例生成"的多 Agent 流水线。看上去挺美------三个 Agent 各司其职,一个审代码质量,一个扫安全漏洞,一个写测试。理论上应该协作无间、交付完美吧?
结果呢?
审代码的那个 Agent 改了一段逻辑之后,安全扫描的 Agent 完全不知道代码已经变了,拿着旧版本的代码一顿扫,扫出了一堆"不存在的漏洞"。写测试的 Agent 更绝------它测的是原始版本的接口,跟前面两位产出的东西完全对不上。
三个 Agent 各干各的,你不知道我改了什么,我不知道你扫了什么,最后交上来的东西?一锅粥。
那一刻我站起来倒了杯水,脑子里反复就一个念头:
这帮 AI,需要有人管。而且不能是那种"你们自己商量商量"的管法------得有制度、有流程、有人审核、有人拍板。
灵感来了:1400 年前古人就解决过这个问题
说来你可能不信,灵感来自一次无聊翻历史书。
唐朝的三省六部制------中书省起草诏令,门下省审核封驳,尚书省执行派发。如果中书省写的方案门下省觉得不靠谱?直接封驳,打回重写。不是给你一个 warning,不是写个日志让人事后去看------是直接不让你往下走。
我当时"啪"一下就拍了大腿。
这不就是我要的吗?
现在所有 Multi-Agent 框架的通病是什么?Agent A 做完直接甩给 Agent B,B 做完甩给 C。中间没有任何质量把关。就像一个公司没有 QA 部门,工程师写完代码直接上线------出事只是时间问题。
而三省六部制天然就有一层制度性审核 。不是可选的插件,不是你想开就开想关就关的 flag------它是架构的一部分。每一个任务都必须经过这一层,没有例外。
1300 年前唐太宗就想明白了的道理:不受制约的权力必然会出错。
放到 AI 多 Agent 协作里,这句话可以翻译成:不受审核的 Agent 产出必然会翻车。
架构总览:12 个 AI Agent 组成的"朝廷"
好,让我把这套架构完整展开给你看。
你 (皇上) → 太子 (分拣) → 中书省 (规划) → 门下省 (审议)
│ 准奏 ✅ / 封驳 🚫
尚书省 (派发)
┌──┬──┬──┬──┬──┐
户 礼 兵 刑 工 ← 六部并行执行
部 部 部 部 部
│
尚书省 (汇总回奏)
12 个 Agent,不是随便起的名字------每一个都有精确的定位:
-
太子:消息的第一接收人,干的活说白了就是"前台分诊"------闲聊你自己回,正式旨意才建任务往下传
-
中书省:方案设计师,把笼统的需求拆解成可执行的子任务
-
门下省:质量守门员,从可行性、完整性、风险、资源四个维度审核,不合格直接封驳
-
尚书省:项目经理,把审核通过的方案派发给具体的"部门"去执行
-
六部(户礼兵刑工吏):干活的一线执行者,各有专长------兵部写代码,礼部写文档,户部搞数据,刑部做安全审计,工部负责 DevOps
你可能会问:搞这么复杂干嘛?直接让一个 Agent 干不就完了?
这就好比问"一个人全栈开发不就完了"------小项目可以,但凡复杂一点的任务,分工协作才是正道。而且关键不在于"分工"本身,而在于分工之间的制衡和审核。
设计哲学:为什么"门下省"才是整个架构的灵魂
我跟你讲一个真实的场景。
有次我下了一道旨:"帮我设计一个用户注册系统,要求 FastAPI + PostgreSQL + JWT 鉴权 + 完整测试 + 部署文档"。
中书省接到旨意后很快出了一份规划方案,把任务拆成了 5 个子任务。看上去挺完整对吧?
门下省一审,直接封驳了。
为啥?中书省的方案里漏了数据库迁移策略,没有考虑密码加密方案的选型,JWT 的刷新机制完全没提。门下省的审议意见写得很干脆:
🔍 门下省·审议意见
任务ID: JJC-20260301-003
结论: ❌ 封驳
问题:
1. 缺少数据库迁移策略(Alembic?手动脚本?)
2. 密码加密未指定方案(bcrypt/argon2/scrypt?)
3. JWT Token 刷新机制未设计,安全隐患
中书省被打回去之后修订了方案,再次提交,门下省第二轮审核通过------准奏。
这个流程在 CrewAI 里你做得到吗?在 AutoGen 里你做得到吗?
我对比过市面上主流的 Multi-Agent 框架:
| 能力 | CrewAI | AutoGen | MetaGPT | 三省六部 |
|---|---|---|---|---|
| 专职审核 | ❌ | ⚠️ 可选 | ⚠️ 可选 | ✅ 门下省强制审核 |
| 实时看板 | ❌ | ❌ | ❌ | ✅ 10 个功能面板 |
| 任务干预 | ❌ | ❌ | ❌ | ✅ 叫停 / 取消 / 恢复 |
| 流转审计 | ⚠️ | ❌ | ⚠️ | ✅ 完整奏折存档 |
| 崩溃恢复 | ❌ | ❌ | ❌ | ✅ 事件 ACK + 自动认领 |
"门下省"解决的不是一个技术问题,而是一个制度问题------在 Agent 的产出到达执行层之前,有一个强制的质量关卡。这就是为什么我的系统处理复杂任务时结果可靠:因为垃圾方案根本流不到下游。
深水区:状态机设计------让我头疼了整整一周
说完"为什么这么设计",来聊聊"怎么实现的"。这部分我掉了不少头发。
一个任务从诞生到完成,要经过一个严格的状态机:
STATE_TRANSITIONS = {
TaskState.Taizi: {TaskState.Zhongshu, TaskState.Cancelled},
TaskState.Zhongshu: {TaskState.Menxia, TaskState.Cancelled, TaskState.Blocked},
TaskState.Menxia: {TaskState.Assigned, TaskState.Zhongshu, TaskState.Cancelled},
TaskState.Assigned: {TaskState.Doing, TaskState.Next, TaskState.Cancelled, TaskState.Blocked},
TaskState.Doing: {TaskState.Review, TaskState.Done, TaskState.Blocked, TaskState.Cancelled},
TaskState.Review: {TaskState.Done, TaskState.Doing, TaskState.Cancelled},
TaskState.Blocked: {TaskState.Taizi, TaskState.Zhongshu, TaskState.Menxia, TaskState.Assigned, TaskState.Doing},
}
看着简单?让我解释一下几个让我纠结到失眠的设计决策:
第一个纠结:门下省的封驳到底跳到哪?
Menxia → Zhongshu ------封驳之后退回中书省。但问题来了:退回之后,中书省修订完再提交,是走第一轮审核的路径还是新开一轮?我最终的决定是用 review_round 字段记录轮次。并且设了一条硬性规则:最多 3 轮,第 3 轮强制准奏。
为什么?因为我见过太多代码审核里那种"改了再改、改了再改"的无限循环了。门下省的 SOUL.md 里写得很清楚:"最多 3 轮,第 3 轮强制准奏(可附改进建议)"。这不是偷懒,这是效率和质量之间的权衡。
第二个纠结:Blocked 状态可以跳到几乎任何地方?
TaskState.Blocked: {TaskState.Taizi, TaskState.Zhongshu, TaskState.Menxia, TaskState.Assigned, TaskState.Doing}
对,Blocked 是一个"万能复活点"。一个任务卡住了,可能是在中书省的阶段卡住了,也可能是在六部执行的时候卡住了。恢复的时候要跳回到正确的位置------这要求我必须记住"它是从哪个状态进入 Blocked 的"。
实现上我用了一个 _prev_state 字段:
if action in ('stop', 'cancel'):
task['_prev_state'] = old_state # 存起来,resume 时用
简单粗暴但管用。
让我最骄傲的设计:双通道事件总线
好,到了我最想跟你聊的部分了。这个设计解决了一个让我抓狂了好几天的问题。
问题背景 :旧版架构里,任务的派发靠的是 Python 的 daemon 线程。也就是说,server.py 启动后开几个后台线程,这些线程负责"看到任务状态变了就派发给对应的 Agent"。
问题在哪? kill -9 重启服务器的时候------线程没了。任务派了一半,中间状态断了,永久卡住。
这种场景你可能没遇到过,但在生产环境里这是日常。后台进程挂了、机器重启了、OOM 被系统干掉了------你的"正在处理中"的任务怎么办?
我的解决方案是引入 Redis Streams 事件总线:
async def publish(self, topic, trace_id, event_type, producer, payload, meta):
event = {
"event_id": str(uuid.uuid4()),
"trace_id": trace_id,
"timestamp": datetime.now(timezone.utc).isoformat(),
"topic": topic,
"event_type": event_type,
"producer": producer,
"payload": json.dumps(payload or {}, ensure_ascii=False),
"meta": json.dumps(meta or {}, ensure_ascii=False),
}
stream_key = self._stream_key(topic)
# 关键:XADD 写入 Stream,持久化
entry_id = await self.redis.xadd(stream_key, event, maxlen=10000)
# 同时发布到 Pub/Sub 频道,供 WebSocket 实时推送
await self.redis.publish(f"edict:pubsub:{topic}", json.dumps(event))
return entry_id
为什么是"双通道"?
你仔细看------每次发布事件,我干了两件事:
-
XADD 到 Redis Stream:持久化存储,配合消费者组(Consumer Group)和 ACK 机制,保证事件不丢失
-
同时 PUBLISH 到 Redis Pub/Sub:零延迟推送给 WebSocket 客户端,让前端看板实时更新
为什么不只用 Stream?因为 XREADGROUP 是阻塞轮询,延迟在毫秒到秒级别,对看板的实时性要求来说不够快。
为什么不只用 Pub/Sub?因为 Pub/Sub 是火后即忘------如果消费者不在线,消息直接丢了。Worker 崩溃后重启,那些没处理的事件?没了。
Stream 保证可靠性,Pub/Sub 保证实时性,两个通道各干各的活。
这就像收快递------Stream 是快递柜(包裹放里面等你取,你不取它就一直在),Pub/Sub 是快递员打电话通知你(你接了就知道有快递,没接就错过了,但包裹还在柜子里)。
崩溃恢复:那个让我半夜从床上爬起来的 Bug
有了 Stream 还不够。我遇到过一个真实的生产 Bug:
Orchestrator Worker 处理一个事件处理到一半------数据库连接断了。事件已经被 XREADGROUP 读出来了(从 pending 列表里移走了),但还没有 ACK(没有确认消费成功)。Worker 崩溃重启后,这个事件处于一种"薛定谔的状态"------被读了但没被确认。
如果不处理,这个任务就永远卡在那了。
我的解决方案是 Worker 启动时的 pending 事件恢复机制:
async def _recover_pending(self):
"""恢复崩溃前未 ACK 的事件。"""
for topic in WATCHED_TOPICS:
events = await self.bus.claim_stale(
topic, GROUP, CONSUMER, min_idle_ms=30000, count=50
)
if events:
log.info(f"Recovering {len(events)} stale events from {topic}")
for entry_id, event in events:
await self._handle_event(topic, entry_id, event)
claim_stale 底层用的是 Redis 的 XAUTOCLAIM 命令------"把那些超过 30 秒还没被 ACK 的事件,全部认领过来重新处理"。
Worker 启动 → 先恢复上次遗留的事件 → 再开始正常轮询。简单,优雅,可靠。
旧架构里的启动恢复就更"暴力"了:
def _startup_recover_queued_dispatches():
"""服务启动后扫描 lastDispatchStatus=queued 的任务,重新派发。"""
tasks = load_tasks()
for task in tasks:
sched = task.get('_scheduler') or {}
if sched.get('lastDispatchStatus') == 'queued':
dispatch_for_state(task_id, task, state, trigger='startup-recovery')
直接扫描所有任务,看哪些的派发状态是 "queued"(入队了但没完成)------全部重新派发。用最笨的方法解决最棘手的问题。
并发写入:12 个 Agent 同时操作一个 JSON 文件怎么办?
这是另一个让我掉头发的问题。
旧版架构里,所有任务数据存在一个 tasks_source.json 文件里。12 个 Agent 可能同时通过 kanban_update.py 脚本更新这个文件。
你会怎么做?加数据库?上 PostgreSQL?
我的做法是------文件锁 + 原子写入:
def atomic_json_update(path, modifier, default=None):
lock_file = _lock_path(path)
fd = os.open(str(lock_file), os.O_CREAT | os.O_RDWR)
try:
fcntl.flock(fd, fcntl.LOCK_EX) # 排他锁
data = json.loads(path.read_text()) # 读
result = modifier(data) # 改
# 先写到临时文件,再 rename 过去------保证原子性
tmp_fd, tmp_path = tempfile.mkstemp(dir=str(path.parent))
with os.fdopen(tmp_fd, 'w') as f:
json.dump(result, f, ensure_ascii=False, indent=2)
os.replace(tmp_path, str(path)) # 原子替换
return result
finally:
fcntl.flock(fd, fcntl.LOCK_UN)
os.close(fd)
三层保护:
-
fcntl.flock 排他锁:同一时间只有一个进程能写
-
读-改-写在同一把锁内完成:避免 TOCTOU(Time-of-check to time-of-use)竞态
-
tmpfile + os.replace:先写临时文件再原子重命名,即使写入过程中崩溃,原文件也不会被破坏
你会问:为什么不直接用数据库?
因为旧版架构的设计哲学就是零依赖 。server.py 只用 Python 标准库------http.server、json、pathlib,一个第三方依赖都没有。在很多部署环境里(比如轻量级 VPS、Docker 容器内),你不想也不需要拉一个 PostgreSQL 进来。
当然,新版 Edict 2.0 引入了 PostgreSQL + Redis,那是另一个故事了。架构演进不是推倒重来,是在对的时间做对的升级。
旨意清洗:你不知道 Agent 能把标题搞得多脏
这个模块我本来觉得是个小活儿,结果花的时间比我预想的多了三倍。
事情是这样的:太子 Agent 负责接收皇上(也就是我)的消息,然后创建任务。但你知道 AI Agent 有一个毛病------它特别喜欢把各种乱七八糟的元数据塞进文本里。
我试过直接让太子把我的飞书消息当标题,结果看板上出现了这样的任务标题:
传旨(/Users/bingsen/.openclaw/workspace-taizi/sessions/xxx):看看这个项目
???
文件路径、session ID、Conversation info 块,什么都塞进来了。看板上简直没法看。
于是我写了一个标题清洗管道:
def _sanitize_text(raw, max_len=80):
t = (raw or '').strip()
# 砍掉 Conversation info 后面的所有元数据
t = re.split(r'\n*Conversation\b', t, maxsplit=1)[0].strip()
# 砍掉代码块
t = re.split(r'\n*```', t, maxsplit=1)[0].strip()
# 砍掉文件路径(各种后缀)
t = re.sub(r'[/\\.~][A-Za-z0-9_\-./]+(?:\.(?:py|js|ts|json|md|sh|yaml))?', '', t)
# 砍掉 URL
t = re.sub(r'https?://\S+', '', t)
# 砍掉"传旨/下旨"前缀
t = re.sub(r'^(传旨|下旨)([((][^))]*[))])?[::\uff1a]\s*', '', t)
# 砍掉系统元数据(message_id, session_id 等)
t = re.sub(r'(message_id|session_id|chat_id)\s*[:=]\s*\S+', '', t)
# 合并空白,截断
t = re.sub(r'\s+', ' ', t).strip()
if len(t) > max_len:
t = t[:max_len] + '...'
return t
还不够!光清洗还不行,还得校验。有些消息本质上就不是旨意------比如"好"、"?"、"ok"、"知道了"。这些如果被创建成任务,看板上就会出现一堆莫名其妙的空气任务。
_JUNK_TITLES = {
'?', '?', '好', '好的', '是', '否', '不', '不是', '对', '了解', '收到',
'嗯', '哦', '知道了', '可以', 'ok', 'yes', 'no', '测试', '试试',
}
def _is_valid_task_title(title):
t = (title or '').strip()
if len(t) < 6:
return False, f'标题过短({len(t)}<6字),疑似非旨意'
if t.lower() in _JUNK_TITLES:
return False, f'标题 "{t}" 不是有效旨意'
if re.fullmatch(r'[\s??!!.。,,...·\----~]+', t):
return False, '标题只有标点符号'
if re.match(r'^[/\\~.]', t):
return False, f'标题看起来像文件路径'
return True, ''
这套清洗 + 校验的组合拳下来,看板终于干净了。垃圾标题直接被拒,Agent 收到明确的拒绝理由。
这种"脏活"写起来不酷,但它直接决定了用户体验。看板上的每一条任务标题,都是清洗管道的产出。
SOUL.md:给每个 Agent 写一份"员工手册"
这是我在这个项目里最有成就感的创新之一。
每个 Agent 有一个 SOUL.md 文件------它不是简单的 system prompt,而是一份完整的角色人格 + 工作流规则 + 输出规范 + 看板操作手册。
拿门下省的 SOUL.md 举个例子。它规定了审议框架:
审议四维度:可行性、完整性、风险、资源
并且明确了输出格式------不是让 Agent 自由发挥,而是告诉它"你的输出长这个样":
🔍 门下省·审议意见
任务ID: JJC-xxx
结论: ✅ 准奏 / ❌ 封驳
问题: [如有,列出具体问题]
甚至规定了什么时候必须上报进展 ------开始审议时、发现问题时、审议完成时,每个关键节点都必须调用 kanban_update.py progress 命令更新看板。
# 审查过程中
python3 scripts/kanban_update.py progress JJC-xxx \
"可行性通过,正在检查子任务完整性" \
"可行性审查✅|完整性审查🔄|风险评估|资源评估|出具结论"
这有什么好处?
Agent 的行为变得可预测了。 你知道门下省收到方案后一定会做四维度审核,你知道它产出的结论一定是准奏或封驳,你知道看板上一定能看到它当前审查到哪个维度了。
这跟"让 AI 自由发挥"是完全不同的理念。自由发挥适合创作,不适合工程。
四阶段调度策略:任务卡住了怎么办?
生产环境里,任务卡住是家常便饭。Agent 调用的 LLM 超时了、API 返回了错误、Agent 进程被 OOM 杀了------各种原因。
我设计了一套四阶段自动恢复策略:重试 → 升级 → 回滚 → 人工介入。
def handle_scheduler_scan(threshold_sec=180):
for task in tasks:
sched = _ensure_scheduler(task)
stalled_sec = (now - last_progress).total_seconds()
if stalled_sec < threshold_sec:
continue
retry_count = sched.get('retryCount', 0)
max_retry = sched.get('maxRetry', 1)
level = sched.get('escalationLevel', 0)
# 阶段1:重试
if retry_count < max_retry:
sched['retryCount'] = retry_count + 1
dispatch_for_state(task_id, task, state, trigger='taizi-scan-retry')
continue
# 阶段2:升级(让更高级别的 Agent 介入)
if level < 2:
target = 'menxia' if level == 0 else 'shangshu'
sched['escalationLevel'] = level + 1
wake_agent(target, f'任务 {task_id} 停滞,请介入')
continue
# 阶段3:自动回滚到上一个稳定状态
if sched.get('autoRollback', True):
snapshot = sched.get('snapshot', {})
task['state'] = snapshot.get('state')
# 重置计数器,重新开始
为什么这样分阶段?
想象一下你是项目经理。一个开发者的任务卡住了,你会怎么做?
-
先让他重试------也许只是临时的网络问题
-
找人帮忙------叫 Tech Lead 看看是不是方案有问题
-
回退到上一个版本------至少回到一个可用状态
-
上报老板------人工介入
我的调度策略就是这个逻辑的代码化。每个阶段都有对应的操作,每个操作都记录在 flow_log 里,事后可以完整审计。
这里还有一个细节你可能注意到了------快照(snapshot)机制。在每次关键状态转换之前,我会保存当前状态的快照:
def _scheduler_snapshot(task, note=''):
sched = _ensure_scheduler(task)
sched['snapshot'] = {
'state': task.get('state', ''),
'org': task.get('org', ''),
'now': task.get('now', ''),
'savedAt': now_iso(),
'note': note,
}
有了快照,回滚就有目标了------不是瞎跳,而是回到上一个"确认健康"的状态。
前端管道可视化:一眼看清任务走到哪了
看板的核心需求是一眼就知道每个任务现在在哪、谁在处理、什么进度。
我设计了一个 Pipeline 可视化组件,原理很简单但效果很好:
export const PIPE = [
{ key: 'Inbox', dept: '皇上', icon: '👑', action: '下旨' },
{ key: 'Taizi', dept: '太子', icon: '🤴', action: '分拣' },
{ key: 'Zhongshu', dept: '中书省', icon: '📜', action: '起草' },
{ key: 'Menxia', dept: '门下省', icon: '🔍', action: '审议' },
{ key: 'Assigned', dept: '尚书省', icon: '📮', action: '派发' },
{ key: 'Doing', dept: '六部', icon: '⚙️', action: '执行' },
{ key: 'Review', dept: '尚书省', icon: '🔎', action: '汇总' },
{ key: 'Done', dept: '回奏', icon: '✅', action: '完成' },
];
export function getPipeStatus(t: Task): PipeStatus[] {
const stateIdx = PIPE_STATE_IDX[t.state] ?? 4;
return PIPE.map((stage, i) => ({
...stage,
status: (i < stateIdx ? 'done' : i === stateIdx ? 'active' : 'pending'),
}));
}
每个任务在看板上有一条 8 段管道,已完成的高亮、当前活跃的闪烁、待处理的灰显。一眼扫过去,所有任务的进度状态一目了然。
这比你去翻日志、查数据库、问 Agent "你现在在干嘛"强太多了。
权限矩阵:不是想给谁发消息就能发
这是"三省六部"跟其他 Multi-Agent 框架最本质的区别之一。
| From ↓ \ To → | 太子 | 中书 | 门下 | 尚书 | 六部 |
| 太子 | --- | ✅ | | | |
| 中书省 | ✅ | --- | ✅ | ✅ | |
| 门下省 | | ✅ | --- | ✅ | |
| 尚书省 | | ✅ | ✅ | --- | ✅ |
| 六部 | | | | ✅ | |
六部只能给尚书省报告,不能直接找中书省,更不能跳过所有人去找太子。
为什么要这么严格?
因为我见过太多 Multi-Agent 系统里 Agent 之间"串通"的情况------执行 Agent 不满意方案,直接去找规划 Agent 私聊改方案,绕过了审核层。这在人类组织里叫"越级汇报",在 AI 系统里就是系统性风险。
权限矩阵确保信息沿着制度化的路径流转,任何绕道行为在架构层面就不可能发生。
双架构并存:新旧系统怎么和平共处?
这是一个很现实的工程问题。
旧版系统(基于 JSON 文件 + Python stdlib)已经在生产跑了一段时间,上面有历史数据、有在用的流程。新版 Edict 2.0(FastAPI + PostgreSQL + Redis)性能更好、更可靠,但你不能说切就切。
我的做法是兼容路由:
新版 API 提供 by-legacy/{legacy_id} 端点,可以用旧版的 JJC-xxx ID 查询任务。旧版的 kanban_update.py 脚本继续工作,数据同时写入 JSON 文件(供旧版读取)和通过 API 同步到新版数据库。
架构升级不是一刀切,是渐进式迁移。 像换飞机引擎------你得在飞机飞着的时候换。
这套架构教会我的三件事
做完这个项目,有三个认知上的收获,我觉得比代码本身更有价值:
1. 制度比技术更重要
CrewAI 的底层用了多先进的 LLM 编排技术?AutoGen 的对话管理有多精妙?不重要。没有审核机制,再好的技术也挡不住垃圾产出。
唐太宗设计三省六部制的时候,没有编程语言,没有分布式系统,但他的制度设计比今天绝大多数 AI 框架都高明------因为他抓住了核心:权力必须受到制约。
2. 可观测性是信任的基础
你敢不敢把一个复杂任务交给一堆 AI Agent 然后去睡觉?
如果你的系统有实时看板、有完整的流转日志、有任务干预能力------你敢。因为即使出了问题,你也能第一时间发现并处理。
可观测性不是"最好有",是"没有就不能用"。
3. 古人的智慧被严重低估了
三省六部制存在了 1400 年,从唐朝一直沿用到清末。一个制度能延续这么久,说明它解决的是人类协作中的根本问题------分权、制衡、审核、可追溯。
这些问题不会因为协作主体从人变成了 AI 就消失。恰恰相反,AI Agent 的不可预测性比人类更强,更需要制度化的约束。
未来的坑和机会
写到这里,也聊聊还有什么没做完的。
功过簿(Agent 绩效评分体系):哪个 Agent 经常被封驳?哪个 Agent 的产出质量最高?建立量化评估体系,为未来的 Agent 模型选择提供数据支撑。
御批模式:目前门下省是 AI 自动审核,接下来要加入 Human-in-the-loop------某些关键决策需要人工拍板。看板上一键"准奏"或"封驳",把人的判断力和 AI 的执行力结合起来。
急递铺(Agent 间实时消息流可视化):目前 Agent 之间的通信是看不到的,只能通过看板上的状态变化间接推断。要做到像调试网络流量一样,能看到每一条 Agent 间的消息------谁发给谁、什么内容、花了多长时间。
写在最后
回到开头的故事------那个让我崩溃的深夜。
现在的我,再也不会遇到三个 Agent 各干各的、产出互相矛盾的情况了。因为在我的系统里:
-
中书省写完方案,必须过门下省这一关
-
门下省觉得不行,直接打回重做
-
通过了才到尚书省派发
-
六部执行过程中看板全程可见
-
卡住了有自动恢复机制
-
出了问题随时可以叫停
这不是技术的胜利,是制度的胜利。
唐太宗要是活到现在,看到我用他的制度来管 AI,大概会说一句:
"朕早就说过了。"
项目开源地址:github.com/cft0808/edict
如果这篇文章对你有启发,欢迎 Star。有问题或者想讨论的,评论区见。
