# anima CLI 使用指南

anima 是一个 CLI agent runner，提供完整的生命周期管理、状态持久化和交互式调试能力。每个 agent 运行独立的 PydanticAI 循环，并通过 MCP 服务器接口暴露实时交互和状态监控。

---

## 目录

- [快速开始](#快速开始)
- [环境变量](#环境变量)
- [配置](#配置)
- [命令参考](#命令参考)
  - [Launch（run, chat, spawn）](#launch-run-chat-spawn)
  - [Observe（list, status, inspect, logs, tree）](#observe-list-status-inspect-logs-tree)
  - [Control（approve, reject, resume, kill）](#control-approve-reject-resume-kill)
  - [Monitor（monitor, serve, talk）](#monitor-monitor-serve-talk)
  - [Tools（list, init, inspect）](#tools-list-init-inspect)
  - [Cleanup（rm, prune）](#cleanup-rm-prune)
- [输入文件格式](#输入文件格式)
- [Agent 状态机](#agent-状态机)
- [内置工具 (ctl.*)](#内置工具-ctl)
  - [`ctl_finish(result_ref?)`](#ctl_finishresult_ref)
  - [`ctl_fail(error)`](#ctl_failerror)
  - [`ctl_request_approval(reason)`](#ctl_request_approvalreason)
  - [`ctl_suspend_until(resume_after?)`](#ctl_suspend_untilresume_after)
  - [`ctl_spawn_subagent(persona_ref?, task)`](#ctl_spawn_subagentpersona_ref-task)
  - [`ctl_switch_persona(persona_ref)`](#ctl_switch_personapersona_ref)
- [预算与超时机制](#预算与超时机制)
- [MCP 服务器接口](#mcp-服务器接口)
- [错误码参考](#错误码参考)
- [退出码约定](#退出码约定)
- [实战示例](#实战示例)

---

## 快速开始

```bash
# 运行一个一次性任务（阻塞直到完成）
anima run \
  --system-prompt "You are a helpful assistant" \
  --model openai:gpt-5.2 \
  "Summarize the top Hacker News stories"

# 后台启动一个 daemon agent
anima spawn \
  --persona-file researcher.json \
  --mcp "uvx mcp-server-fetch" \
  "Monitor server logs every 5 minutes"

# 查看所有 agent
anima list

# 与运行中的 agent 交互
anima talk inst_abc123

# 收集结果
anima collect inst_abc123
```

---

## 环境变量

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `ANIMA_STATE` | `~/.anima/` | 状态存储根目录 |
| `ANIMA_MEMORY_PROVIDER` | `none` | Memory provider：`none`、`local`、`mcp` |

**状态目录结构：**

```
$ANIMA_STATE/
├── agents/<instance_id>/
│   ├── state.json              # 当前状态、指标、配置
│   ├── log.jsonl               # 事件日志（结构化 JSON 行）
│   ├── result.json             # 最终结果（仅终态 agent）
│   ├── mcp.sock                # per-agent MCP Unix domain socket
│   └── approval_response.json  # 审批响应通道
└── logs/
    └── anima.log               # 全局日志
```

---

## 配置

### 全局配置文件

全局配置使用 TOML，默认路径：`~/.anima/config.toml`。

可通过环境变量 `ANIMA_CONFIG` 覆盖配置文件路径：

```bash
export ANIMA_CONFIG="/path/to/custom-config.toml"
```

### 模型字符串格式

`--model` 与 `defaults.model` 使用统一格式：

```text
provider:model_name
```

示例：
- `openai:gpt-5.2`
- `anthropic:claude-sonnet-4-5-20250929`
- `ollama:qwen2.5-coder:14b`

### 配置优先级

模型解析采用简化优先级（高到低）：

1. CLI 参数（如 `--model`、`--llm-base-url`）
2. 进程环境变量（如 `ANIMA_DEFAULT_MODEL`、`OPENAI_BASE_URL`、`OPENAI_API_KEY`）
3. 全局配置 `defaults.model`（`~/.anima/config.toml` 或 `ANIMA_CONFIG` 指向路径）
4. PersonaSpec 的 `model`

> 说明：配置文件中的 `[env]` 会在启动时写入进程环境变量，但仅在该变量当前未设置时生效（不覆盖已有环境变量）。

### 配置文件中的 `[env]`

`config.toml` 使用 `[env]` 注入环境变量（统一替代旧的 provider 分段配置）：

```toml
[defaults]
model = "openai:gpt-5.2"

[env]
OPENAI_API_KEY = "sk-openai-..."
ANTHROPIC_API_KEY = "sk-ant-..."
OPENROUTER_API_KEY = "sk-or-..."

# 非标准 OpenAI 兼容端点（例如本地 vLLM/Ollama 网关）
OPENAI_BASE_URL = "http://localhost:11434/v1"
```

> PydanticAI 原生支持的 provider：`openai`、`anthropic`、`ollama`、`groq`、`deepseek`、`openrouter`。  
> 对于非标准端点，请在 `[env]` 中设置 `OPENAI_BASE_URL`，或运行 LiteLLM 代理后接入。

### Memory Provider 配置

> **注意:** Memory provider 支持已移除。以下为遗留接口说明。

Memory provider 决定 memory 操作的后端。配置优先级（高到低）：

1. `--memory-provider` CLI 参数
2. `ANIMA_MEMORY_PROVIDER` 环境变量
3. `memory.provider` 配置项
4. 默认值：`none`

```toml
[memory]
provider = "local"  # "none" | "local" | "mcp"
```

| Provider | 说明 |
|----------|------|
| `none` | 无 memory。memory 操作返回 `not_configured`。agent 正常运行。 |
| `local` | 文件系统后端（遗留）。 |
| `mcp` | 远程 MCP 后端。用于 opifex 组合部署。 |

### 配置示例

#### OpenAI

```bash
export OPENAI_API_KEY="sk-..."

anima run \
  --model openai:gpt-5.2 \
  "Summarize this repository"
```

#### Anthropic

```bash
export ANTHROPIC_API_KEY="sk-ant-..."

anima run \
  --model anthropic:claude-sonnet-4-5-20250929 \
  "Review API boundary risks"
```

#### Ollama

```bash
anima run \
  --model ollama:qwen2.5-coder:14b \
  --llm-base-url http://localhost:11434/v1 \
  "Write a Python CLI parser"
```

#### OpenRouter

```bash
export OPENROUTER_API_KEY="sk-or-..."

anima run \
  --model openrouter:openai/gpt-5.2-mini \
  "Generate edge-case test ideas"
```

#### vLLM

```bash
anima run \
  --model vllm:meta-llama/Llama-3.1-8B-Instruct \
  --llm-base-url http://localhost:8000/v1 \
  "Generate test cases for edge conditions"
```

---

## 命令参考

### 速查表

```
┌──────────┬────────────┬──────────────────────────┐
│ 分组     │ 命令       │ 说明                     │
├──────────┼────────────┼──────────────────────────┤
│ Launch   │ run        │ 一次性任务（阻塞）       │
│          │ chat       │ 交互式启动（默认会话清理） │
│          │ spawn      │ 后台 agent（立即返回）    │
├──────────┼────────────┼──────────────────────────┤
│ Observe  │ list       │ 列出所有 agent           │
│          │ status     │ 单个 agent 详情          │
│          │ inspect    │ 完整 spec/config         │
│          │ logs       │ 事件日志                 │
│          │ tree       │ 父子层级视图             │
├──────────┼────────────┼──────────────────────────┤
│ Control  │ approve    │ 批准审批请求             │
│          │ reject     │ 拒绝审批请求             │
│          │ resume     │ 恢复挂起 agent           │
│          │ kill       │ 终止 agent               │
├──────────┼────────────┼──────────────────────────┤
│ Monitor  │ monitor    │ TUI 实时仪表盘           │
│          │ serve      │ 远程 MCP 服务            │
│          │ talk       │ 交互式会话               │
├──────────┼────────────┼──────────────────────────┤
│ Tools    │ tools list │ 列出工具预设             │
│          │ tools init │ 初始化预设配置           │
│          │ tools inspect │ 检查工具配置          │
├──────────┼────────────┼──────────────────────────┤
│ Cleanup  │ rm         │ 删除 agent 状态          │
│          │ prune      │ 清理终态 agent           │
├──────────┼────────────┼──────────────────────────┤
│ 别名     │ ls=list    │ ps=status  top=monitor   │
└──────────┴────────────┴──────────────────────────┘
```

### Launch（run, chat, spawn）

#### 三态启动模型（run/chat/spawn）

`anima` 的启动命令分为三个动词，分别覆盖一次性执行、交互式启动和后台运行：

| 命令 | 模式 | 返回时机 | 默认生命周期 | 典型用途 |
|------|------|----------|--------------|----------|
| `anima run` | fire-and-forget（前台阻塞执行） | 任务完成后返回 | `ephemeral` | 单次任务，拿结果就结束 |
| `anima chat` | interactive session（即时对话） | 分离/退出后返回 | 内部固定 `ephemeral` | 立即进入会话，边聊边做 |
| `anima spawn` | background（后台守护） | 启动成功后立即返回 | `daemon` | 长时间运行、持续服务 |

#### `anima run` — 运行一次性任务

阻塞执行，直到 agent 完成、失败或超时。始终使用 `lifecycle=ephemeral`。

```bash
anima run [OPTIONS] TASK
```

**参数：**

| 参数 | 说明 |
|------|------|
| `TASK` | 传递给 agent 的任务文本（必需） |

**选项：**

| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `--persona-file` | 路径 | — | PersonaSpec JSON 文件（设置启动时的初始 persona；运行时切换暂未实现） |
| `-s, --system-prompt` | 字符串 | — | 内联 system prompt（替代 `--persona-file`；设置启动时的初始 persona；运行时切换暂未实现） |
| `--job-file` | 路径 | — | JobSpec JSON 文件（CLI 选项优先级更高） |
| `--model` | 字符串 | — | LLM 模型 ID（覆盖 PersonaSpec.model） |
| `--llm-base-url` | URL | — | LLM API 地址，如 `http://localhost:4000/v1` |
| `--mcp` | 字符串 | — | MCP 服务器，可重复。`"command args"` (stdio) 或 `http[s]://url` (SSE) |
| `--tools` | 字符串 | — | 工具预设名称，可重复。从配置文件 `[tools.<name>]` 解析 MCP 配置 |
| `--timeout` | 字符串 | — | 超时，如 `5m`、`2h`、`30s` |
| `--max-turns` | 整数 | — | 最大循环轮次 |
| `--max-tokens` | 整数 | — | Token 预算上限 |
| `--context-mode` | 选项 | `isolated` | `isolated` 或 `shared` |
| `--context-bundle` | 路径 | — | ContextBundle JSON 文件（需配合 `--context-mode shared`） |
| `--instance-id` | 字符串 | 自动生成 | 幂等键（不指定时自动生成 UUID） |
| `--memory-provider` | 选项 | `none` | Memory provider：`none`、`local`、`mcp` |
| `--completion-policy` | 选项 | `explicit` | `explicit` 或 `auto` |
| `--token-file` | 路径 | — | CapabilityToken JSON 文件 |
| `--sandbox` | 标志 | — | 启用沙箱（所有 MCP stdio 服务器） |
| `--no-sandbox` | 标志 | — | 强制禁用沙箱（覆盖配置） |
| `--sandbox-allow` | 字符串 | — | 授予能力：`fs:<path>`、`net`、`net:<domain>`（可重复，隐含 `--sandbox`） |
| `--json` | 标志 | 关 | 机器可读 JSON 输出 |
| `--verbose / --quiet` | 标志 | `--quiet` | 详细或精简输出 |

**预算优先级**（由高到低）：
1. `--max-tokens` CLI 选项
2. `JobSpec.max_tokens`
3. `PersonaSpec.budget`
4. 无限制

**沙箱优先级：**

```
--no-sandbox          → off（覆盖一切）
--sandbox             → on（CLI 覆盖）
config tools.X.sandbox → on（该预设）
default               → off
```

无 PersonaSpec 参与。`--sandbox-allow` 全局应用于所有沙箱化的 MCP 服务器（威胁模型是 agent，而非工具）。

**沙箱能力语法：**

| 格式 | 说明 |
|------|------|
| `fs:<path>` | 授予文件系统访问（路径树） |
| `net` | 授予所有网络访问 |
| `net:<domain>` | 授予特定域名网络访问 |

**沙箱默认策略：**

当启用 `--sandbox` 但未指定 `--sandbox-allow`：

| 能力 | 默认值 |
|------|--------|
| 文件系统读取 | 拒绝敏感路径（~/.ssh、~/.aws、~/.gnupg、~/.config） |
| 文件系统写入 | 仅允许 /tmp |
| 网络出站 | 全部拒绝 |
| 进程创建 | 全部拒绝 |

**合并行为：**

CLI `--sandbox-allow` 与配置 `sandbox_allow` **合并**（累加）：

```bash
# 配置有 sandbox_allow = ["fs:/tmp"]
anima run --sandbox --sandbox-allow net --tools filesystem "task"
# 实际：fs:/tmp + net
```

**重要：** 沙箱仅适用于 MCP stdio 服务器（`MCPServerStdio`，来自 `--mcp "cmd args"` 或 `--tools <preset>`）。HTTP/SSE 服务器（`MCPServerSSE`，来自 `--mcp https://...`）已经是远程服务器，永不包装。

**JSON 输出：**

```json
{
  "instance_id": "inst_abc12345",
  "persona": "researcher",
  "model": "openai:gpt-5.2",
  "final_state": "completed",
  "token_usage": {
    "prompt_tokens": 5000,
    "completion_tokens": 1200,
    "total_tokens": 6200
  },
  "result_ref": null,
  "error": null
}
```

---

#### `anima chat` — 启动并立即进入交互会话

`anima chat` 会先启动一个 `ephemeral` agent，然后立即附着到交互会话：

```bash
anima chat [OPTIONS] TASK
```

默认行为是会话结束后自动清理该 agent；如果希望保留实例，可使用 `--keep` 或会话内输入 `/detach`。

**选项：**

| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `--persona-file` | 路径 | — | PersonaSpec JSON 文件（设置启动时的初始 persona；运行时切换暂未实现） |
| `-s, --system-prompt` | 字符串 | — | 内联 system prompt（替代 `--persona-file`；设置启动时的初始 persona；运行时切换暂未实现） |
| `--job-file` | 路径 | — | JobSpec JSON 文件（CLI 选项优先级更高） |
| `--model` | 字符串 | — | LLM 模型 ID（覆盖 PersonaSpec.model） |
| `--llm-base-url` | URL | — | LLM API 地址，如 `http://localhost:4000/v1` |
| `--mcp` | 字符串 | — | MCP 服务器，可重复。`"command args"` (stdio) 或 `http[s]://url` (SSE) |
| `--tools` | 字符串 | — | 工具预设名称，可重复。支持逗号分隔或多次声明 |
| `--timeout` | 字符串 | — | 超时，如 `5m`、`2h`、`30s` |
| `--max-turns` | 整数 | — | 最大循环轮次 |
| `--max-tokens` | 整数 | — | Token 预算上限 |
| `--context-mode` | 选项 | `isolated` | `isolated` 或 `shared` |
| `--context-bundle` | 路径 | — | ContextBundle JSON 文件（需配合 `--context-mode shared`） |
| `--instance-id` | 字符串 | 自动生成 | 幂等键（不指定时自动生成 UUID） |
| `--memory-provider` | 选项 | `none` | Memory provider：`none`、`local`、`mcp` |
| `--completion-policy` | 选项 | `explicit` | `explicit` 或 `auto` |
| `--token-file` | 路径 | — | CapabilityToken JSON 文件 |
| `--sandbox / --no-sandbox` | 标志 | `--sandbox` | MCP stdio 工具沙箱开关 |
| `--sandbox-allow` | 字符串 | — | 授予能力：`fs:<path>`、`net`、`net:<domain>`（可重复） |
| `--keep / --no-keep` | 标志 | `--no-keep` | 退出会话后是否保留该实例 |
| `--json` | 标志 | `--no-json` | 机器可读输出 |

**会话控制（chat）**

| 操作 | 效果 |
|------|------|
| 输入消息 + 回车 | 发送一轮消息并等待响应 |
| `/stop` | 请求停止当前 turn（协作式取消） |
| `/detach` | 立即分离并保留实例（escape hatch） |
| `/quit` | 分离会话；若未 `--keep` 且未 `/detach`，会在退出后清理实例 |
| `Ctrl-C` / `Ctrl-D` | 分离会话，后续保留/清理由 `--keep` 与 `/detach` 决定 |

**示例：**

```bash
# 直接进入会话；退出后默认自动清理
anima chat -s "You are a strict reviewer" "Review src/anima/shell/cli.py"

# 会话结束后保留实例，便于后续 anima talk / inspect / logs
anima chat --keep --tools shell "Investigate flaky tests"
```

---

#### `anima spawn` — 后台启动 agent

非阻塞启动，成功后立即返回 `instance_id`。

```bash
anima spawn [OPTIONS] TASK
```

**生命周期默认值已更新：** `--lifecycle` 默认为 `daemon`（可显式切换为 `ephemeral`）。

| 选项 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `--persona-file` | 路径 | — | PersonaSpec JSON 文件（设置启动时的初始 persona；运行时切换暂未实现） |
| `-s, --system-prompt` | 字符串 | — | 内联 system prompt（替代 `--persona-file`；设置启动时的初始 persona；运行时切换暂未实现） |
| `--job-file` | 路径 | — | JobSpec JSON 文件（CLI 选项优先级更高） |
| `--model` | 字符串 | — | LLM 模型 ID（覆盖 PersonaSpec.model） |
| `--llm-base-url` | URL | — | LLM API 地址 |
| `--mcp` | 字符串 | — | MCP 服务器，可重复 |
| `--tools` | 字符串 | — | 工具预设名称，可重复 |
| `--timeout` | 字符串 | — | 超时，如 `5m`、`2h`、`30s` |
| `--max-turns` | 整数 | — | 最大循环轮次 |
| `--max-tokens` | 整数 | — | Token 预算上限 |
| `--context-mode` | 选项 | `isolated` | `isolated` 或 `shared` |
| `--context-bundle` | 路径 | — | ContextBundle JSON 文件 |
| `--instance-id` | 字符串 | — | 幂等键 |
| `--memory-provider` | 选项 | `none` | Memory provider：`none`、`local`、`mcp` |
| `--completion-policy` | 选项 | `explicit` | `explicit` 或 `auto` |
| `--token-file` | 路径 | — | CapabilityToken JSON 文件 |
| `--lifecycle` | 选项 | `daemon` | `daemon` 或 `ephemeral` |
| `--sandbox / --no-sandbox` | 标志 | `--sandbox` | MCP stdio 工具沙箱开关 |
| `--sandbox-allow` | 字符串 | — | 沙箱能力，可重复 |
| `--rm` | 标志 | 关 | 任务结束后删除实例状态（默认保留） |
| `--json` | 标志 | 关 | 机器可读 JSON 输出 |

**示例：**

```bash
# 默认 daemon（无需再写 --lifecycle daemon）
anima spawn --persona-file monitor.json "Watch error logs and report hourly"

# 显式切换为 ephemeral
anima spawn --lifecycle ephemeral --timeout 20m "One-shot background indexing"
```

---
### 工具预设配置（--tools）

`--tools` 选项从 `config.toml` 读取预定义的 MCP 服务器配置，简化命令行参数。

#### 配置结构

编辑 `~/.anima/config.toml`（或通过 `ANIMA_CONFIG` 指定路径）：

```toml
[tools.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
description = "Local filesystem access"

[tools.shell]
command = "uvx"
args = ["mcp-shell-server"]
env."ALLOW_COMMANDS" = "ls,cat,echo"
description = "Shell command execution"

[tools.fetch]
command = "uvx"
args = ["mcp-server-fetch"]
description = "Fetch web content"

[tools.github]
command = "github-mcp-server"
args = ["stdio"]
env."GITHUB_PERSONAL_ACCESS_TOKEN" = "YOUR_TOKEN_HERE"
description = "GitHub API integration"
```

#### 使用示例

```bash
# 单个工具预设
anima run --tools filesystem "List files in /tmp"

# 带沙箱和额外能力
anima run --sandbox --sandbox-allow net --tools fetch "Search the web"

# 多个预设组合
anima spawn --tools filesystem --tools shell "Monitor logs and run diagnostics"

# 等价于手动指定 --mcp
anima run --mcp "npx -y @modelcontextprotocol/server-filesystem /tmp" \
           --mcp "uvx mcp-shell-server" "List files"
```

#### 配置字段

| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `command` | 字符串 | 是 | 可执行命令 |
| `args` | 字符串数组 | 否 | 命令参数 |
| `sandbox` | 布尔 | 否 | 启用沙箱 |
| `sandbox_allow` | 字符串数组 | 否 | 能力列表（`fs:<path>`、`net`、`net:<domain>`） |
| `description` | 字符串 | 否 | 人类可读描述 |

#### 配置文件示例

参见 `config.toml.example` 获取完整模板：

```bash
# 复制示例配置
cp config.toml.example ~/.anima/config.toml

# 编辑配置
vim ~/.anima/config.toml
```

---

### Observe（list, status, inspect, logs, tree）

#### `anima list` — 列出所有 agent
#### `anima list` — 列出所有 agent

```bash
anima list [--state STATE] [--json]
```

| 选项 | 说明 |
|------|------|
| `--state` | 按状态过滤（如 `running`、`completed`） |
| `--json` | JSON 输出 |

**别名：** `anima ls`

ID 显示策略：
- 表格中的 `INSTANCE_ID` 使用"最短唯一前缀"（minimum 12 字符）。
- 若多个 ID 在当前长度冲突，会自动递增长度直到唯一，避免固定 8 位截断歧义。

**Stale Agent 自动清理：**

当 `anima ls` 显示 `running` agent 时，系统会自动检测每个 agent 的进程是否仍然存活。
如果检测到进程已终止（PID 不存在），系统会自动将其状态转换为 `failed`，错误消息为
`"Stale agent state: process terminated unexpected"`。用户无需手动处理这些崩溃的 agent。

**表格输出示例：**

```
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━┓
┃ INSTANCE_ID    ┃ STATE    ┃ PERSONA    ┃ LIFECYCLE ┃ UPTIME ┃ TOKENS ┃
┣━━━━━━━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━╋━━━━━━━━┫
┃ inst_abc123    ┃ running  ┃ researcher ┃ ephemeral ┃ 2m30s  ┃ 6200   ┃
┃ inst_def456     ┃ completed┃ coder      ┃ ephemeral ┃ 5m12s  ┃ 15000  ┃
┗━━━━━━━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━┻━━━━━━━━┛
```

---
#### `anima status` — 查看单个 agent 详情
#### `anima status` — 查看单个 agent 详情

```bash
anima status INSTANCE_ID [--json]
```

`INSTANCE_ID` 支持前缀匹配：`inst_abc` 会匹配 `inst_abc12345...`。

**别名：** `anima ps`

**Stale Agent 自动清理：**

如果 agent 状态显示为 `running` 但进程已终止，`anima status` 会自动将其转换为 `failed`
状态，错误消息为 `"Stale agent state: process terminated unexpectedly"`。

**面板输出示例：**

```
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Agent Status                                               ┃
┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ Instance ID: inst_abc12345                                 ┃
┃ State:      running                                        ┃
┃ Persona:    researcher                                     ┃
┃ Lifecycle:  ephemeral                                      ┃
┃ Tokens:     5000 prompt / 1200 comp / 6200                 ┃
┃ Uptime:     2m30s                                          ┃
┃ Parent:     inst_parent123                                  ┃
┃ Children:   inst_child1, inst_child2                       ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
```

---
#### `anima tree` — 层级树视图

```bash
anima tree [--state STATE] [--json]
```

```
Agent Hierarchy
├── inst_parent1 running researcher
│   ├── inst_child1 running coder
│   │   └── inst_grandchild1 completed reviewer
│   └── inst_child2 suspended reviewer
└── inst_root2 completed monitor
```

---

#### `anima inspect` — 完整规格详情

```bash
anima inspect INSTANCE_ID [--json]
```

显示 Identity、State、Hierarchy、Process、Budget、Token Usage、Tools Called、Timestamps 等多个面板。JSON 模式输出完整 AgentStateData。

---

#### `anima logs` — 查看事件日志

```bash
anima logs INSTANCE_ID [--tail N] [--follow] [--json]
```

| 选项 | 说明 |
|------|------|
| `--tail N` | 只显示最后 N 条 |
| `--follow` | 实时跟踪（类似 `tail -f`） |
| `--json` | 原始 JSONL 输出 |

**日志格式 (JSONL)：**

```json
{"ts": "2026-02-28T10:30:01Z", "event": "state_change", "from": "pending", "to": "running"}
{"ts": "2026-02-28T10:30:02Z", "event": "turn", "turn": 1, "tokens": {"prompt": 1500, "completion": 300}}
{"ts": "2026-02-28T10:30:03Z", "event": "tool_call", "tool": "read_file", "args": {"path": "src/main.py"}}
```

---

### Control（approve, reject, resume, kill）

#### `anima approve` — 批准审批请求

```bash
anima approve INSTANCE_ID [--note TEXT] [--json]
```

**前提：** Agent 必须处于 `awaiting_approval` 状态。

**效果：** `awaiting_approval` → `running`。Agent 阻塞的 `ctl_request_approval()` 调用返回 `{"approved": true, "note": ...}`。

---

#### `anima reject` — 拒绝审批请求

```bash
anima reject INSTANCE_ID [--reason TEXT] [--json]
```

**前提：** Agent 必须处于 `awaiting_approval` 状态。

**效果：** `awaiting_approval` → `running`。Agent 阻塞的 `ctl_request_approval()` 调用返回 `{"approved": false, "note": ...}`，Agent 可以根据拒绝原因重新规划。

---

#### `anima resume` — 恢复挂起的 agent

```bash
anima resume INSTANCE_ID [--json]
```

**前提：** Agent 必须处于 `suspended` 状态。

**效果：** `suspended` → `running`。

---

#### `anima kill` — 终止 agent

```bash
# 单个 agent
anima kill INSTANCE_ID [--json]

# 批量
anima kill --all [--state STATE...] [--yes] [--json]
```

| 选项 | 说明 |
|------|------|
| `--all` | 终止所有可杀的 agent |
| `--state` | 按状态过滤（可重复：`running`、`suspended`、`awaiting_approval`） |
| `--yes` | 跳过确认提示 |
| `--json` | JSON 输出 |

**可杀状态：** `running`、`suspended`、`awaiting_approval`

**处理方式：** 向 agent 进程发送 `SIGTERM`，agent 进入 grace finalization 阶段。

---

### Monitor（monitor, serve, talk）

#### `anima monitor` — 实时 TUI 仪表盘

```bash
anima monitor [--refresh SECONDS] [--once]
```

| 选项 | 默认 | 说明 |
|------|------|------|
| `--refresh` | 1.0 | 刷新间隔（秒） |
| `--once` | 关 | 渲染一帧后退出 |

**别名：** `anima top`

**颜色编码：**

| 状态 | 颜色 |
|------|------|
| `running` | 绿色 |
| `completed` | 蓝色 |
| `failed` | 红色 |
| `killed` | 黄色 |
| `suspended` | 青色 |
| `awaiting_approval` | 品红 |

按 `q` 退出仪表盘。

实现备注（对应当前修复）：
- `q` 为单键立即退出（无需回车），通过 raw TTY 读取实现。
- 列宽使用 Rich 自适应布局（无固定宽度），在窄/宽终端均可显示。
- 退出时会恢复终端模式（正常退出、异常、信号中断路径均覆盖）。

---

#### `anima serve` — 启动远程 MCP 服务器

```bash
anima serve [--port PORT] [--host HOST] [--json]
```

| 选项 | 默认 | 说明 |
|------|------|------|
| `--port` | 8420 | 监听端口 |
| `--host` | 127.0.0.1 | 绑定地址 |
| `--json` | 关 | 输出 JSON 启动信封 |

通过 SSE 传输暴露 6 个 MCP 工具：`anima.spawn`、`anima.list`、`anima.status`、`anima.interact`、`anima.collect`、`anima.kill`。

---

#### `anima talk` — 交互式会话
#### `anima talk` — 交互式会话

```bash
anima talk INSTANCE_ID [--json]
```

**前提：** Agent 必须处于 `running`、`suspended` 或 `awaiting_approval` 状态。

**Stale Agent 检测：**

如果 agent 状态为 `running` 但进程已终止，`anima talk` 会：
1. 自动将 agent 状态转换为 `failed`，错误消息为 `"Stale agent state: process terminated unexpectedly"`
2. 退出并显示错误信息，无法连接到已终止的进程

**流式输出（Streaming）：**

`anima talk` 自动检测 agent 是否支持 SSE 流式输出。新版本 agent 会实时推送文本片段，
用户可以看到渐进式输出；旧版本 agent（<0.1.0）自动回退到阻塞模式（等待完整响应后显示）。

**流式检测机制：**
- 客户端在首次 interact turn 时探测 `/stream` 端点
- 如果返回 404/405 或连接失败，缓存 `streaming_supported=false`
- 后续 turns 使用阻塞模式（等待完整响应）
- 流式模式启用时：建立 SSE 连接，消费事件直到终端事件（`done`/`error`）

**`/stop` 行为：**
- 调用 `anima.stop_turn()` 设置停止标志
- Agent 在节点边界检测停止信号（协作式取消）
- Agent 保留已输出的内容，发送 `done` 事件（`stop_reason: "stopped"`）
- Agent 进程继续运行，可接受新消息或 `/quit` 分离

**会话控制：**

| 操作 | 效果 |
|------|------|
| 输入消息 + 回车 | 通过 `anima.interact()` 发送，agent 处理一轮后返回响应 |
| `/stop` | 请求停止当前 turn（agent 在节点边界停止，保留已输出内容） |
| `/quit` | 分离会话（agent 继续运行） |
| `Ctrl-C` | 分离会话（agent 继续运行） |
| `Ctrl-D` | 分离会话（agent 继续运行） |

**会话示例：**

```
Attaching to agent inst_abc123...
State: running
Type your message and press Enter. /quit to exit. Ctrl-C to detach.

You > What's your current progress?
agent> I've processed 50% of the data files...
Turn: 5

You > /quit
Detaching from agent (agent continues)
```

---
### Cleanup（rm, prune）

### Tools（list, init, inspect）

#### `anima tools list` — 列出工具预设

```bash
anima tools list [--json]
```

| 选项 | 说明 |
|------|------|
| `--json` | JSON 输出 |

列出 `~/.anima/config.toml` 中配置的工具预设。

**表格输出示例：**

```
┏━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━┓
┃ Name       ┃ Command                                            ┃ Description    ┃ Sandbox ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━┩
│ filesystem │ npx -y @modelcontextprotocol/server-filesystem /tmp│ Local files    │ false  │
│ shell      │ uvx mcp-shell-server                               │ Shell commands │ true   │
└────────────┴─────────────────────────────────────────────────────┴────────────────┴────────┘
```

若未配置预设，显示配置指引。

---

#### `anima tools init` — 初始化工具预设

```bash
anima tools init [PRESET_NAME] [--json]
```

| 参数 | 说明 |
|------|------|
| `PRESET_NAME` | 预设名称（可选） |

| 选项 | 说明 |
|------|------|
| `--json` | JSON 输出 |

创建工具预设配置脚手架。（占位命令，实现待完成）

---

#### `anima tools inspect` — 检查工具配置

```bash
anima tools inspect [--instance INSTANCE_ID] [--json]
```

| 选项 | 说明 |
|------|------|
| `--instance` | Instance ID，检查该 agent 的工具配置 |
| `--json` | JSON 输出 |

显示指定 agent 或当前全局配置的工具配置。（占位命令，实现待完成）

---
#### `anima rm` — 删除 agent 状态

```bash
anima rm INSTANCE_ID [--force] [--json]
anima rm --all [--force] [--yes] [--json]
```

| 选项 | 适用范围 | 说明 |
|------|----------|------|
| `--all` | 批量删除 | 删除所有可删除的 agent（终态默认可删） |
| `--force` | 单个 / 批量 | 非终态时先 kill，再删除（等价于 kill + rm） |
| `--yes` | 仅 `--all` | 跳过确认提示，直接执行批量删除 |
| `--json` | 单个 / 批量 | 以机器可读 JSON 输出结果 |

**行为：**
- 默认：仅删除终态 agent（completed / failed / killed）
- `--force`：先 kill → 等待 grace → 删除
- `--all`：批量模式；不加 `--yes` 时会进入确认流程
- `INSTANCE_ID` 与 `--all` 互斥，不能同时使用
- 必须二选一：`INSTANCE_ID` 或 `--all`

```bash
# 交互式批量删除（先预览，再确认）
anima rm --all

# 批量强制删除（包含非终态，跳过确认）
anima rm --all --force --yes

# JSON 输出（适合脚本）
anima rm --all --force --yes --json
```

---

#### `anima prune` — 批量清理终态 agent

```bash
anima prune [--state STATE...] [--older-than DAYS] [--dry-run] [--yes] [--json]
```

| 选项 | 默认 | 说明 |
|------|------|------|
| `--state` | 全部终态 | 按终态过滤（`completed`、`failed`、`killed`） |
| `--older-than` | — | 按天数过滤 |
| `--dry-run` | 开 | 仅预览，不删除（默认行为） |
| `--yes` | 关 | 跳过确认直接删除 |

```bash
# 预览 7 天前的已完成 agent
anima prune --state completed --older-than 7

# 确认删除
anima prune --state completed --older-than 7 --yes
```

---
## 输入文件格式

### PersonaSpec (`--persona-file`)

定义 agent 的身份和能力。

```json
{
  "spec_version": "0.1.0",
  "name": "researcher",
  "system_prompt": "You are a research assistant...",
  "model": "openai:gpt-5.2",
  "budget": 50000,
  "can_spawn": false,
  "model_params": {
    "temperature": 0.7
  }
}
```

| 字段 | 类型 | 必需 | 说明 |
|------|------|------|------|
| `spec_version` | `"0.1.0"` | 是 | 固定版本号 |
| `name` | 字符串 | 是 | 显示名称 |
| `system_prompt` | 字符串 \| null | 否 | 系统提示词。省略或 `null` 均表示不发送 system prompt |
| `model` | 字符串 | 是 | LLM 模型 ID |
| `budget` | 整数 | 否 | Token 预算（≥0） |
| `can_spawn` | bool \| list | 否 | 子 agent 权限。`false`=禁止，`true`=任意，`["worker"]`=白名单 |
| `model_params` | 对象 \| null | 否 | LLM 模型参数（如 temperature、top_p）。透传至 LLM 调用 |
| `tools_profile` | 字符串 \| null | 否 | 工具配置集名称。独立模式：逗号分隔的工具预设名称，从 `config.toml` `[tools.*]` 解析（如 `"filesystem,shell"`）。联合模式（带 CapabilityToken）：原样传递给 tela |
| `sandbox` | `str \| None` | 否 | 预留字段（用于未来 agent 进程沙箱）。**不参与** MCP 沙箱决策。 |

**独立模式 `tools_profile` 解析：**

在独立模式下（无 nervus/tela，无 CapabilityToken），`tools_profile` 字段支持逗号分隔的多个预设名称：

```json
{
  "tools_profile": "filesystem,shell,fetch"
}
```

解析过程：
1. 读取 `~/.anima/config.toml`（或 `ANIMA_CONFIG` 指定路径）
2. 对每个预设名称，查找 `[tools.<name>]` 配置段
3. 将每个预设展开为对应的 MCP 服务器配置
4. 等价于 `--tools filesystem --tools shell --tools fetch`

示例：

```toml
# config.toml
[tools.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]

[tools.shell]
command = "uvx"
args = ["mcp-shell-server"]

[tools.fetch]
command = "uvx"
args = ["mcp-server-fetch"]
```

```json
// PersonaSpec
{
  "tools_profile": "filesystem,shell"
}
// 等价于 CLI: --tools filesystem --tools shell
```

**联合模式（带 CapabilityToken）：**

当 anima 通过 `--token-file` 接收 CapabilityToken 时，`tools_profile` 字段原样传递给 tela，不进行本地解析。tela 将其作为单一 profile 名称处理。

注：沙箱配置通过 CLI 参数（`--sandbox`、`--sandbox-allow`）或工具预设配置（`config.toml` 中的 `sandbox`、`sandbox_allow`）指定，而非 PersonaSpec。

---

### JobSpec (`--job-file`)

定义一次任务的执行参数。CLI 选项优先级高于 JobSpec 字段。

```json
{
  "job_version": "0.1.0",
  "persona_ref": "researcher",
  "instance_id": "job-2026-03-01-001",
  "timeout": "10m",
  "max_turns": 50,
  "max_tokens": 100000,
  "lifecycle": "ephemeral",
  "completion_policy": "explicit",
  "side_effect_policy": "approval_required",
  "finalize_grace_budget": 500,
  "max_depth": 3
}
```

| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `job_version` | `"0.1.0"` | 必需 | 固定版本号 |
| `persona_ref` | 字符串 | 必需 | Persona 身份引用，格式为 `<persona_id>@<spec_digest>` |
| `instance_id` | 字符串 | 必需 | 幂等键 |
| `timeout` | 字符串 | — | 超时，如 `10m`、`2h` |
| `max_turns` | 整数 | — | 最大轮次（≥1） |
| `max_tokens` | 整数 | — | Token 上限（≥1） |
| `completion_policy` | 枚举 | `explicit` | `explicit` 或 `auto` |
| `lifecycle` | 枚举 | `ephemeral` | `ephemeral` 或 `daemon` |
| `context_mode` | 枚举 | `isolated` | `isolated` 或 `shared` |
| `side_effect_policy` | 枚举 | `allow` | `read_only`、`approval_required`、`allow`（按 most_restrictive 合并） |
| `finalize_grace_budget` | 整数 | 500 | Grace 阶段的 token 配额（≥0） |
| `max_depth` | 整数 | 3 | 子 agent 最大嵌套深度（≥1） |

> 运行时兼容性说明（deferred scope）：`spec_digest` 当前仍会写入 `state.json`（由 `src/anima/shell/state.py` 持久化，`src/anima/shell/mcp_serve.py` 传递）。
> 归属：anima shell 状态持久化边界。收敛标准：同一步删除 `AgentStateData.spec_digest`、去除 `create_agent_state(..., spec_digest=...)` 传递，并提供旧 `state.json` 的迁移/兼容证明。

---

## Agent 状态机

```
                          ┌─────────────────┐
                          │    pending       │
                          └────────┬────────┘
                                   │ start
                          ┌────────▼────────┐
                     ┌────│    running       │────┐
                     │    └──┬─────┬─────┬──┘    │
                     │       │     │     │        │
                suspend   request  │   finish/   kill
                     │   approval  │   auto_complete
                     │       │     │        │
              ┌──────▼──┐  ┌▼─────▼──┐  ┌──▼─────────┐
              │suspended │  │awaiting │  │ completed   │
              └──┬───┬──┘  │approval │  └─────────────┘
                 │   │     └──┬───┬──┘
              resume kill  approve reject    ┌──────────┐
                 │   │      │     │          │ failed   │
                 │   │      │     └─────────►│          │
                 │   │      │                └──────────┘
                 │   │      └──► running
                 │   │                       ┌──────────┐
                 │   └──────────────────────►│ killed   │
                 └──► running                └──────────┘
```

**终态：** `completed`、`failed`、`killed`（不可再转换）

**完整转换表（16 条）：**

| 当前状态 | 事件 | 目标状态 |
|----------|------|----------|
| pending | start | running |
| running | finish | completed |
| running | auto_complete | completed |
| running | fail | failed |
| running | timeout | failed |
| running | budget_exhausted | failed |
| running | max_turns | failed |
| running | crash | failed |
| running | suspend | suspended |
| running | request_approval | awaiting_approval |
| running | kill | killed |
| suspended | resume | running |
| suspended | kill | killed |
| awaiting_approval | approve | running |
| awaiting_approval | reject | running |
| awaiting_approval | kill | killed |

---

## 内置工具 (ctl.*)

每个 agent 自动注册以下控制工具：

### `ctl_finish(result_ref?)`

标记任务完成。状态 → `completed`。`result_ref` 可选，用于引用外部结果文件。

### `ctl_fail(error)`

标记任务失败。状态 → `failed`。`error` 为错误描述字符串。

### `ctl_request_approval(reason)`

请求人工审批。状态 → `awaiting_approval`。调用阻塞直到 `anima approve` 或 `anima reject`。

返回值：`{"approved": true/false, "note": "..."}`

### `ctl_suspend_until(resume_after?)`

挂起 agent。状态 → `suspended`。`resume_after` 为可选的恢复延迟时间。通过计时器到期或 `anima resume` 恢复。

### `ctl_spawn_subagent(persona_ref?, task)`

创建子 agent。子 agent 继承父 agent 的 MCP 连接和 trace_id，记录在父子树中。受 `max_depth` 限制。

**参数:**
- `persona_ref` (string, 可选): **standalone 模式:** PersonaSpec 文件的相对路径（如 `personas/helper.json`）。省略或 `null` 时，子 agent 继承父 agent 的 persona。**Nervus 集成:** 将支持通过 registry 解析 persona_ref（未实现）。
- `task` (string, 必需): 子 agent 的任务字符串。

**调用约定:**
- 位置参数仍按 `(persona_ref, task)`。
- 当省略 `persona_ref` 时，建议使用关键字参数：`ctl_spawn_subagent(task="...")`，避免参数歧义。

**安全限制 (standalone 模式):**
- 仅支持相对路径
- 拒绝绝对路径和路径遍历（如 `../secrets.json`）
- 从当前工作目录加载 PersonaSpec JSON 文件

### `ctl_switch_persona(persona_ref)` [暂未实现]

> **状态:** 此功能正在规划中，尚未实现。Persona 目前在 agent 启动后固定，无法运行时切换。

在会话中切换 agent 的 persona。Agent 将在下一轮次使用新的 persona 重建，同时保留对话历史。

**参数:**
- `persona_ref` (string, 必需): PersonaSpec 文件路径（如 `personas/new-persona.json`）。

**计划行为 (实现后):**
- Persona 切换将在下一轮次边界应用（协作式，非立即生效）
- Agent 将通过 `AgentFactory.create()` 使用新 persona 重建
- 对话历史 (`message_history`) 将在切换后保留
- 轮次计数器、token 统计和 MCP 服务器状态将保留
- 当前轮次中正在进行的工具调用不会被中断
- 同时只能有一个待处理的 persona 切换；后续请求会被拒绝，直到待处理切换完成

**返回值 (实现后):**
- 成功: `"Persona switched to: <persona_name>. Will take effect at next turn."`
- 失败: 以 `"Error:"` 为前缀的字符串消息

**使用场景 (实现后):**
- 在 `anima talk` 会话中动态切换 persona 以适应不同任务阶段
- 从代码生成模式切换到审查模式，无需重启 agent
- 在 daemon 生命周期 agent 中按需调整行为

**注意:** 此工具尚未实现。在 standalone 模式下，anima 内置提供；在 nervus 集成模式下，由 nervus 提供。

### Memory Provider 说明

> **注意:** Memory provider 支持已移除。legacy 配置选项仍然可解析，但不会影响运行时行为。

---

## 预算与超时机制

### 预算耗尽 (Grace Finalization)

当 token 预算耗尽或 max_turns 达到上限时：

1. anima 注入提示：*"Budget exhausted. You have {grace_budget} tokens remaining. Call ctl_finish now."*
2. Agent 获得 `finalize_grace_budget`（默认 500）个 token 用于最后一轮
3. 若 agent 调用 `ctl_finish` → 状态 = `completed`
4. 若未调用或 grace 预算也耗尽 → 状态 = `failed`

### 超时处理

- 超时是硬性墙钟限制
- 超时触发时 agent 立即转为 `failed`，不进入 grace 阶段
- Grace 阶段中超时同样立即终止

### Completion Policy

| 策略 | 行为 |
|------|------|
| `explicit`（默认） | Agent 必须显式调用 `ctl_finish` 或 `ctl_fail` |
| `auto` | 当 LLM 连续两轮产生纯文本响应（无工具调用）时自动完成 |

### Daemon 生命周期

`lifecycle=daemon` 时：
- Agent 持续运行，不因任务完成而退出
- `ctl_finish` **无效**（日志警告，调用被忽略）
- 只能通过 `anima kill` 或进程信号终止
- 可通过 `anima talk` / `anima.interact()` 持续接收新消息

---

## MCP 服务器接口

每个 spawned agent 在 `$ANIMA_STATE/agents/<instance_id>/mcp.sock` 暴露 MCP 服务器：

| 工具 | 说明 |
|------|------|
| `anima.status()` | 返回 agent 实时状态（token 用量、工具调用计数、运行时间等） |
| `anima.interact(message)` | 向 agent 发送消息，返回响应和轮次号 |
| `anima.interrupt()` | 请求 agent 停止（触发 grace finalization） |

---

## 错误码参考

### JSON 错误信封格式

所有 `--json` 输出在出错时遵循统一格式：

```json
{
  "error": {
    "code": "AGENT_NOT_FOUND",
    "numeric_code": 300,
    "message": "Agent not found: 'abc123'",
    "details": {"instance_id": "abc123"}
  }
}
```

### anima 专用错误码（300 段）

| code | numeric_code | 说明 |
|------|-------------|------|
| `AGENT_NOT_FOUND` | 300 | Agent ID 不存在 |
| `AGENT_ALREADY_EXISTS` | 301 | 该 instance_id 的 agent 已在运行 |
| `BUDGET_EXHAUSTED` | 310 | Token 预算耗尽 |
| `MAX_TURNS_REACHED` | 311 | 达到最大轮次限制 |
| `MAX_DEPTH_EXCEEDED` | 312 | 子 agent 嵌套深度超限 |
| `AGENT_TERMINATED` | 313 | Agent 被终止或中断 |
| `UNSUPPORTED_MODEL` | 320 | 不支持的 LLM 模型 |
| `MCP_SOCKET_NOT_FOUND` | 321 | Agent MCP socket 未找到 |
| `MCP_CONNECTION_REFUSED` | 322 | Agent 拒绝 MCP 连接 |
| `MCP_CONNECTION_ERROR` | 323 | MCP 连接错误 |

### 通用错误码

| code | numeric_code | 说明 |
|------|-------------|------|
| `INVALID_INPUT` | 1 | 输入格式错误或缺少必需字段 |
| `NOT_FOUND` | 2 | 资源未找到 |
| `TIMEOUT` | 3 | 操作超时 |
| `INTERNAL` | 10 | 内部错误 |

---

## 退出码约定

| 退出码 | 含义 | 适用命令 |
|--------|------|----------|
| `0` | 成功 | 所有命令 |
| `1` | 错误（agent 失败/被杀、状态不匹配、内部错误） | run, collect, kill, approve, reject, resume |
| `2` | Agent 未找到 | status, inspect, logs, collect, talk, kill, approve, reject, resume, rm |

---

## 实战示例

### 示例 1：带自定义 persona 运行任务

```bash
cat > analyst.json << 'EOF'
{
  "spec_version": "0.1.0",
  "name": "analyst",
  "system_prompt": "You are a data analyst. Analyze the provided data and produce a summary report.",
  "model": "openai:gpt-5.2",
  "budget": 30000
}
EOF

anima run --persona-file analyst.json "Analyze Q4 sales data from /data/sales.csv"
```

### 示例 2：带 MCP 工具的 daemon agent

```bash
anima spawn \
  --persona-file monitor.json \
  --lifecycle daemon \
  --mcp "npx -y @anthropic/mcp-server-filesystem /var/log" \
  --timeout 24h \
  "Watch for errors in application logs and alert when critical issues found"
```

### 示例 3：交互式调试工作流

```bash
# 1. 启动 agent
anima spawn --system-prompt "You are a code reviewer" \
  --model openai:gpt-5.2 \
  "Review the authentication module"

# 2. 查看状态
anima list
# INSTANCE_ID   STATE     PERSONA   LIFECYCLE  UPTIME  TOKENS
# inst_f8a23b   running   default   ephemeral  0m10s   1200

# 3. 实时交互
anima talk inst_f8a

# 4. 查看日志
anima logs inst_f8a --tail 20

# 5. 收集结果
anima collect inst_f8a --wait
```

### 示例 4：审批流程

```bash
# Agent 在运行中调用了 ctl_request_approval("Need to delete production data")
anima list --state awaiting_approval
# INSTANCE_ID   STATE               PERSONA
# inst_abc123   awaiting_approval   cleaner

# 查看详情
anima inspect inst_abc

# 批准（附带备注）
anima approve inst_abc --note "Approved. Only delete data older than 90 days."

# 或拒绝
anima reject inst_abc --reason "Operation not approved for production environment"
```

### 示例 5：批量清理

```bash
# 预览 7 天前的失败 agent
anima prune --state failed --older-than 7

# 确认删除
anima prune --state failed --older-than 7 --yes

# 删除所有终态 agent
anima prune --yes

# 强制删除特定 agent（即使仍在运行）
anima rm inst_abc123 --force
```

### 示例 6：通过本地 LLM 运行

```bash
anima run \
  --system-prompt "You are a code generator" \
  --model openai/deepseek-r1 \
  --llm-base-url http://localhost:4000/v1 \
  "Write a Python function to calculate fibonacci numbers"
```

### 示例 7：远程节点管理

```bash
# 在节点上启动 anima serve
anima serve --host 0.0.0.0 --port 8420

# 其他服务通过 MCP SSE 连接
# -> anima.spawn(persona_spec, job_spec, task)
# -> anima.list()
# -> anima.status(instance_id)
# -> anima.interact(instance_id, message)
# -> anima.collect(instance_id)
# -> anima.kill(instance_id)
```
