Skip to content

acdm-backend 控制面架构

本章目标:

  1. 看懂 create_app() 工厂:中间件栈、异常契约、30+ router 如何串起来
  2. 掌握 _lifespan 启动序列每一步在初始化什么、为什么是这个顺序
  3. 理解 api → service → repository → model 四层铁律及其禁忌

TL;DR

acdm-backend 是 a-cdm 的"控制面":一个 FastAPI 应用,create_app()(acdm-backend/app/main.py:214)装配 5 道中间件(CORS、SlowAPI 限速、reversible actor、MCP service token、audit log)、3 个统一异常处理器(429/业务 400/全局 500)、30+ router 和一个 /mcp 子应用。_lifespan(main.py:134)按"AI 注册表 → DB event recorder → AI 抽取监听 → 启动恢复 → 健康探测 → 后台执行器 → BA 报告调度器"顺序启动。代码严格分四层:api(契约) → service(业务+事务) → repository(纯 CRUD) → model(ORM)。

Overview(为什么控制面要这样组织)

引擎(deer-flow)是通用 Agent 框架,不懂"项目""会议""成员"这些业务概念,也不该承担鉴权、数据治理、可逆操作。acdm-backend 就是这一层"业务适配 + 安全边界 + 编排中枢":

  • 对前端:提供项目/会议/知识库/BA 报告等业务 CRUD;
  • 对引擎:既是 forward_auth 的 verify 提供方,又是 Agent 工具的 BFF 后端,还是 MCP 知识源;
  • 对自身:统一鉴权、统一异常契约、可逆操作框架。

它把这些职责用"工厂装配 + lifespan 编排 + 四层分层"组织起来,目的是让每类关注点(中间件、异常、启动、业务)各归其位、互不缠绕。

Architecture:中间件栈

create_app() 按顺序 add_middleware,执行时后注册的先进(FastAPI/Starlette 洋葱模型):

中间件作用Source
CORSMiddleware跨域(前端 dev origin)acdm-backend/app/main.py:222-228
SlowAPIMiddleware/auth/login 速率限制(30/min,防扫描/DoS)acdm-backend/app/main.py:230-233
reversible_actor_context从 JWT 设 actor=direct(可逆操作上下文)acdm-backend/app/main.py:239-250
mcp_service_auth校验 /mcp/*/agent-tools/*X-ACDM-Service-Authacdm-backend/app/main.py:255-268
audit_log请求日志 + API 审计表记录acdm-backend/app/main.py:270-295

reversible_actor_context 是 a-cdm 特有的:它把当前用户身份注入 ContextVar(set_direct_actor),后续可逆操作框架据此记录"是谁动了数据"(详见可逆操作章)。mcp_service_auth 拦截服务间调用路径,这是引擎回调控制面 BFF 的认证关口(详见耦合契约章)。

Components:统一异常契约

三个 @app.exception_handler 把所有错误收敛成一致的 ApiResponse 形状:

异常HTTP响应体Source
RateLimitExceeded429{code,data:null,message} + Retry-Afteracdm-backend/app/main.py:297-315
BusinessException400{code, data:null, message}acdm-backend/app/main.py:317-330
Exception(兜底)500统一格式,不泄露栈acdm-backend/app/main.py:331-337

这就是为什么授权依赖抛 BusinessException(40401) 能统一变成 HTTP 400 + {code:40401} ——前端只需按 code 判业务错误,不用解析多种错误形状。/health 端点(main.py:339)供 docker healthcheck 用。

Data Flow:_lifespan 启动序列

启动顺序不是随意的——后面的步骤依赖前面初始化好的状态:

  1. init_registry()(main.py:153):AI 角色注册表 fail-fast 校验——结构错直接让进程起不来,这必须最先做。
  2. install_db_event_recorder()(main.py:159):注册 SQLAlchemy ORM 事件监听,可逆操作框架的基础,必须在任何业务写之前装好。
  3. install_ai_extract_listener()(main.py:166):给 MeetingFile 装 after_insert hook,文件入库即触发 AI 抽取。
  4. recover_pending_on_startup()(main.py:170):扫 status=pending 的未完抽取任务重新入队——容错重启(非阻塞,失败只 log)。
  5. probe_streaming_roles()(main.py:178):探测 streaming AI 角色健康(非阻塞,main.py:180 失败只 log)。
  6. start_background_executor()(main.py:187):后台任务执行器。
  7. run_sync_scheduler()(main.py:191):BA 报告状态监控定时任务,asyncio.create_task 常驻。

关闭序列对称收尾:stop_background_executor() + scheduler_task.cancel()

Implementation:四层铁律

acdm-backend/README.md:9-40 把分层定为铁律,每层职责单一:

目录职责禁忌
apiapp/api/FastAPI router + Pydantic 契约 + @Depends 鉴权❌ 直接 import repository(跨过 service)
serviceapp/services/业务逻辑 + 事务边界 + BusinessException❌ 调 api/* 或返 FastAPI Response
repositoryapp/repository/纯 SQLAlchemy CRUDawait session.commit()(commit 只在 service)
modelapp/model/ORM 类,绑 acdm schema❌ 写业务逻辑

样板:api/project_router.py + services/project_service.py + repository/project_repo.py + model/models.py:Project 是一套干净分层,新增资源直接对照(acdm-backend/README.md:38-40)。commit 只在 service 层发生这条很关键——它保证事务边界与可逆操作的 business_transaction 对齐(详见可逆操作章)。

router 注册在 create_app() 末段(main.py:379-569),约 30 个业务/admin/agent-tools router + app.mount("/mcp", get_mcp_app())(main.py:560)挂 FastMCP 子应用 + auth_router/verify_router/health_routeragent_tools_* router 走共享 X-ACDM-Service-Auth 网关(main.py:566-569),由 mcp_service_auth 中间件保护。

Common Pitfalls / 实战 Tips

  • lifespan 步骤顺序不能乱:install_db_event_recorder 必须在业务写之前;init_registry 必须最先(fail-fast)。改 lifespan 注意依赖。
  • repository 不 commit:在 repo 里写 session.commit() 会破坏 service 的事务边界,也会让可逆操作框架记错事件边界。
  • 新增 router 别忘鉴权 Depends:api 层不挂 require_* 依赖等于裸奔;agent-tools 路由要靠 mcp_service_auth 中间件覆盖前缀。
  • 中间件顺序是洋葱:audit_log 最后注册=最外层,能记到所有请求;改中间件注册顺序会改变包裹关系。

References

  • acdm-backend/app/main.py:134-212_lifespan 启动/关闭序列(本章主源)
  • acdm-backend/app/main.py:214-337create_app 工厂:中间件栈 + 异常处理器
  • acdm-backend/app/main.py:379-569 — 30+ router 注册 + /mcp 挂载
  • acdm-backend/README.md:9-40 — 四层铁律与禁忌(线索,已回源核实)
  • acdm-backend/app/database.py — async SQLAlchemy 引擎 + acdm schema 绑定
  • acdm-backend/app/config.py:17-242 — 控制面配置 Settings
PageRelationship
仓库结构与代码地图本章是该章 acdm-backend 分区的机制展开
鉴权与授权双层体系本章中间件/router 挂载该章的授权依赖
可逆 DB 操作与存储层本章 reversible_actor_context + install_db_event_recorder 在该章详解
审计、SSE 与后台任务本章 lifespan 启动的 background_executor/scheduler 在该章详解
知识源 MCP 与 Agent Tools BFF本章 /mcp 挂载 + mcp_service_auth 在该章展开

公司内部参考 · 由 claude-wiki-gen 基于源码自动生成的二次分析