<div align="center">
  <h1>CMDC</h1>
  <h3>Production-grade AI Agent kernel for Elixir.</h3>
  <p>用 OTP 把 Agent 跑成生产服务 — Crash-safe · Observable · Multi-tenant by design.</p>

  [![Hex.pm](https://img.shields.io/hexpm/v/cmdc.svg)](https://hex.pm/packages/cmdc)
  [![Docs](https://img.shields.io/badge/docs-hexdocs-blue.svg)](https://hexdocs.pm/cmdc)
  [![License](https://img.shields.io/badge/License-Apache%202.0%20with%20Commons%20Clause-blue.svg)](LICENSE)
  [![Tests](https://img.shields.io/badge/tests-1219%20%2B%2021%20doctests-brightgreen.svg)]()
  [![Warnings](https://img.shields.io/badge/warnings-0-brightgreen.svg)]()
</div>

---

## 为什么是 CMDC

把 Agent 推到生产环境会立刻撞上三堵墙：**一个子任务挂了整个会话陪葬 / LLM
在你看不见的地方烧 token / 想做前端断网重连或跨设备恢复但框架根本不支持**。

CMDC 把每个会话当作一棵 OTP Supervisor 树跑在 BEAM 上，从内核就把这些问题
解决了：

- **进程级容错** — 每个 Agent / SubAgent 各自一个 OTP 进程，crash 不传染。
  Supervisor 决定重启策略，BEAM 调度天然亿级并发。
- **可观测性内建** — 6 个标准 `:telemetry` 事件零侵入接 Langfuse / LangSmith /
  Tempo / Datadog；50+ 种业务事件经 `EventBus` 广播给业务侧订阅。
- **多租户透传** — `Options.user_data :: map()` 经 Plugin / Tool / SubAgent
  全链路透传，按 `user_id` / `tenant_id` 隔离记忆、计费、审批白名单。
- **会话快照** — `CMDC.Checkpoint` 一等公民 + Backend behaviour，BEAM 重启 /
  Gateway 滚动升级 / 用户跨设备恢复同一对话。
- **大规模工具结果** — 200KB+ 工具返回 0 token 占用，Plugin 自动 offload 到
  backend，Agent 用 `read_file(offset, limit)` 分页消费。
- **A2A 协议全栈** — `cmdc_gateway` 同时支持 sync / SSE / **webhook**（HMAC
  签名 + 指数退避）/ Agent Card 四种交互机制，>5 分钟长任务也不丢回调。

---

## 主要能力

按部署关注点分组：

### Runtime — OTP 容错与并发

- `gen_statem` 4 状态机：`idle / running / streaming / executing_tools`
- Supervisor 树管理父代理 + 子代理 + DynamicSupervisor，按需 `:rest_for_one`
- `CMDC.steer/2` 中段软中断（killable tools brutal_kill + queue 合并注入）
- `CMDC.abort/2` 4 状态行为表 + 100ms 内 `:agent_abort` 事件保证
- 内建循环检测：文件编辑频率 / 重复调用模式 / 连续失败 三路自动 intervene

### Observability — 可观测性

- `CMDC.Telemetry` — 6 个标准 `:telemetry` 事件契约（agent.turn /
  llm.request / tool.exec start/stop），schema_version 锁定向后兼容
- `CMDC.EventBus` — 50+ 业务事件经 `{:cmdc_event, sid, event}` 广播
- `CMDC.monitor/1` — 结构化崩溃 reason 表：`:max_turns_exceeded /
  :provider_timeout / {:plugin_aborted, name, why}` 等
- `EventBus.subscribe(sid, since: idx, types: [...])` — 重连补帧

### Safety — 安全与合规

- `HumanApproval` — HITL 审批，4 态权限（approve_once / approve_always /
  reject_once / reject_always），session-scoped 白名单 + ACP 协议透传
- `SecurityGuard` — 路径 / 命令 deny list（HTTP 层快过滤）
- `ContentPolicy` — LLM-as-Judge 4 大策略（越狱 / 有害 / 离题 / 品牌违规），
  judge 失败容错降级
- `OutputFilter` — 输出端 PII / 敏感词过滤
- `Sandbox.virtual_mode` — 拦 `..` / `~` traversal + `O_NOFOLLOW` symlink 防护

### Cost & Performance — 成本与性能

- `CMDC.TokenUsage` struct — 自动归一化 OpenAI / Anthropic / Google 三家
  raw usage 字段
- `CostGuard` — token / cost 硬预算超限 abort + 80% 告警
- `ModelRouter` — 按 turn / cost / token_budget / task_complexity /
  time_of_day / user_tier / user_data 7 类规则动态切模型
- `LargeResultOffload` — 200KB+ 工具结果通过 `:replace_tool_result` action
  落 backend，message history 只留 head/tail preview + 文件路径
- `PromptCache` — Anthropic prompt caching 自动启用
- `Compactor` + `ArgTruncator` — 上下文压缩 + 预 truncate 大参数

### Memory & Recovery — 记忆与恢复

- `MemoryLoader` + `MemoryFlush` 闭环 — 长会话不失忆（压缩前持久化关键事实，
  下次会话由 `MemoryLoader` 自动加载）
- `EpisodicMemory` — 成功对话作 few-shot 复用，按 user_id 多租户隔离
- `CMDC.Checkpoint` — ETS / DETS 内置 backend，跨 BEAM 进程恢复
- `CMDC.Backend.Composite` — 一个会话同时挂 sandbox + PG memory + ETS history
  （prefix 路由）

### Plugin Pipeline — 13 hook × 8 action

13 个生命周期 hook（session / prompt / request / response / tool /
compact / steering / turn）× 8 种 action（continue / intervene / abort /
skip / block_tool / replace_args / replace_result / switch_model）。
**16 个内置 Plugin** 覆盖审批 / 安全 / 内容拦截 / 长会话记忆 / 模型路由 /
大结果 offload / 反思 / 规划等典型场景。

---

## 安装

```elixir
def deps do
  [
    {:cmdc, "~> 0.4"}
  ]
end
```

可选生态库：

```elixir
{:cmdc_gateway, "~> 0.4"},       # HTTP / SSE / WebSocket / A2A 网关
{:cmdc_orchestrator, "~> 0.3"},  # DAG / Debate / Hierarchy / Router-LLM
{:cmdc_skill_engine, "~> 0.2"}   # Skill 自进化引擎
```

## 30 秒上手

```elixir
{:ok, session} = CMDC.create_agent(
  model: "anthropic:claude-sonnet-4-5",
  api_key: System.get_env("ANTHROPIC_API_KEY")
)

CMDC.prompt(session, "用一句话介绍 Elixir 的优势。")
{:ok, reply} = CMDC.collect_reply(session)
IO.puts(reply)

CMDC.stop(session)
```

完整指南：[5 分钟上手](https://hexdocs.pm/cmdc/quickstart.html) /
[核心概念](https://hexdocs.pm/cmdc/concepts.html) /
[10 个生产配方](https://hexdocs.pm/cmdc/cookbook.html)

---

## 生产部署模式

```elixir
defmodule MyApp.SupportAgent do
  @behaviour CMDC.Blueprint

  def build(opts) do
    %CMDC.Options{
      model: "anthropic:claude-sonnet-4-5",
      working_dir: "/tmp/support/#{opts[:tenant_id]}",
      user_data: %{tenant_id: opts[:tenant_id], user_tier: opts[:user_tier]},

      # 多 backend 路由：sandbox + 长期记忆 + 短期 ETS
      backend: CMDC.Backend.Composite.new(
        default: CMDC.Backend.Filesystem.new(
          root_dir: "/tmp/support/#{opts[:tenant_id]}",
          virtual_mode: true              # 防 traversal
        ),
        routes: %{
          "/memories/" => MyApp.PgBackend.new(),
          "/conversation_history/" => CMDC.Backend.State.new()
        }
      ),

      tools: [MyApp.QueryDB, MyApp.RefundOrder, CMDC.Tool.AskUser],

      plugins: [
        # 安全
        {CMDC.Plugin.Builtin.HumanApproval, tools: ["refund_order"]},
        {CMDC.Plugin.Builtin.ContentPolicy, []},

        # 成本
        {CMDC.Plugin.Builtin.CostGuard, max_usd: 0.50},
        {CMDC.Plugin.Builtin.ModelRouter, [
          rules: [
            %{condition: {:user_tier, :free}, model: "openai:gpt-4o-mini"},
            %{condition: {:cost_gt, 0.10}, model: "openai:gpt-4o-mini"}
          ]
        ]},

        # 大结果落盘
        {CMDC.Plugin.Builtin.LargeResultOffload, [
          backend: opts[:backend],
          tool_token_limit_before_evict: 20_000
        ]}
      ],

      # 上下文压缩 + 重连补帧
      compactor: [trigger: {:tokens, 50_000}, keep: {:messages, 10}],
      event_buffer_size: 200
    }
  end
end

{:ok, session} = CMDC.create_agent(MyApp.SupportAgent,
  tenant_id: "acme",
  user_tier: :pro
)

# 接 Langfuse 可观测
:telemetry.attach_many("cmdc-langfuse",
  CMDC.Telemetry.all_events(),
  &MyApp.LangfuseSink.handle_event/4, [])

# 业务订阅事件流
CMDC.subscribe(session)
CMDC.monitor(session)
```

---

## FAQ

### 为什么用 Elixir / BEAM 跑 Agent

LLM Agent 的本质是**长期运行的并发状态机**：每个会话独立、可崩可重启、需要
被持续观察、要能在多租户场景下互不干扰。这恰好是 BEAM 三十年来的本职工作——
WhatsApp 用 Erlang 单机扛 200 万并发连接，Discord 用 Elixir 处理千万级实时消息。
把 LLM Agent 跑在 BEAM 上不是花活，是**让 Agent 享受电信级容错和并发的免费午餐**。

### 是否绑死 LLM 厂商

不。Provider 层基于 [`req_llm`](https://hex.pm/packages/req_llm) 封装，支持
Anthropic / OpenAI / Google / Mistral / Bedrock / 自建网关 / 任意 OpenAI
兼容 endpoint。`switch_model/2` 支持运行期热切（含 `provider_opts` 同步切换
base_url / api_key）。

### 生产可靠性证据

- v0.4.1 主库：**1219 tests + 21 doctests, 0 failures, 0 warnings**
- v0.4.1 网关：125 tests，0 failures（含 12 个 webhook 测试）
- 4 个生态 hex 包同步发布：[cmdc](https://hex.pm/packages/cmdc) /
  [cmdc_gateway](https://hex.pm/packages/cmdc_gateway) /
  [cmdc_orchestrator](https://hex.pm/packages/cmdc_orchestrator) /
  [cmdc_skill_engine](https://hex.pm/packages/cmdc_skill_engine)
- A2A 协议 4 种交互机制全实现（sync / SSE / webhook / Agent Card）
- 所有公共 API 在 v0.3 起返回 `{:ok, _} | {:error, _}`，无意外 raise

### 跟 Python Agent 框架的差别

不写对比表（写了也没意思），列三个**只有 BEAM 才便宜实现**的能力让你自己判断：

1. 子代理 crash 不传染父代理——`DynamicSupervisor` 默认行为，零代码
2. 跨进程跨节点会话恢复——`CMDC.Checkpoint` + 任意分布式 backend 即可
3. 单机数万 Agent 进程并发——OTP 调度天然支持，无需额外协程框架

### 与 Langfuse / LangSmith 集成需要写多少代码

零侵入。CMDC 只发 `:telemetry` 标准事件，sink 由你按需挂：

```elixir
:telemetry.attach_many("my-langfuse", CMDC.Telemetry.all_events(),
  &MyApp.LangfuseSink.handle_event/4, [])
```

3 份完整配方（Langfuse OTLP / LangSmith OTel / Grafana Tempo + Loki）见
[常见配方](https://hexdocs.pm/cmdc/cookbook.html)。

---

## 数字

| 指标 | v0.4.1 |
|---|---|
| Tests | 1219 + 21 doctests, 0 failures |
| 编译 warnings | 0 |
| Hex doc warnings | 0 |
| 内置 Plugin | 16 |
| 内置 Tool | 11 |
| Plugin Pipeline | 13 hook × 8 action |
| 生态 Hex 包 | 4（cmdc / cmdc_gateway / cmdc_orchestrator / cmdc_skill_engine） |
| 主库代码 | ~12K 行（不含测试） |

---

## 文档

- [hexdocs.pm/cmdc](https://hexdocs.pm/cmdc) — 完整 API 文档 + 7 篇入门指南
- [GitHub Releases](https://github.com/tupleyun/cmdc/releases) — 版本完整 changelog
- [升级指南](https://hexdocs.pm/cmdc/upgrading.html) — v0.2 → v0.3 → v0.4 兼容边界

---

## 开发

```bash
mix deps.get
mix compile --warnings-as-errors
mix test
mix format --check-formatted
mix credo --strict
mix docs
```

跑真实 LLM 端到端示例（需 `ANTHROPIC_API_KEY` 等环境变量）：

```bash
cd example && mix run example/simple_agent.exs
```

---

## License

Apache 2.0 with Commons Clause。商用授权请联系 `glggsai@qq.com`。
