# 5 分钟上手
把 CMDC 当作一个会话级 Agent 引擎:调一次 `create_agent/1` 拿到 pid,
之后所有交互都通过这个 pid 异步推进,事件经 `EventBus` 广播给订阅者。
---
## 安装
```elixir
def deps do
[
{:cmdc, "~> 0.4"}
]
end
```
获取依赖:
```bash
mix deps.get
```
---
## Hello World
最少 4 个调用就能完成一次完整对话——创建 → 提问 → 收回复 → 关闭:
```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)
```
`prompt/2` 是非阻塞的——它返回后 LLM 调用才开始;`collect_reply/2` 同步等
拿到本轮所有 assistant 文本拼接的字符串。需要边收边渲染请改用 `subscribe/1`。
---
## 流式订阅
订阅当前进程接收 `{:cmdc_event, session_id, event}` 消息:
```elixir
{:ok, session} = CMDC.create_agent(model: "anthropic:claude-sonnet-4-5")
CMDC.subscribe(session)
CMDC.prompt(session, "数到 5。")
stream_loop = fn loop ->
receive do
{:cmdc_event, _sid, {:message_delta, %{delta: text}}} ->
IO.write(text)
loop.(loop)
{:cmdc_event, _sid, {:agent_end, _msgs, _usage}} ->
:done
after
30_000 -> {:error, :timeout}
end
end
stream_loop.(stream_loop)
CMDC.stop(session)
```
完整事件清单见 [`CMDC.Event`](CMDC.Event.html)。订阅断网想补帧请用
`Options.event_buffer_size` 开启 ring buffer。
---
## 带工具的 Agent
CMDC 内置 11 个工具(读写文件 / shell / grep / glob / ls / 子代理派发 /
todo 跟踪 / 用户提问 / 上下文压缩 / 大结果分页)。声明 `:tools`
即可让 Agent 自主调用:
```elixir
{:ok, session} = CMDC.create_agent(
model: "anthropic:claude-sonnet-4-5",
tools: [
CMDC.Tool.ReadFile,
CMDC.Tool.WriteFile,
CMDC.Tool.Shell,
CMDC.Tool.Grep
],
working_dir: "/tmp/agent-workspace"
)
CMDC.prompt(session, "读取 /tmp/agent-workspace/notes.md,把 TODO 抽出来写到 todos.md")
{:ok, reply} = CMDC.collect_reply(session)
```
Shell / WriteFile 默认走 `Sandbox.Local`,所有文件路径限制在 `working_dir`
内(见 [Sandbox](CMDC.Sandbox.html))。生产环境强烈建议接 `Backend.Filesystem`
+ `virtual_mode: true`。
---
## 用 Plugin 加切面
Plugin 是把"切面逻辑"插入 Agent 13 个生命周期 hook 的标准方式:
```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
{:ok, session} = CMDC.create_agent(
model: "anthropic:claude-sonnet-4-5",
tools: [CMDC.Tool.Shell],
plugins: [{MyApp.AuditPlugin, []}]
)
```
CMDC 自带 16 个内置 Plugin(见 [Plugins(安全与控制)](CMDC.Plugin.html)
和 Plugins(优化与记忆)分组),覆盖审批 / 安全 / 内容拦截 / 长会话记忆 /
模型路由 / 大结果 offload / 反思 / 规划等典型场景。
---
## 中段干预(Steering)
发现方向不对想换条路?不需要 abort 重来——直接 `steer/2` 软中断:
```elixir
{:ok, session} = CMDC.create_agent(
model: "anthropic:claude-sonnet-4-5",
tools: [CMDC.Tool.Shell]
)
CMDC.prompt(session, "帮我用 100 行 Python 实现快排。")
# 中途改主意
ref = make_ref()
CMDC.steer(session, ref, "停,改成用 Elixir 实现,别用 Python。")
{:ok, reply} = CMDC.collect_reply(session)
```
正在执行的不可中断工具会跑完,可中断的工具被 `brutal_kill`,下一轮
LLM 调用看到合并后的新 prompt。完整选项见 [`CMDC`](CMDC.html) 的 `steer/2` 与
[`CMDC.Agent`](CMDC.Agent.html) 的状态行为表。
---
## HITL 审批
让人类在 Agent 调危险工具前点头:
```elixir
{:ok, session} = CMDC.create_agent(
model: "anthropic:claude-sonnet-4-5",
tools: [CMDC.Tool.Shell],
plugins: [
{CMDC.Plugin.Builtin.HumanApproval, [tools: ["shell"]]}
]
)
CMDC.subscribe(session)
CMDC.prompt(session, "在 /tmp 下创建一个 hello.txt 文件。")
receive do
{:cmdc_event, _sid, {:approval_required, %{id: id, tool: "shell", args: args}}} ->
IO.inspect(args, label: "Agent 想跑")
CMDC.approve(session, id) # 或 CMDC.reject(session, id)
end
{:ok, reply} = CMDC.collect_reply(session)
```
`approve_always` 可把同类命令加入 session 白名单,详见
[`CMDC.Plugin.Builtin.HumanApproval`](CMDC.Plugin.Builtin.HumanApproval.html)。
---
## 下一步
跑通上面五段你已经覆盖了 80% 的日常用法。继续深挖请看:
- [核心概念](concepts.html) — Agent / Session / Plugin / Tool / Backend 七大概念
- [Agent 状态机与事件](agent-loop.html) — 4 状态流转 + 完整事件清单
- [写一个 Plugin](plugins.html) — 13 hook × 8 action 矩阵 + 5 个完整范例
- [写一个 Tool](tools.html) — Tool behaviour + Sandbox 代理 + 错误处理
- [常见配方](cookbook.html) — 端到端组合范例(流式 UI / 长会话不失忆 / 多 Agent / Checkpoint / Telemetry)
- [升级指南](upgrading.html) — v0.2 → v0.3 → v0.4 各版本兼容边界