一个 AI 产品上线后最怕的不是"出 bug",而是"出 bug 了但不知道出在哪"。尤其是多智能体流水线,一次生成要经过 analyzer → tool → synthesizer → reviewer → writer 五步,任何一步卡住,用户只看到一个转圈。
在可观测 和部署两件事上都做了工程化设计,让"出问题能定位、发版本能一键"。
一、全链路追踪:把决策路径变成一棵树
有一个 Tracer(追踪器),把每一次请求在 Agent 内部的决策路径 沉淀成一棵可回放的树:
analyzer(分析)
├─ tool(确定性计算,调后端)
├─ synthesizer(LLM 综合)
├─ reviewer(LLM 复核)
└─ writer(LLM 成稿)
实现上很轻量:
- 通过
contextvars(协程上下文变量)在单次请求内传递 Tracer,不用手动传参; - LLM 包装层(
patch.py)自动读取并埋点,业务代码只需在关键节点调mark_phase/record_step; - 每个节点是一个
Span(跨度),记录kind(phase / llm / tool / error)、耗时、状态、错误信息。
最关键的哲学:无 Tracer 时所有 API 都是 no-op(空操作) 。离线脚本、缓存回放场景下调这些函数不会报错,更绝不拖垮主流程------观测是"锦上添花",不是"命门"。
一次线上排障实例
某次用户反馈"综合报告一直转圈不出"。工程师拉出这次请求的 trace 树:
go
analyzer ok 12ms
tool ok 88ms
synthesizer ok 420ms
reviewer error 0ms ← 报错:"timeout calling llm"
writer (未执行)
一眼就看出是 reviewer 这一步调模型超时,而不是前面计算或分析的问题。直接定位到 reviewer 的超时配置,调大后恢复正常------如果没有这棵树,你只能盲猜"是不是模型挂了",然后在十几个可能的环节里逐个试错,耗时可能是现在的十倍。
这就是可观测的价值:它把"玄学排障"变成"看树定位"。
为什么可观测是生产的命脉
很多团队把可观测当成"锦上添花",上线后才发现:没有追踪,每次线上异常都得靠"复现 + 猜"。而 AI 应用的不确定性更高------同样的输入,模型这次行、下次崩,没有决策树你根本分不清是"哪一步"出的幺蛾子。把 Tracer 做成"无则 no-op"的轻量设施,接入成本极低,收益却是每次排障从小时级降到分钟级。
二、SSE 流式:边算边给用户看
生成不是"算完再给",而是流式输出(SSE,Server-Sent Events)。home_agent 流式接口 yield 一系列事件:
arduino
open → tool_start(系统自动计算)→ delta(逐字输出)→ meta(模型/降级信息)→ done
而且流式输出里也嵌了合规清洗:URL 跨 chunk 时先入缓冲再按安全边界切出,防外链漏出。流式 + 追踪结合,用户看到的是"实时思考过程",工程师看到的是"完整决策树"。
三、monorepo + subtree + Vercel:三端一起好发
是三端解耦 的:前端(Next.js)、后端(FastAPI)、AI 服务(LangGraph),各自独立运行。但它们又放在同一个大仓库里管理。
部署用了一套巧妙的组合:
- 主仓库管理
oraclemind-frontend/oraclemind-backend/oraclemind-ai三个子目录; - 通过
git subtree把每个子目录同步到对应的 GitHub 独立仓(仅作 Vercel 部署镜像); - Vercel 直接连 GitHub 独立仓部署,零改动。
好处:本地一份代码、三端一起改、一起提交;部署时各端独立镜像、互不干扰。不用维护三套 git 仓库的同步脚本。
subtree 回推命令示例
bash
# 首次回推前端到 GitHub(供 Vercel 部署)
git remote add gh-frontend git@github.com:wufan0312/oraclemind-frontend.git
git subtree push --prefix=oraclemind-frontend --squash gh-frontend main
# 后端 / AI 同理,remote 为 gh-backend / gh-ai
部署的三个"静默坑"
Vercel 部署有三条容易踩又不易察觉的坑(踩过并记进了 docs/deployment.md):
- 面板空串变量盖掉
.env.production:在 Vercel 面板建了变量却留空,比不建更危险------构建期内联出"",把本地配好的值覆盖成空串。 .vercelignore的.env.*误排分层配置 :如果写成.env.*,连.env.production一起排除,导致线上读不到生产配置。正确写法是精确列举。- 改面板变量不触发部署:Vercel 只对 push commit 自动部署,改面板环境变量后必须手动 Redeploy,否则旧代码旧配置继续跑。
这三条坑的共同点是"静默"------不会报错,只是悄悄不对。可观测 + 规范部署,正是为了把这些"看不见的错"挡在门外。
四、一套架构支撑多业务线
产品层还有一个技术亮点------一套架构支撑多条业务线:
技术上通过 report_type 注册制 + track 字段隔离不同业务线的能力,让同一套架构能跑合规要求不同的多条产品线。每条业务线要守的红线不同(比如一条要守"诱导消费"红线,另一条要守医疗边界与 GDPR)。把它们抽象成"可注册的 report 类型",新增一条业务线不用改主干。
五、一句话总结
全链路 Tracer 把"哪一步坏了"变成可回放的树,SSE 让过程对用户可见;monorepo + subtree + Vercel 让三端发布又统一又独立;report_type 注册制让一套架构支撑多条业务线。 可观测解决"出问题能定位",部署解决"发版本能一键",两者合起来才是"能长期运维的生产系统"。
代码锚点
- 决策树追踪:
oraclemind-ai/src/harness/observability/tracer.py/patch.py/sse.py- 部署规范:
docs/deployment.md;路线图:docs/roadmap.md