README.md

# CMDC

**Elixir Agent Kernel** — OTP `gen_statem` 驱动的 AI Agent 开发库,专为高并发、高可靠性的 AI Agent 场景设计。

[![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)

---

## 功能亮点

| 维度 | DeepAgents (Python) | CMDC (Elixir) |
|------|---------------------|---------------|
| **并发模型** | asyncio + Thread | OTP gen_statem + Supervisor — 原生容错、热更新、进程隔离 |
| **SubAgent** | 同步阻塞 | OTP 进程级隔离 + 真并发,子 Agent crash 不传染父 Agent |
| **Plugin 系统** | Middleware 线性链 | Pipeline:11 个 hook × 7 种 action,更精细的拦截和控制力 |
| **安全** | 无内置 | SecurityGuard Plugin — 内置路径/命令安全防护 |
| **成本控制** | 无 | Agent.State 自动累加 token / cost_usd |
| **类型安全** | Python type hints | TypedStruct + NimbleOptions + `@spec` 五层 AI-Friendly 防护 |
| **声明式定义** | 无等价物 | Blueprint 系统 — 可复用的 Agent 蓝图 |

---

## 安装

将 `cmdc` 添加到 `mix.exs` 依赖列表:

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

然后获取依赖:

```bash
mix deps.get
```

---

## 快速开始

### 最简 Agent

```elixir
# 1. 在应用监控树中启动 Session
{:ok, pid} = CMDC.create_agent(
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY")
)

# 2. 发送提示词(异步流式)
:ok = CMDC.prompt(pid, "你好,请介绍一下你自己")

# 3. 收集完整回复
{:ok, reply} = CMDC.collect_reply(pid)
IO.puts(reply)

# 4. 停止
CMDC.stop(pid)
```

### 带工具的 Agent

```elixir
{:ok, pid} = CMDC.create_agent(
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY"),
  tools: [CMDC.Tool.ReadFile, CMDC.Tool.WriteFile, CMDC.Tool.Shell],
  working_dir: "/tmp/workspace"
)

CMDC.prompt(pid, "读取 README.md 并写一份中文摘要到 summary.md")
{:ok, reply} = CMDC.collect_reply(pid)
```

### 订阅事件流

```elixir
CMDC.subscribe(pid)

CMDC.prompt(pid, "写一段 Elixir 代码示例")

# 实时接收流式事件
receive do
  {:cmdc_event, %CMDC.Event{type: :stream_delta, data: %{delta: text}}} ->
    IO.write(text)
  {:cmdc_event, %CMDC.Event{type: :stream_stop}} ->
    IO.puts("\n[完成]")
end
```

### 使用 Blueprint 声明式定义

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

  @impl true
  def build(_opts) do
    %CMDC.Options{
      system_prompt: "你是一名资深 Elixir 工程师。",
      tools: [CMDC.Tool.ReadFile, CMDC.Tool.WriteFile, CMDC.Tool.Shell],
      plugins: [CMDC.Plugin.Builtin.SecurityGuard],
      skills_dirs: ["priv/skills"]
    }
  end
end

{:ok, pid} = CMDC.create_agent(MyApp.CodingAgent,
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY")
)
```

### 自定义 Plugin

```elixir
defmodule MyApp.AuditPlugin do
  @behaviour CMDC.Plugin

  @impl true
  def init(_opts), do: {:ok, %{count: 0}}

  @impl true
  def priority, do: 100

  @impl true
  def handle_event({:before_tool, name, args}, state, _ctx) do
    IO.puts("[审计] 调用工具: #{name}, 参数: #{inspect(args)}")
    {:continue, %{state | count: state.count + 1}}
  end
  def handle_event(_event, state, _ctx), do: {:continue, state}
end
```

---

## 架构

```
CMDC(公共 API 入口)
├── SessionServer(Supervisor Tree)
│   ├── Agent(gen_statem 状态机)
│   │   ├── State          — 运行时状态 + token/cost 追踪
│   │   ├── Stream         — 流式响应 delta 组装
│   │   ├── ToolRunner     — 工具执行 + 循环检测
│   │   ├── Emitter        — EventBus 事件广播
│   │   ├── SystemPrompt   — 提示词组装(BasePrompt + Skills + Memory)
│   │   └── Compactor      — 上下文压缩 + ArgTruncator
│   └── SubAgent.Supervisor(DynamicSupervisor)
│       └── 子 Agent 进程(并行、隔离)
│
├── Plugin Pipeline(11 hooks × 7 actions)
├── Tool(11 个内置工具)
├── Provider(req_llm 封装,支持多 LLM 提供商)
├── MCP(Bridge + Client + Supervisor)
├── Sandbox(可插拔文件系统抽象)
├── Blueprint(声明式 Agent 蓝图)
├── Skills(渐进式 SKILL.md 发现)
└── Memory.ETS(ETS 持久记忆)
```

### 模块依赖层级

```
L0  基础类型    Options / Config / Context / Message / Event / EventBus / SubAgent
L1  核心抽象    Blueprint / Plugin / Tool / Sandbox / Skill / Provider
L2  Agent      Agent (gen_statem) + State + Stream + ToolRunner + Compactor
L3  集成       SessionServer + MCP.* + Memory.ETS + SubAgent.Supervisor
L4  Facade     CMDC(公共 API 入口)
```

---

## 内置功能

### Plugin(6 个)

| Plugin | 说明 |
|--------|------|
| `SecurityGuard` | 拦截危险路径和系统命令,防止越权操作 |
| `EventLogger` | 记录所有 Agent 事件,便于调试和审计 |
| `HumanApproval` | HITL 审批流,工具调用前等待人工确认 |
| `MemoryLoader` | 加载 AGENTS.md 持久记忆并注入 System Prompt |
| `PatchToolCalls` | 自动修复悬空 tool_call(无对应 ToolMessage 的响应) |
| `PromptCache` | Anthropic 模型 prompt caching 支持,降低成本 |

### Tool(11 个)

| Tool | 说明 |
|------|------|
| `ReadFile` | 读取文件,支持 offset/limit 分页 |
| `WriteFile` | 写入文件 |
| `EditFile` | 精确字符串替换(str_replace 模式) |
| `Shell` | 执行 shell 命令,大输出自动存文件 |
| `Grep` | 正则搜索,支持 glob 文件过滤 |
| `ListDir` | 列出目录内容 |
| `Glob` | 模式匹配文件列表 |
| `Task` | 启动 SubAgent 子进程(OTP 进程级并发) |
| `WriteTodos` | 更新 Agent 的 Todo 列表 |
| `AskUser` | 暂停执行,等待用户输入 |
| `CompactConversation` | 手动触发上下文压缩 |

### 事件系统(22 种事件)

所有事件通过 `CMDC.EventBus` 广播,消费者通过 `CMDC.subscribe/1` 订阅:

```
session_start / session_end
stream_start / stream_delta / stream_stop
tool_start / tool_end / tool_batch_end
approval_required / approval_responded
todo_change
cost_update
compact_start / compact_end
subagent_start / subagent_end
memory_loaded
ask_user / user_responded
context_overflow
error
```

---

## MCP(Model Context Protocol)支持

```elixir
{:ok, pid} = CMDC.create_agent(
  model: "anthropic/claude-3-5-sonnet-20241022",
  api_key: System.get_env("ANTHROPIC_API_KEY"),
  mcp_servers: [
    %CMDC.MCP.Config{
      name: "filesystem",
      command: "npx",
      args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    }
  ]
)
```

---

## AI-Friendly 类型系统

CMDC 的核心差异化之一是「AI-Friendly 类型系统」,让 AI 生成的调用代码更准确:

```elixir
# 精确的 NimbleOptions schema,每个字段含类型 + 默认值 + 中文说明
%CMDC.Options{
  model: "anthropic/claude-3-5-sonnet-20241022",  # 必填
  system_prompt: "...",                             # 可选,nil 表示使用 BasePrompt
  tools: [CMDC.Tool.ReadFile],                      # 可选,Tool 模块列表
  plugins: [CMDC.Plugin.Builtin.SecurityGuard],     # 可选,Plugin 模块列表
  max_tokens: 8192,                                 # 可选,默认 8192
  max_turns: 10,                                    # 可选,默认 10,nil 表示无限制
  working_dir: "/tmp/workspace",                    # 可选,工具执行根目录
  skills_dirs: ["priv/skills"],                     # 可选,Skills SKILL.md 搜索目录
  memory_dir: "~/.cmdc/memory"                      # 可选,AGENTS.md 持久记忆目录
}
```

---

## 开发

```bash
# 测试
mix test

# 格式化
mix format

# 静态分析
mix credo --strict

# 类型检查
mix dialyzer

# 一键质量检查
mix quality.check
```

---

## 许可证

本项目采用 **Apache 2.0 + Commons Clause** 许可证。

- **允许**:学习、修改、自由使用(包括内部商业用途)、基于 CMDC 构建自己的应用/产品
- **不允许**:将 CMDC 本身作为托管服务、云服务或 SaaS 对外提供,或出售以 CMDC 功能为核心价值的产品

详见 [LICENSE](LICENSE)。商业授权合作请联系:glggsai@qq.com

---

## 文档

- [HexDocs API 参考](https://hexdocs.pm/cmdc)
- `llm.txt` — AI 快速参考(~200 行,API 签名 + 类型 + 示例)
- `llms-full.txt` — AI 完整参考(~800 行,含事件协议、Plugin/Tool 开发、已知陷阱)