通爻 Bridge 是薄中继架构:Server 持有全部解释权,Worker 只上报执行事实。
下面是一个需求经历的完整管道——从用户触发到产物落盘。
以“用户通过 MCP 客户端发出一个需求”为起点,追踪每个步骤、每个 API 调用、每个状态转移。
用户通过 MCP 工具、网页 UI 或直接调用 Protocol API 提交需求。需求可以是一段自然语言描述。
# MCP 工具towow_formulation_start(scene='ai-gig-market')# 或直接调用 APIPOST /protocol/formulations{ "scene_id": "ai-gig-market" }
系统通过多轮 SSE 流式对话,帮用户澄清需求细节。完成后用户调用 confirm,触发下一阶段。
# 多轮 SSE 对话POST /protocol/formulations/{id}/reply{ "message": "我需要一个会 Python 的..." }# 确认,触发 DiscoveryPOST /protocol/formulations/{id}/confirm{ "start_negotiation": true }
纯向量计算,不调用 LLM。将需求和所有 Agent Profile 编码为 D1~D5 五个语义维度,通过 6 个算子计算匹配分,生成 Nominations。GT Recall 基线 98.65%。
# 产出 Nomination 列表GET /protocol/nominations/{id}{"candidates": [{ "agent_id": "...", "score": 0.91 },{ "agent_id": "...", "score": 0.87 }],"dimensions": { "d1": 0.9, "d2": 0.85 }}
Server 根据 Nominations 选出参与者,组装 task_package:包含需求方 Profile、参与者 Profile、Prompt 版本配置。Run 状态进入 pending,等待 Bridge 领取。
{"run_id": "abc-123","scene_id": "ai-gig-market","formulated_demand": "需要一位...","demand_owner": {"id": "u001", "profile_text": "..."},"participants": [{ "id": "a001", "profile_text": "..." }],"prompt_versions": { "catalyst": "v1" }}
Bridge 节点每隔固定间隔轮询 /api/bridge/pending。发现 pending run 后,调用 accept 锁定任务,开始发送定期心跳。Server 收到 accept 后,将 run 状态更新为 running。
GET /api/bridge/pending每 5s 轮询POST /api/bridge/accept锁定任务POST /api/bridge/heartbeat每 30s 保活POST /api/bridge/events进度上报POST /api/bridge/complete任务完成Bridge 将 task_package 展开为本地文件(owner.md, participants/*.md, pipeline_config.json),然后启动 Claude CLI 子进程执行协商流。监听 output/ 目录新文件作为进度信号。
# 写工作区文件workdir/owner.mdparticipants/a001.mdpipeline_config.jsonoutput/ # 监听此目录# 启动 Claude CLIclaude -p '{prompt}' \--output-format json \> workdir/output/bridge_output.json
Bridge 持续扫描 output/ 目录,发现新文件即上报。只转发 raw facts(文件名 + 内容),不解释语义。Server 端负责将 bridge.output_file 事件翻译为业务进度。
POST /api/bridge/events{"run_id": "abc-123","event_type": "bridge.output_file","payload": {"filename": "round_1_catalyst.md","content": "# 第一轮协商结果\n..."}}# Server 翻译为业务事件# WS → 前端: { progress: 33% }
Claude CLI 退出后,Bridge 读取 bridge_output.json,原样 POST 给 Server。Worker 职责结束。成功标准:exit_code == 0 且 bridge_output.json 存在。否则报告 failed + stderr。
POST /api/bridge/complete{"run_id": "abc-123","exit_code": 0,"output": {"endpoint": "# 联系方式\n...","delivery": "# 交付计划\n...","plan": "# 协作方案\n..."}}
Server 收到 complete 后,解析 output bundle 为 Artifacts(endpoint / delivery / plan),判定 verdict,更新 run 状态,推送 WebSocket 通知,写入 inbox。所有业务语义在这里产生。
{"run_id": "abc-123","status": "completed","artifacts": [{ "type": "endpoint","content": "# 联系方式..." },{ "type": "delivery","content": "# 交付计划..." },{ "type": "plan","content": "# 协作方案..." }]}
Inbox 通知 + /runs/{run_id}/result 页面
Bridge 节点与 Server 通过 HTTP 直连,绕过 ICP 限制。MCP 客户端通过 Cloudflare Workers 反代接入。
所有 Bridge 改动必须符合这 5 条规则。不需要逐次审查代码即可判断方向是否正确。
如果一段 worker 代码需要理解输出内容的含义,它就写错了地方。Worker 只知道「文件名」和「退出码」,不知道它们意味着什么。
不管是文件名模式、artifact 类型、还是 event 含义,只能在一个地方定义。散布定义是 bridge 复杂度爆炸的根源。
不做 partial_success 抢救、不生成 placeholder、不从失败 stdout 里猜内容。这些如果需要,由 Server 决定,不是 Worker 的职责。
本地必须能用 fake CLI + 真实 HTTP backend 跑完整链。任何只有在生产才能发现的问题,都意味着本地集成环境不够完整。
开闭原则的具体体现。Server 是语义解释的扩展点,Worker 是封闭的事实上报器。Worker 改动越少,Bridge 越稳定。