主题
a-cdm 二开实现合理性审计报告
审计师:资深源码架构审计师(脚本式执行,读源码直接定性) 日期:2026-05-18 · a-cdm 快照
07b3469· 冻结基线 = 上游898f4e8(2026-04-17 12:00) 上游最新参照:~/repos/deer-flow main(898f4e8..HEAD= 199 提交,仅作概念地图)本报告只读代码,只产出本文件,未改任何代码。
1. 执行结论
一句话定性:a-cdm 是一次架构纪律罕见地好的深度二开 —— 全部定制收敛在"上游目录级不存在的新增目录"与"两条 HTTP 契约 + 一个零代码共享的控制面"上,鉴权用 LangGraph SDK 官方扩展点、Pipeline 复用 LangGraph 原生 StateGraph、工具走 deer-flow 原生 tools[].use 扩展点、前端 Agent 对话完整复用 deer-flow useStream。造轮子极少;真正的弯路只有 2 处局部代码不一致(ba_report.agent_runner 绕开 deer-flow agent 工厂、ba_expert_stream 手拼协议不复用同仓 SDK 封装),且团队已主动把第一处废弃、收敛回原生 lead_agent。
| 维度 | 评分(0-10) | 理由 |
|---|---|---|
| 能力复用度 | 9 | SDK 官方 Auth 扩展点、LangGraph StateGraph 多图注册、deer-flow create_deerflow_agent/sandbox/models.factory/skills/tools[].use/Gateway POST /api/agents、前端 useStream 全部被正确复用。扣 1 分:ba_report.agent_runner 用裸 create_react_agent 绕开 create_deerflow_agent,丢掉 18 个 middleware,需手动管 sandbox。 |
| 实现合理性 | 9 | 自建的(owner_sub 隔离、确定性 Pipeline、Agent-Tools BFF、可逆 DB/saga、L1/L2 缓存、ai_registry)全部是 deer-flow 冻结版确无能力的合理自建,且职责分层清晰(引擎无状态算、BFF 有状态编排、harness 不碰业务 DB 有 CI 防火墙强制)。扣 1 分:同仓两套"连引擎"方式并存(SDK client vs raw httpx),代码一致性欠债。 |
| 弯路严重度 | 2(越低越好) | 唯一侵入上游核心文件的是 lead_agent/prompt.py 植入 ~300 行(deer-flow 确无 prompt 注入扩展点,属无奈但真实冲突面)+ acdm_thread_auth.py 经 Depends() 注入 3 个上游 router(无法走 SDK Auth,因这些端点不经 Aegra,属必要补丁非弯路)。无大规模重造、无与引擎打架的并行系统。 |
2. 方法论与置信度声明
- 判定基线 = 冻结版上游
898f4e8(2026-04-17,a-cdm fork 点)。所有"deer-flow 本来有没有这能力"一律以git show 898f4e8:<path>/git ls-tree 898f4e8取 ground truth,不拿上游最新版苛求 a-cdm。两份 code-wiki 仅作概念地图。 - 关键基线事实(实测,推翻了背景报告的一个隐含前提):冻结点
898f4e8上游完全没有任何鉴权/Auth 能力 ——backend/app/gateway/langgraph_auth.py是上游94eee95f(2026-04-26,晚于 fork 点 9 天)才引入的(#2008);git merge-base --is-ancestor 94eee95f 898f4e8返回 false;冻结版langgraph.json无auth字段。因此 a-cdm 自建 owner_sub 鉴权时,上游零鉴权能力可借,这是后续多条判定的前提。 - 三档置信度:【确证】= 双方源码/扩展点 API/git ground truth 实锤;【合理推断】= 证据强但未逐行;【存疑】= 无法干净归因,不下定论。
- 平衡原则:deer-flow 冻结版确无能力或无干净扩展点而自建的,一律认定为合理自建,不计为弯路。
- 与背景交叉报告的关系:本报告不重复其"漂移 caveat / 三大新增目录清单",而是逐点做"实现方式合不合理"的定性,并对其建议 #3(消除 acdm_thread_auth 侵入)给出修正(见 §3.1)。
3. 逐能力点审计
3.1 owner_sub 鉴权隔离 + acdm_thread_auth.py 侵入
① 业务需求:多租户按 SSO owner_sub 隔离 thread/run/store;admin 跨用户访问;紧急降级开关。
② 冻结版 deer-flow 能力:【确证】冻结点 898f4e8 完全无鉴权层 —— harness/deerflow/auth/ 目录不存在,app/gateway/langgraph_auth.py 不存在(上游 2026-04-26 才引入),langgraph.json 无 auth 字段。唯一可借的是 LangGraph SDK 自带的 langgraph_sdk.Auth 扩展点(SDK 包级能力,与 deer-flow harness 无关,冻结版 pyproject.toml 已依赖 langgraph-sdk>=0.1.51)。
③ a-cdm 实际做法:【确证】
deer-flow/backend/packages/harness/deerflow/auth/acdm_auth.py:31from langgraph_sdk import Auth,用@auth.authenticate/@auth.on.threads.create/@auth.on.threads/@auth.on.store官方装饰器(acdm_auth.py:57-186);由aegra.json/langgraph.json的auth.path加载,server-agnostic(LangGraph Server 0.7 + Aegra 0.9 都兼容)。创建 thread 时服务端强制覆盖metadata.owner_sub = ctx.user.identity防伪造(:111-127);降级开关ACDM_THREAD_AUTH_ENABLED(:38-44);admin 不走 bypass,改走独立 admin API。deer-flow/backend/app/gateway/acdm_thread_auth.py:新文件,提供require_thread_ownerFastAPI 依赖,被上游routers/threads.py:26、uploads.py:12、artifacts.py:10以_: None = Depends(require_thread_owner)注入(threads.py:232/uploads.py:98,226,248/artifacts.py:90)。其 docstring(acdm_thread_auth.py:3-26)明确解释:这 3 个端点是 Gateway(8001)自有、不经 LangGraph Server/Aegra(2024),SDK Auth 物理上覆盖不到。
④ 判定:
- acdm_auth.py owner_sub 隔离:【合理利用】(满分范式) —— 用 SDK 官方 Auth 扩展点而非改上游代码,server-agnostic,带降级开关,服务端覆盖防伪造。【确证】
- acdm_thread_auth.py 侵入 3 个上游 router:【绕弯路(轻微,且无可避免)】 —— 是真实的上游文件侵入(改了函数签名加
Depends),cherry-pick 风险点;但 必须修正背景报告建议 #3:这 3 个端点不经 Aegra,acdm_auth.py 的 SDK Auth 物理上拦不到它们,所以"统一收敛到 acdm_auth 扩展点"在此不成立(两个进程/两个端口)。这属于 deer-flow 没给 Gateway 自有端点提供鉴权扩展点而 a-cdm 不得不打的必要补丁,侵入面已压到最小(每文件 1 import + 1 行 Depends)。
⑤ 置信度【确证】。建议:把 3 处 Depends 收敛为一个 FastAPI APIRouter 级 dependencies=[...] 或中间件(仍是侵入但集中到 1 处 import,降 cherry-pick 面);并落实背景报告建议 #1 —— 加 CI 断言 langgraph.json/aegra.json 的 auth.path == acdm_auth.py(实测当前无此断言,只有 test_ba_report_pipeline_env.py 的存在性检查),防 cherry-pick 静默回退鉴权造成越权。
3.2 确定性 Pipeline(weekly_report / meeting_aggregator(_realtime) / ba_report)
① 业务需求:固定流程、不需 LLM 自主决策的任务(周报、跨会议聚合、BA 8 步),要稳定复现 + 共用 thread 持久化。
② 冻结版 deer-flow 能力:【确证】冻结点 harness/deerflow/pipelines/ 目录不存在;langgraph.json graphs 只有单一 lead_agent。但 LangGraph 框架本身(非 deer-flow harness)原生支持 langgraph.json graphs 段注册多图、StateGraph 编译、interrupt_before human-in-loop、顶层 checkpointer 自动注入 —— 这些是 LangGraph 平台能力,deer-flow 只是没用上多图而已。
③ a-cdm 实际做法:【确证】
pipelines/__init__.py:1-6自述"确定性 LangGraph 工作流,与 agents 平级,共用 LangGraph StateGraph 基建"。weekly_report/pipeline.py:15-54:纯langgraph.graph.StateGraph线性 DAG,make_pipeline(config)工厂签名对齐langgraph.json注册,不自设 checkpointer(注释:52-53明说让 LangGraph Server 顶层 checkpointer 自动注入)。ba_report/pipeline.py:141-243:StateGraph+ 原生graph.compile(interrupt_before=[...])做 8 步 human-in-loop,节点名 = skill 目录名。- 全部注册进
langgraph.jsongraphs(5 项)+aegra.jsongraphs(5 项),通过标准/threads/{id}/runs+assistant_id触发。
④ 判定:【合理利用】 —— a-cdm 没有另造任何工作流引擎,完全复用 LangGraph 原生 StateGraph + 多图注册 + interrupt_before + 顶层 checkpointer。"Pipeline"只是 a-cdm 给"非 agent 确定性图"起的命名分层,与 agent 共用全部 LangGraph 基建。这是教科书级的"用框架既有能力"。冻结版 deer-flow 没有 pipeline 概念不是 a-cdm 的锅 —— 它用的是 LangGraph 平台本就支持、deer-flow 恰好没用的多图能力。
⑤ 置信度【确证】。改进建议:无;保持。
3.3 ba_report 步骤执行器(agent_runner / skill_runner)— 唯一明确的造轮子/绕弯路
① 业务需求:BA 报告每步用 LLM + 工具(读写文件、KB 检索)跑一个 agent。
② 冻结版 deer-flow 能力:【确证】冻结版提供 create_deerflow_agent(agents/factory.py:61,SDK 级 agent 工厂,签名 (model, tools, system_prompt, middleware, extra_middleware, features),docstring 自述"sitting between raw create_agent and config-driven make_lead_agent"),自带 deer-flow 中间件链(sandbox 生命周期、tool error handling、dangling tool call、clarification 等 18 个)。还提供 deerflow.sandbox、deerflow.models.factory.create_chat_model、skills 加载、kb_search_tool。
③ a-cdm 实际做法:【确证】ba_report/agent_runner.py:30 from langgraph.prebuilt import create_react_agent,:220 用裸 create_react_agent 建 agent;注释 :229-230 自承"create_react_agent 不支持 middleware,所以我们需要手动 acquire/release sandbox"(:234-322 手写 sandbox 生命周期)。部分复用:create_chat_model(:34)、deerflow.sandbox(:234)、kb_search_tool(:36)、skills 路径约定(skill_runner.py:124-151)。
④ 判定:【绕弯路 / 部分造轮子】 —— deer-flow 冻结版明确提供了 create_deerflow_agent 这个正是为"裸 create_agent 与 make_lead_agent 之间"设计的 SDK 工厂,ba_report 却绕开它用裸 LangGraph prebuilt,代价是丢掉整条 middleware 链、手写 sandbox 生命周期(重复造了 SandboxMiddleware 的轮子)。重要平衡事实:ba_report/pipeline.py:1-5 已标 .. deprecated:: 2026-05-17,当前活跃 BA 路径已改为 ba_expert_stream → assistant_id="lead_agent"(见 §3.8),即团队已自行识别并纠偏这条弯路、收敛回原生 lead_agent + skill。但 agent_runner.py 仍被 ba_report/nodes/base.py:26 import,死代码尚未清理。
⑤ 置信度【确证】。建议:既然 BA 已切原生 lead_agent,删除 ba_report/pipeline.py+agent_runner.py+nodes/ 死代码(消除 cherry-pick 噪声 + 误用风险);若未来仍需独立 pipeline-agent,改用 create_deerflow_agent 拿回 middleware 链。
3.4 Agent-Tools BFF(business_objects / nc_primitives / project_primitives 反向回调)
① 业务需求:引擎里的 Agent 工具要回调 acdm-backend 业务后端(增删改会议/日历/报告/NC 文件),带身份与 service token。
② 冻结版 deer-flow 能力:【确证】冻结版 tools/ 无 business_objects/nc_primitives/project_primitives 三子目录(只有 builtins/、skill_manage_tool.py、tools.py)。但 deer-flow 原生提供 config-driven 工具扩展点:config.yaml tools[] 段 use: <module>:<tool> + group(config.yaml:520-636 实例),get_available_tools() 经 resolve_variable() 装配;标准 langchain_core.tools.@tool;langgraph.config.get_config() 读 configurable 取运行时身份。MCP server 扩展点也在(mcp/)。
③ a-cdm 实际做法:【确证】
tools/business_objects/tools.py:18from langchain_core.tools import tool,18 个工具全用标准@tool(:26,47,80,...);__init__.py:25自述"注册:tool_group=business_objects,通过 config.yamltools:条目挂到 lead_agent"。tools/business_objects/client.py:httpx helper,身份从langgraph.config.get_config()["configurable"]取user_id/agent_name/thread_id(:37-49),4 头X-ACDM-Service-Auth/User-Id/Agent-Name/Thread-Id(:69-75)回调acdm-backend:8002/agent-tools/business/<op>;异常归一为 ToolResponse dict(:80-125)。- 控制面侧
acdm-backend/app/api/agent_tools_business/等 3 个 BFF 路由接收,service token 校验 →via_agentactor。
④ 判定:【合理利用】 —— a-cdm 没造任何工具系统轮子。工具是标准 @tool,身份取自 LangGraph 原生 configurable,注册走 deer-flow 原生 tools[].use 扩展点 + Gateway POST /api/agents 的 tool_groups。"反向回调业务后端"是 deer-flow MCP/tool 机制本就能表达的(工具实现自由),a-cdm 选了 httpx BFF 而非 MCP server 是合理取舍(同步 RPC、强类型、复用控制面鉴权)。唯一小瑕疵:client.py:1-4 自承 business_objects 与 nc_primitives 两份 client 几乎相同未 DRY("未来可抽 agent_tools/_client.py"),属代码债非架构问题。
⑤ 置信度【确证】。建议:抽公共 agent_tools/_client.py 消除两份重复 httpx helper。
3.5 Aegra 替换 LangGraph Server
① 业务需求:需要一个 LangGraph 协议兼容的 Agent Runtime Server,且许可/部署可控(LangGraph Platform / LangSmith Deployments 为商业许可)。
② 冻结版 deer-flow 能力:【确证】冻结版自带一个 LangGraph-compatible 内嵌 Runtime(harness/deerflow/runtime/:RunManager/StreamBridge/Store provider,即上游 make dev-pro Gateway mode),但标准模式依赖外部 LangGraph CLI/Server(冻结版 pyproject.toml 只有 langgraph-sdk,无 langgraph-api/langgraph-cli,即 Server 本体是外部商业组件)。
③ a-cdm 实际做法:【确证】
- 用 Aegra 0.9.4(MIT,
ibbybuilds/aegra)替换 LangGraph Server 进程(docker/docker-compose-dev.yaml:270-326,aegra serve --port 2024,数据落 platform-db 的aegraDB)。 backend/aegra_graphs/5 个 wrapper 极致克制:每个就 1 行from deerflow.xxx import make_xxx as graph(lead_agent.py、weekly_report.py实测),纯路径适配(Aegra 只接受./path.py:var不接受module:var),不重写任何图逻辑。- 图本体(make_lead_agent / 4 个 pipeline)100% 复用 deer-flow harness。
langgraph.json保留作回滚通道,RUNTIME_BACKENDenv 切换。- Gateway 进程仍 import
deerflow.runtime的 RunManager/StreamBridge(app/gateway/services.py:21、deps.py:19,138)—— Aegra 只替换 2024 端口的 Agent Server,与 Gateway 内嵌 runtime 正交,未触碰 deer-flow runtime 代码。
④ 判定:【合理自建 / 合理选型】 —— 不是重造 Runtime 的绕弯路。a-cdm 没写一行 Runtime 代码,Aegra 是成熟的 LangGraph 协议兼容开源 server;替换动机(规避商业许可 + 自托管 + owner_sub Auth 落地)正当;wrapper 是 1 行 re-export 的最小适配;图与 harness 完全复用;保留回滚通道。对 deer-flow Runtime/persistence 的复用程度高(图全复用,Gateway 内嵌 runtime 未碰)。
⑤ 置信度【确证】。建议:落实背景报告建议 #4 —— 给"上游 Runtime 演进 vs Aegra"写影响评估 runbook,并定期实测 RUNTIME_BACKEND=langgraph 回滚路径真实可用性(否则只是名义开关)。
3.6 acdm-backend 控制面 — 哪些是 harness 已提供却重建?
① 业务需求:鉴权/多租户授权、项目 agent provision、业务持久化、模型治理、后台任务/SSE。
② 冻结版 deer-flow 能力:【确证】Gateway 提供 models/mcp/skills/memory/uploads/threads/artifacts/agents 路由;deerflow.runtime 提供 RunManager/StreamBridge/Store(agent 流式与 run 生命周期)。但无任何业务持久化、无 Keycloak/OAuth、无项目/成员/会议/报告域、无业务 DB 事务、无 WebDAV。
③ a-cdm 实际做法:【确证】acdm-backend 与 deer-flow 零代码共享、零 import(grep "import deerflow|from app.gateway" acdm-backend/app/ 实测为空),纯进程隔离,正向调引擎用官方 langgraph_sdk.get_client()(langgraph_client.py:31,93)。36 service / 29 router 全是 deer-flow 无对应能力的业务域。项目 agent provision project_agent_service.py:151-163 调 deer-flow Gateway 原生 POST /api/agents(冻结版 routers/agents.py 存在)+ tool_groups/skills,复用引擎扩展点驱动 agent 拓扑,非自造 agent 管理。
判定细分:
- 鉴权/授权/业务域/可逆 DB/WebDAV:【合理自建】 —— deer-flow 确无,且引擎不该管业务。【确证】
- 项目 agent provision:【合理利用】 —— 用 Gateway 原生
POST /api/agents扩展点。【确证】 - SSE/后台任务(
sse_manager.py/background_executor.py):【合理自建,存疑是否轻微重叠】 —— deer-flowruntime.StreamBridge是 Agent 流式专用(messages-tuple/values);acdm-backend 的 SSE 是业务长任务 + PG 持久化回放 + reattach,语义不同,且 acdm-backend 不能 import harness(CI 防火墙)。判为合理自建;但与引擎流式有概念重叠,存疑是否有更优共享抽象,不下定论。
④ 总判定:【合理自建 + 关键处合理利用】,无"harness 提供却在控制面重建"的实质造轮子。
⑤ 置信度【确证】(SSE 重叠部分【存疑】)。建议:无紧急项。
3.7 模型/Provider 配置(ai_registry/ai_roles vs config.yaml/model 工厂)
① 业务需求:集中治理所有 AI 调用点的 provider/model/凭据。
② 冻结版 deer-flow 能力:【确证】config.yaml models[] + models/factory.py:create_chat_model 管引擎内模型(reflection 装配,$ENV 解析)。无"跨引擎/控制面统一登记"概念。
③ a-cdm 实际做法:【确证】acdm-backend/app/util/ai_registry.py + app/ai_roles.yaml:管 acdm-backend 自身、不经引擎的业务 AI 调用(meeting_description/wiki_ai_rewrite/wiki_ai_extend/vision_calendar 等)。显式声明边界:6 个 role 标 managed_by: deer-flow(ai_roles.yaml:102-150,仅登记不调用),acdm-backend 调用 managed_by: deer-flow role 时主动抛 BusinessException 50403 引导去 config.yaml,拒绝跨边界直管。wiki_router.py:758,777 用 role_id="wiki_ai_rewrite" 走 ai_registry;meeting_ai_service.py:177 同。火山方舟 ark provider 在 ai_roles.yaml 已"永久禁用封存",config.yaml 的 ark 是引擎侧独立配置 —— 两处治理不同调用域(控制面业务 AI vs 引擎内 Agent 模型),凭据虽同源但调用路径不交叉。
④ 判定:【合理自建 + 边界克制(做得对)】 —— 不与引擎模型工厂打架,反而主动划清边界并以异常强制(managed_by: deer-flow → 50403)。这些业务 AI 调用本就不经引擎,deer-flow config.yaml 物理上管不到,自建 ai_registry 合理;且通过"全景登记 + 拒绝跨界"避免了双源治理混乱。
⑤ 置信度【确证】。建议:无;managed_by 边界声明是亮点,保持。
3.8 前端 src/core/acdm(27 模块)+ workspace + SSE 衬底
① 业务需求:项目工作台、wiki 协编、会议日历、BA 报告、业务长任务 SSE。
② 冻结版 deer-flow 能力:【确证】上游有 frontend/src/core/{agents,api,threads,messages,artifacts}、@langchain/langgraph-sdk useStream(Agent 对话流式)。无项目/wiki/会议业务模块。
③ a-cdm 实际做法:【确证】
src/core/acdm/27 个净新增模块(wiki/ba-report/knowledge/calendar/owner-sub-store 等),且复用 deer-flow(tool-result-invalidation.ts用 langgraph-sdk)。- Agent 对话路径完整复用 deer-flow 原生:
core/threads/core/messages/core/artifacts/core/tools全部原生保留并使用@langchain/langgraph-sdk(grep 实测 10+ 文件)。 - 业务长任务自造 SSE 衬底
core/ai-task/{use-ai-task-stream,sse-parser}.ts:基于裸 fetch ReadableStream,带 sessionStorage 持久化 + reattach + cancel API lifecycle;core/insight-engine/client.ts:7-8,170,212复用同一衬底(sse-parser 迁移 + re-export 保兼容),内部 DRY 良好。
④ 判定:【合理自建 + 高度复用(做得对)】 —— deer-flow useStream 是 LangGraph Agent 协议专用(messages-tuple/values/custom),a-cdm 业务长任务是 acdm-backend BFF 反代的 SSE(自定义 result/progress + 断线 reattach + 业务 cancel),语义不同,useStream 表达不了。自造 ai-task 衬底合理,且内部消除了重复(insight-engine 复用)。Agent 对话该复用的全复用了,没平行另造聊天栈。
⑤ 置信度【确证】。建议:无。
3.9 抽样业务点
| 业务点 | 实现方式 | 是否该用引擎能力却硬写 | 判定 | 置信度 |
|---|---|---|---|---|
| 可逆 DB / RevertEngine / saga | revert_engine.py + storage_events_service.py:ORM event + Actor 四模式 + 补偿式 revert(raw client 跳 wrapper 防 event 递归 + ETag 乐观锁 + 备份过期 410 降级) | 否 — deer-flow 引擎无业务 DB 事务/无 WebDAV/无可逆性,引擎不该管 | 【合理自建】 设计严谨(防递归、乐观锁、降级) | 【确证】 |
| 会议聚合 insights_service | BFF 做 NC 下载+markitdown 组 meetings_input + L1/L2 缓存(insights_service.py:1-256),调 langgraph_client 经 Aegra 跑 meeting_aggregator_realtime pipeline,post-pipeline BFF 写回缓存;harness 不碰 DB(test_harness_boundary 强制) | 否 — 引擎做无状态确定性聚合(复用 StateGraph),BFF 做有状态编排/缓存 | 【合理利用】 职责分层模范 | 【确证】 |
| BA 8 步 human-in-loop(当前活跃路径) | ba_expert_stream.py:60-135:SSE 代理,注入 X-Auth 4 头,调引擎 assistant_id="lead_agent"(deer-flow 原生 Agent + skill ba-analysis-pack 按需加载),非自造 pipeline | 否 — 收敛回原生 lead_agent + skill,8 步逻辑下沉为 deer-flow skill | 【合理利用(且为纠偏典范)】 从自造 pipeline 主动收敛回原生 | 【确证】 |
| BA expert stream 传输层 | 用 raw httpx.AsyncClient().stream() 手拼 LangGraph 协议 JSON(ba_expert_stream.py:88-110),未复用同仓 langgraph_client.py 的 SDK 封装(attach_stream/get_langgraph_client) | 部分 — 同仓已有 langgraph_sdk 封装却另起 raw httpx | 【绕弯路(轻微,代码一致性)】 功能正确但两套连引擎方式并存 | 【确证】 |
| 知识库 wiki 协编 | knowledge_service.py:GitLab llm-wiki 仓为真源,get_file_commits 取 sha + commit_file CAS 双层乐观锁(409 "已被他人修改"),AI 改写走 ai_registry SSE | 否 — wiki 协编/GitLab/乐观锁与引擎无关 | 【合理自建】 CAS 双层防御得当 | 【确证】 |
| 项目 agent provision | project_agent_service.py:151-163 调 deer-flow Gateway 原生 POST /api/agents + tool_groups/skills,409 视为复用,不可达则 DB 不写返 None 可 backfill(graceful) | 否 — 用引擎原生 agents 扩展点 | 【合理利用】 控制面驱动引擎拓扑,降级得当 | 【确证】 |
| lead_agent prompt 注入(project_primitives) | lead_agent/prompt.py:710 植入 from deerflow.tools.project_primitives.client import ... + :940-1016 <project_business_objects> prompt 块(~300 行),侵入上游核心文件 | 是 — 但 deer-flow 冻结版 prompt.py 无 prompt 注入扩展点(apply_prompt_template 是写死函数,无 hook/plugin) | 【绕弯路(无奈,deer-flow 缺扩展点)】 真实冲突面,但归因属上游无扩展点 | 【确证】 |
| demoo_service | Flask :8088,与 acdm-backend 仅共享 platform-db/NC,完全不依赖引擎(grep deerflow/langgraph 实测空),自有 LLM 链路 | 否 — 与引擎正交的独立子系统 | 【合理自建】 正交解耦,但留在 monorepo 无集成收益 | 【确证】 |
4. 「造轮子 / 绕弯路」发现清单(按严重度排序)
| # | 严重度 | 发现 | 证据 | 建议 |
|---|---|---|---|---|
| 1 | 中 | ba_report/agent_runner.py 用裸 langgraph.prebuilt.create_react_agent 绕开 deer-flow 冻结版已提供的 create_deerflow_agent SDK 工厂,丢失 18 个 middleware、手写 sandbox 生命周期(重造 SandboxMiddleware) | agent_runner.py:30,220,229-322 vs agents/factory.py:61;pipeline.py:1-5 已 deprecated 但 nodes/base.py:26 仍 import | 删死代码(BA 已切原生 lead_agent);若复活改用 create_deerflow_agent |
| 2 | 中 | lead_agent/prompt.py 侵入上游核心文件植入 ~300 行 project 注入逻辑 + prompt 块。deer-flow 无 prompt 注入扩展点,但 prompt.py 是上游高频演进文件,cherry-pick 必冲突 | prompt.py:710,894,940-1016;冻结版 git show 898f4e8:.../prompt.py 无这些 | 评估能否改用 extra_middleware(SystemMessage 注入)把定制移出 prompt.py;或文档化为"故意定制,cherry-pick 时保留" |
| 3 | 低-中 | langgraph.json/aegra.json 的 auth.path 语义改写无 CI 断言保护,cherry-pick 可静默回退鉴权 → owner_sub 隔离失效(越权风险) | 实测 .gitlab-ci.yml/tests/ 无 auth.path 断言,仅 test_ba_report_pipeline_env.py 存在性检查 | 加 CI 断言 json.load(langgraph.json)["auth"]["path"].endswith("acdm_auth.py:auth"),aegra.json 同 |
| 4 | 低 | acdm_thread_auth.py 经 Depends() 侵入 3 个上游 router(threads/uploads/artifacts) | threads.py:26,232 / uploads.py:12,98,226,248 / artifacts.py:10,90 | 注意:无法走 acdm_auth SDK Auth(这些端点不经 Aegra)— 侵入无可避免;改用 APIRouter(dependencies=[...]) 集中到 1 处降冲突面 |
| 5 | 低 | ba_expert_stream.py 用 raw httpx 手拼协议,不复用同仓 langgraph_client.py 的 langgraph_sdk 封装,两套连引擎方式并存 | ba_expert_stream.py:88-110 vs langgraph_client.py:31,93,430 | 统一走 langgraph_client SDK 封装(一致性,非紧急) |
| 6 | 低 | business_objects/client.py 与 nc_primitives/client.py 几乎重复 httpx helper 未 DRY | business_objects/client.py:1-4 自承 | 抽 tools/agent_tools/_client.py |
5. 「做得对 / 克制」清单(如实肯定)
- owner_sub 鉴权用 SDK 官方
langgraph_sdk.Auth扩展点,server-agnostic、服务端覆盖防伪造、带降级开关 —— 冻结版上游零鉴权能力时的满分自建范式(acdm_auth.py)。【确证】 - 确定性 Pipeline 100% 复用 LangGraph 原生
StateGraph+ 多图注册 +interrupt_before+ 顶层 checkpointer,零工作流引擎重造(pipelines/__init__.py、weekly_report/pipeline.py、ba_report/pipeline.py)。【确证】 - Agent-Tools BFF 完全走 deer-flow 原生扩展点:标准
@tool+langgraph.config身份 +tools[].use注册 + GatewayPOST /api/agents,无工具系统重造(business_objects/、project_agent_service.py)。【确证】 - Aegra 替换是合理选型非重造:wrapper 1 行 re-export,图与 harness 100% 复用,保留
RUNTIME_BACKEND回滚,未触碰 deer-flow runtime 代码。【确证】 - acdm-backend 与引擎零代码共享、纯进程隔离,正向用官方 SDK,
test_harness_boundaryAST 防火墙强制 harness 不碰业务 DB —— 199 提交漂移下冲突面被刻意压到最低的结构性原因。【确证】 - ai_registry 主动声明并以异常强制治理边界(
managed_by: deer-flow→ 50403 拒绝跨界),不与引擎模型工厂打架。【确证】 - 前端 Agent 对话完整复用 deer-flow
useStream/langgraph-sdk,只为语义不同的业务长任务自造ai-task衬底且内部 DRY,无平行聊天栈。【确证】 - 团队具备自我纠偏能力:BA 早期用自造 pipeline+裸 agent,2026-05-17 主动收敛回原生
assistant_id="lead_agent"+ skill —— 弯路被识别并回退,这是成熟二开团队的标志。【确证】 - 业务可逆性/缓存/乐观锁设计严谨:RevertEngine 跳 wrapper 防 event 递归、ETag 乐观锁、备份过期 410 降级;wiki CAS 双层;insights L1/L2 lazy stale —— 自建部分质量高。【确证】
6. 给维护者的优先级建议(可落地)
- 【紧急】给
langgraph.json/aegra.json加auth.pathCI 断言(发现 #3):实测当前无任何断言保护,cherry-pick 上游同文件可静默把鉴权回退到上游langgraph_auth.py→ owner_sub 隔离失效 → 跨租户越权。一行 pytest 即可锁死,投入产出比最高。 - 【高】清理
ba_report死代码(发现 #1):BA 已切原生 lead_agent,pipeline.py/agent_runner.py/nodes/已 deprecated 但仍被 import。删除可同时消除"裸 create_react_agent 绕开 create_deerflow_agent"这条已纠偏弯路的残留与 cherry-pick 噪声。 - 【高】文档化 / 收敛上游侵入点(发现 #2、#4):
lead_agent/prompt.py与 3 个 router 是仅有的上游文件侵入。prompt.py 评估改extra_middleware注入;3 个 router 的Depends收敛为APIRouter(dependencies=[...])集中到 1 处。两者都在文件头加"故意定制,cherry-pick 必保留"注释 + 记入vendored-sync.md。 - 【中】统一控制面连引擎方式(发现 #5):
ba_expert_stream.py改走langgraph_client.py的 SDK 封装,消除两套并存。 - 【中】抽
agent_tools/_client.pyDRY(发现 #6):消除 business_objects / nc_primitives 两份重复 httpx helper(代码自己已标注 TODO)。 - 【中】落实 Aegra 回滚路径实测 + demoo 拆仓评估(承接背景报告 #4/#5):
RUNTIME_BACKEND=langgraph定期实测真实可用;demoo_service 与引擎完全正交、零依赖,留 monorepo 无集成收益,带宽允许可拆出降认知负载。
审计方法论备注:所有"deer-flow 是否有此能力"以冻结点
898f4e8git ground truth 为准(实测推翻"上游 fork 时已有 langgraph_auth"的隐含前提 —— 它晚于 fork 点 9 天)。所有"a-cdm 定制"以"冻结版目录/文件不存在"或显式acdm/owner_sub标记为据。无法干净归因项(SSE 与引擎流式是否有更优共享抽象)已标【存疑】不下定论。本报告对背景交叉报告建议 #3 作出修正:acdm_thread_auth.py物理上无法收敛进 acdm_auth.py 的 SDK Auth 扩展点(端点不经 Aegra),其侵入属必要补丁而非可消除的绕弯路。