# YAML 配置参考

> `from_config("agent-config.yml")` 将 YAML 编译为可执行的 Lambda Term。
> 本文档覆盖完整 YAML Schema 及每个字段的语义。

---

## 1. 完整 Schema 概览

```yaml
# ═══ 必填字段 ═══
agentId: string               # Agent 唯一标识
name: string                  # Agent 名称
type: enum                    # react | chain | simple | parallel | router
systemPrompt: string          # 系统提示词 (Lambda body)

# ═══ 模型配置 ═══
model:
  provider: string            # 见下方「Provider 列表」
  name: string                # 模型名 (可省略，使用 provider 默认值)
  temperature: float          # 0.0 - 1.0, 默认 0.3
  maxTokens: int              # 单次回复最大 token, 默认 4096
  timeout: int                # 请求超时 (秒), 默认 600
  conversation: bool          # 启用 ConversationLam, 默认 true
  maxHistoryTokens: int       # 对话历史 token 预算, 默认 min(contextWindow/2, 80000)
  contextWindow: int          # 模型最大上下文窗口, 默认 200000
  fallback:                   # 降级模型列表
    - "provider/model-name"

# ═══ ReAct 配置 ═══
react:
  maxSteps: int               # 最大推理步数, 默认 20
  observationEnabled: bool    # 启用 Observation 步骤, 默认 true
  toolTimeout: int            # 单工具超时 (秒)
  thinkTimeout: int           # 思考步骤超时 (秒)

# ═══ 工具 (MCP) ═══
mcp:
  localTools:                 # 允许使用的工具名称列表
    - ToolName
  policy:
    mode: auto                # auto | confirm | deny

# ═══ 记忆 ═══
memory:
  enabled: bool
  strategy: local | redis
  size: int                   # 记忆条目上限
  ttl: int                    # 过期时间 (秒)

# ═══ 运行时引擎 (Phase 6.5) ═══
runtime:
  engine: enum              # recursive | cek | adaptive, 默认 recursive
  costBudget: float         # CEK: 成本上限 (USD), 超过自动暂停
  maxSteps: int             # CEK: 最大转移步数, 默认 10000

# ═══ 安全 ═══
guard:
  dangerousCommandBlock: bool
  highRiskConfirmation: bool
  maxOutputLength: int
  retry: int
  fallback: last | error

# ═══ 人设 ═══
persona:
  name: string
  style: string
  template: string
```

---

## 2. Provider 列表

`model.provider` 决定 LLM 调用方式。三类 Provider 实现:

| provider 值 | Provider 类 | 说明 | API Key |
|---|---|---|---|
| `claude-code` | `ClaudeCodeProvider` | 通过 `claude -p --resume` 调用, 复用 Claude Code Max Plan | 不需要 |
| `anthropic` | `AnthropicProvider` | Anthropic Messages API | `ANTHROPIC_API_KEY` |
| `openai` | `OpenAICompatProvider` | OpenAI API | `OPENAI_API_KEY` |
| `ollama` | `OpenAICompatProvider` | 本地 Ollama (http://localhost:11434) | 不需要 |
| `dashscope` | `OpenAICompatProvider` | 阿里云 DashScope (通义千问) | `DASHSCOPE_API_KEY` |
| `deepseek` | `OpenAICompatProvider` | DeepSeek API | `DEEPSEEK_API_KEY` |
| `moonshot` | `OpenAICompatProvider` | Moonshot AI (Kimi) | `MOONSHOT_API_KEY` |

### Provider 默认模型

| provider | 默认 model.name |
|---|---|
| `claude-code` | `sonnet` |
| `anthropic` | `claude-sonnet-4-20250514` |
| `openai` | `gpt-4o` |
| `ollama` | `qwen2.5:7b` |
| `dashscope` | `qwen-max` |
| `deepseek` | `gpt-4o` (需显式指定) |
| `moonshot` | `gpt-4o` (需显式指定) |

### Provider 默认 contextWindow

| provider | contextWindow |
|---|---|
| `claude-code` / `anthropic` / `openai` | 200,000 |
| `moonshot` | 128,000 |
| `deepseek` | 64,000 |
| `ollama` | 32,000 |

---

## 3. ConversationLam 与对话历史

当 `model.conversation: true` (默认) 时, `from_config` 创建 `ConversationLam` 而非无状态 `Lam`。

**ConversationLam 的作用:**
- 包裹任意 Provider, 自动管理对话历史
- 每次调用追加 user/assistant 消息对
- 按 `maxHistoryTokens` 预算自动截断旧消息, 保留 system prompt
- 消除因上下文丢失导致的幻觉 (session persistence)

**编译等式:**

```
conversation: true  →  ConversationLam(provider, system_prompt, max_history_tokens)
conversation: false →  Lam(name, prompt, model)   # 无状态, 每次调用独立
```

**相关字段:**

| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| `model.conversation` | bool | `true` | 启用 ConversationLam |
| `model.maxHistoryTokens` | int | `min(contextWindow/2, 80000)` | 对话历史 token 预算 |
| `model.contextWindow` | int | 按 provider 自动设置 | 模型最大上下文窗口 |

---

## 4. 运行时引擎配置 (Phase 6.5)

`runtime.engine` 控制 Agent 的执行后端。两种引擎对相同输入产生相同结果，但提供不同的运行时能力。

### 三种引擎模式

| 引擎 | 实现 | 适用场景 | 特有能力 |
|------|------|---------|---------|
| `recursive` (默认) | Python 调用栈 (`Executor.reduce`) | 简单 Agent, 短管道 (≤10 步) | 低开销, 简单直接 |
| `cek` | Agent CEK Machine (Paper II §5) | 长循环, 高成本, 需暂停/恢复 | 逐步成本监控, 成本熔断, 循环检测, 暂停/恢复, K 栈可视化 |
| `adaptive` | 自动选择 | 不确定复杂度 | 分析 Term 结构, 自动选最优引擎 |

### 配置字段

| 字段 | 类型 | 默认值 | 适用引擎 | 说明 |
|------|------|--------|---------|------|
| `runtime.engine` | enum | `recursive` | 全部 | 执行引擎选择 |
| `runtime.costBudget` | float | 无限制 | `cek` | 成本上限 (USD), 超过自动暂停并抛出 `CostBudgetExceeded` |
| `runtime.maxSteps` | int | `10000` | `cek` | CEK 最大转移步数, 超过抛出 `MaxStepsExceeded` |

### 选择指南

```
maxSteps ≤ 10, 无并行          → recursive (默认, 不需要配置)
maxSteps > 10                  → cek (需要成本监控)
有 Pair/Par/AsyncPar           → cek (需要并行安全追踪)
有 Guard + retry > 1           → cek (重试可能爆成本)
不确定                         → adaptive (自动判断)
```

### 示例

```yaml
# 简单 Agent — 使用默认 recursive 引擎 (无需配置 runtime)
agentId: hello-bot
type: simple
systemPrompt: "You are a friendly bot."

# 复杂 ReAct Agent — 使用 CEK 引擎 + 成本熔断
agentId: security-scanner
type: react
react:
  maxSteps: 200
runtime:
  engine: cek
  costBudget: 10.00         # 超过 $10 自动暂停
  maxSteps: 10000

# 不确定复杂度 — 自适应选择
agentId: general-assistant
type: react
react:
  maxSteps: 15
runtime:
  engine: adaptive
```

### Python API

```python
# 通过 Runtime 类切换引擎
from lambdagent.agentruntime.runtime import Runtime

# 方式 1: YAML 配置 (读取 runtime.engine 字段)
result = Runtime.execute("agent-config.yml", "Hello")

# 方式 2: Python 参数覆盖
result = Runtime.execute("agent-config.yml", "Hello",
                         engine_mode="cek", cost_budget=5.0)

# 方式 3: 直接使用引擎
from lambdagent.agentruntime.cek_engine import CEKEngine
engine = CEKEngine(cost_budget=5.0)
result = engine.execute(term, "Hello", ctx)
# result.final_state → 可序列化的 CEKState (暂停/恢复)
# result.transitions → 完整小步转移记录
# result.cost → CostVector(tokens, latency, money)
```

---

## 5. 各 Provider 配置示例

### Claude Code Max Plan (无需 API Key)

```yaml
agentId: my-agent
name: my-agent
type: react

model:
  provider: claude-code
  name: sonnet                 # claude CLI 内部映射
  temperature: 0.3
  maxTokens: 4096

systemPrompt: |
  You are a helpful coding assistant.
```

运行: `python3 agentexample/agent67/run.py --claude`

### Anthropic API

```yaml
model:
  provider: anthropic
  name: claude-sonnet-4-20250514
  temperature: 0.3
  maxTokens: 4096
```

需设置: `export ANTHROPIC_API_KEY=sk-ant-...`

### OpenAI API

```yaml
model:
  provider: openai
  name: gpt-4o
  temperature: 0.5
  maxTokens: 4096
```

需设置: `export OPENAI_API_KEY=sk-...`

### DashScope (通义千问)

```yaml
model:
  provider: dashscope
  name: qwen-max
  temperature: 0.3
  maxTokens: 4096
```

需设置: `export DASHSCOPE_API_KEY=sk-...`

### Ollama (本地推理)

```yaml
model:
  provider: ollama
  name: qwen2.5:7b
  temperature: 0.3
  maxTokens: 4096
  contextWindow: 32000
```

需先启动: `ollama serve`

### DeepSeek

```yaml
model:
  provider: deepseek
  name: deepseek-chat
  temperature: 0.3
  maxTokens: 4096
  contextWindow: 64000
```

需设置: `export DEEPSEEK_API_KEY=sk-...`

### Moonshot (Kimi)

```yaml
model:
  provider: moonshot
  name: moonshot-v1-128k
  temperature: 0.3
  maxTokens: 4096
  contextWindow: 128000
```

需设置: `export MOONSHOT_API_KEY=sk-...`

---

## 5. 工具参数 Schema 自动生成

`from_config` 在编译时会自动扫描 `mcp.localTools` 中声明的工具, 从 `BUILTIN_TOOLS` 注册表提取每个工具的参数签名 (类名、必填/可选参数), 生成格式化文档并注入到 system prompt 末尾。

**目的:** LLM 调用工具时能使用准确的参数名, 避免因参数名猜测错误导致 `VALIDATION_ERROR` 进而引发幻觉。

**生成格式示例:**

```
## 工具参数参考 (Tool Parameter Reference)
调用工具时请严格使用以下参数名:

- **ReadFile**: `{"action":"ReadFile","input":{"file_path": ..., "offset": 0, "limit": 2000}}`
- **Bash**: `{"action":"Bash","input":{"command": ...}}`
- **terminate**: `{"action":"terminate","input":{"summary":"结果摘要"}}`
```

该文档块在 `_generate_tool_schema_docs()` 中生成, 仅当 `mcp.localTools` 非空时注入。

---

## 6. --strict-mcp-config 工具隔离

`ClaudeCodeProvider` 在调用 `claude -p` 时自动传入:

```
--mcp-config '{"mcpServers":{}}' --strict-mcp-config
```

效果: Claude CLI 只能看到 agent YAML 中声明的工具, 宿主机上安装的 MCP Server (如 Vercel, Gmail) 完全不可见。这防止了 LLM 调用未预期的工具导致安全问题或幻觉。

---

## 7. fallback 降级链

```yaml
model:
  provider: claude-code
  name: sonnet
  fallback:
    - anthropic/claude-sonnet-4-20250514
    - dashscope/qwen-max
```

当主 provider 失败时, 按顺序尝试 fallback 列表中的模型。格式为 `provider/model-name`。
