CMDC 的设计就是 7 个互不重叠的抽象搭积木。读完本章你能在脑里画出整个调用图。


一、Agent — gen_statem 状态机

每个会话对应一个 OTP 进程,跑 :gen_statem 状态机,4 个状态:

idle prompt running stream chunk streaming tool calls executing_tools
                                                                      
   工具批次完成 / abort / agent_end 

外部代码不直接持 Agent struct,只通过 pid 或 session_id 字符串交互

{:ok, session} = CMDC.create_agent(model: "anthropic:claude-sonnet-4-5")

CMDC.prompt(session, "...")       # 异步 cast,立即返回
CMDC.steer(session, ref, "...")   # 中段干预
CMDC.abort(session)               # 中止
CMDC.status(session)              # 状态快照
CMDC.stop(session)                # 终止 Supervisor 树

完整 API 矩阵见 CMDC,状态机详细行为见 Agent 状态机与事件


二、Session — Supervisor Tree

create_agent/1 实际启动了一棵 Supervisor 树:

SessionServer (Supervisor :rest_for_one)
 Agent (gen_statem)
 SubAgent.Supervisor (DynamicSupervisor)
      Agent #1 (gen_statem)
      Agent #2 (gen_statem)
         ... Agent 同样隔离

子 Agent crash 不影响父 Agent;父 Agent crash 由 SessionServer 决定是否 重启全树。Stop 一个 session = 停整棵树。


三、EventBus — 唯一的对外合约

Agent 内部所有"事情发生了"都通过 CMDC.Emitter 广播到 CMDC.EventBus,订阅者收到统一格式:

{:cmdc_event, session_id, event}

事件类型分七大类(session / stream / tool / approval / subagent / plugin_event / error),完整清单见 CMDC.Event

消费方式

场景API
当前进程订阅CMDC.subscribe/2
重连补帧CMDC.subscribe(session, since: last_index)(需 event_buffer_size > 0
Agent 崩溃监控CMDC.monitor/1{:cmdc_down, ref, sid, reason}

四、Plugin — 切面拦截器

Plugin 实现 CMDC.Plugin behaviour,在 13 个 hook 中 返回 8 种 action 之一:

关键 hook用途常用 action
:session_start / :session_end资源初始化/清理:emit
{:before_prompt, text}用户 prompt 进 Agent 前:intervene 改写、:abort 拦截
{:before_request, messages}LLM 请求前:switch_model 路由模型
{:after_response, msg}LLM 回复后:abort / :intervene
{:before_tool, name, args}工具执行前:block_tool 拦截、:replace_tool_args 改参
{:on_tool_error, ...}工具失败:continue 重试、:abort 放弃
{:after_tool, name, call_id, result}单工具后:replace_tool_result 改 result
{:before_compact, messages}压缩前持久化关键事实

完整矩阵 + 5 个范例见 写一个 Plugin


五、Tool — Agent 可调用的能力

Tool 是 LLM 视角的"函数",实现 CMDC.Tool behaviour:

@callback name() :: String.t()
@callback description() :: String.t()
@callback parameters() :: map()                          # JSON Schema
@callback execute(args :: map(), ctx :: CMDC.Context.t()) ::
            {:ok, String.t()} | {:error, String.t()} | {:effect, term()}

CMDC 内置 11 个:ReadFile / WriteFile / EditFile / Shell / Grep / ListDir / Glob / Task(子代理)/ WriteTodos / AskUser / CompactConversation

文件类工具默认走 CMDC.Sandbox 代理,所有路径在 working_dir 内做边界校验。详见 写一个 Tool


六、Backend / Sandbox — 文件与执行的抽象

CMDC.Backend 是文件 / 状态 / 远程存储的统一访问层 (10 callback:ls / read / write / edit / grep / glob / upload / download + 扩展的 execute / id),3 个内置实现:

Backend用途持久性
Backend.State内存 ETS,单测 / 短会话进程级
Backend.Filesystem本地文件,CLI / 开发跨进程
Backend.Compositeprefix 路由组合,生产推荐

CMDC.Sandbox 是 Backend 的子集 + 加 execute (shell 命令)。Sandbox.Local 是默认实现。

典型生产配置(一个会话挂多套存储):

backend = CMDC.Backend.Composite.new(
  default: CMDC.Backend.Filesystem.new(root_dir: "/tmp/work", virtual_mode: true),
  routes: %{
    "/memories/" => MyApp.PgBackend.new(),                # 长期记忆
    "/conversation_history/" => CMDC.Backend.State.new()  # 短期 ETS
  }
)

{:ok, session} = CMDC.create_agent(model: "...", backend: backend)

七、Skill / Memory / Checkpoint — 三类持久化

CMDC 把"持久化"按时间尺度拆成三层,命名独立、互不重叠:

模块时间尺度用途数据形态
CMDC.Skill永久加载 SKILL.md 注入 system prompt.md 文件 + frontmatter
CMDC.Memory behaviour跨会话语义记忆存储(store / search / similarity)由 backend 决定(ETS / Postgres + pgvector)
CMDC.Checkpoint单会话快照BEAM 重启 / 跨设备恢复Snapshot struct 序列化

易混淆

  • Backend 是「文件接口」(read_file 之类)
  • Memory 是「语义记忆接口」(向量检索之类)
  • Checkpoint 是「会话快照」(save / load / list)

详见 CMDC.Backend / CMDC.Memory / CMDC.Checkpoint 三个模块文档。


依赖关系一览

                    
                       CMDC (facade) 
                    
                             
        
                                                
   SessionServer  EventBus       Checkpoint    Telemetry
        
   
            
  Agent  SubAgent.Supervisor
   
    State / Stream / ToolRunner / Compactor    @moduledoc false 私有
    Plugin Pipeline
         16 内置 Plugin
    Tool11 内置
         Sandbox / Backend
    Providerreq_llm 封装
    Skill / Memory / Blueprint
    MCPBridge / Client / Supervisor

层级规则:只允许向下依赖,同层不互相依赖


下一步