context-infra 检查与复盘infra.guiming.net · 全内容自包含呈现 · 生成于 2026-07-21 16:28 UTC

ai_agent_cli_guide

Z3 全文↑ Z2 条目

道-方法 · 道层 skill 全文

← 返回道层 skill 索引 · 返回方法论区

本页是 <code>rules/skills/ai_agent_cli_guide.md</code> 的逐字投影(仅隐私清洗,零改写)。

时点提示:本页是仓内文件 rules/skills/ai_agent_cli_guide.md 的逐字投影(仅做隐私清洗:仓库根绝对路径→相对路径、家目录→~/;除此零改写)。若源文件后续有修订,以仓内真源为准。

AI CLI Agent 实用指南

元数据


何时用 CLI Agent 而非原始 API

直接调用 LLM API 在处理复杂任务时存在短板。CLI Agent 作为中间层的核心优势:

  1. 对抗"模型偷懒": 大任务时 API 易输出截断,Agent 天生具备循环执行和自我纠正能力
  2. 原生文件上下文: Agent 自动处理文件读取、编码和写入,将推理与 IO 解耦
  3. 继承工具链: 内置 MCP 插件,可随时调用 Tavily 搜索、执行脚本等
  4. 优化上下文管理: 自动处理 Context Window 消耗和长对话压缩

工具速查

维度Claude CodeCodex CLIOpenCode
开源✅ 100%
模型绑定仅 Claude仅 OpenAIProvider-agnostic(xAI, Anthropic, OpenAI, Google 等)
CLI 非交互claude --printcodex execopencode serve + opencode run --attach(两步)
Web API✅ 完整
推荐场景深度推理自动化多模型对比、自动化 + 可视化

文件响应模式(核心设计原则)

原则: 在生产环境中,所有输入输出都通过文件,严禁使用管道模式处理核心逻辑。

为什么:

实现要点:

Python 示例:

import subprocess
from pathlib import Path

# 1. 写 prompt 到文件
Path("prompt.txt").write_text("Your task here...")

# 2. 构造驱动 prompt
driver_prompt = (
    f"Read the full prompt from {Path('prompt.txt').resolve()}\n"
    f"Write ONLY a JSON object to {Path('output.json').resolve()}\n"
    "Do not include Markdown or extra text."
)

# 3. 执行(以 Claude Code 为例)
subprocess.run([
    "claude", "--print", "--output-format", "json",
    "--model", "claude-sonnet-4-6-20260217",
    driver_prompt.replace('\0', '')  # 清理 null byte
])

Claude Code 快速参考

基本命令: claude --print "prompt"

关键参数:

推荐: Sonnet 4.6 性能接近 Opus,价格仅 1/5


Codex CLI 快速参考

基本命令: codex exec [options] "prompt"

关键参数:

默认与命名: 用户未指定特殊 effort 时,通过 cli_agent 使用 codex:xhigh。对外显示为 x-high,传给 Codex CLI 的 wire 值必须是 xhigh;literal x-high 会被拒绝。codex:ultra 必须原样传 ultra,不得 alias 到 xhigh。当前顺序是 high → xhigh → max → ultra,因此默认 x-high 属于 Ultra 以下的高 effort,但并非紧邻 Ultra(中间还有最大单-agent推理的 max)。OpenAI 原生 Power 默认 gpt-5.6-sol + medium,不等于本仓库的调用政策默认。

推荐: 生产脚本通过 cli_agent 调 plain codex(解析为 codex:xhigh)或显式 codex:low / codex:high / codex:xhigh / codex:max / codex:ultra,不要在业务代码中硬编码具体模型 ID;直接 CLI 只用于 harness 自检或一次性实验。旧 codex:deep / codex:fast 仅作兼容 alias。

272K 防护: OpenAI GPT-5.6 API 模型页明确写明输入 >272K 后整次请求
input 2x、output 1.5x。统一 trigger 是 200K:前台/后台 direct Codex 使用上述
三个 -c 键,OpenCode/API 使用 limit.input=220000 与 reserved 20K 的等价配置。
safe_input_budget=200000 只是输入文件提示,不会自动 compact;Auto Compact 本身
也只在 turn boundary 生效,单次巨型输入仍不是硬拒绝保证。当前 Codex credits
文档未明示同一个 272K 阶跃,不要把 API 结论扩张成订阅计费已确认事实。


OpenCode 快速参考

OpenCode 深度用法(CLI serve/run --attach 与 Web Server API 两种非交互调用方式、关键参数、Python 客户端、REST 端点、启动认证、五条硬规则)见 opencode_server_usage_guide


AI 调用 AI 模式

如果你正在编写一个 Agent 来调用这些 CLI,提供如下元指令:

"当面临大规模文本处理或文件系统操作时,请调用底层的 CLI Agent:

1. 优先使用文件响应模式,先将待处理内容存入本地临时文件

2. 使用流模式 (--json) 并实时解析事件以便监控进度

3. 设置合理的推理强度(如翻译设为 low

4. 传递 Prompt 前清理空字符 (.replace('\0', ''))

5. 对于 OpenCode,优先使用 Web Server API"


极简主义设计哲学 (pi-mono)

来自 pi-mono 项目的核心原则:"What's missing matters more than what's included"

核心理念:

启发: 在复杂任务中,添加功能往往是逃避问题。真正难的决策是:什么不该有


模型选择速查

任务类型Claude CodeCodexOpenCode
翻译/格式转换Sonnet 4.6gpt-5.2 + low(你的轻量模型)
常规开发Sonnet 4.6gpt-5.2 + medium(你的标准模型)
深度推理/重构Opus 4.6gpt-5.2 + high(你的推理模型)

配额与虚假冷却防护(跨 provider)

router(CliAgentRouter)按 quota scope 记录各 provider 的限额状态,撞限额就跳过同 scope 的 tier、走 fallback 链。"虚假配额冷却"指 provider 实际可用、却被标记冷却并被持续跳过。两个机制专门防它(2026-06-04 落地)。

第一,限额只从 provider 的 durable 错误内容识别,不被 stderr 污染。判断一个 provider 是否真限额,只看它返回的正式错误体(claude 的 result 字段、codex 的 --output-last-message 写出的内容),不扫子进程 stderr 里回显的 prompt、加载规则、skill 描述。而且无论成功路径还是错误路径,都只在短错误体(少于 600 字)上认 rate limit。这样一段正常的长输出、或一次和配额无关的失败,即便 stderr 里出现 "quota"、"429"、"rate limit" 字样,也不会被误判成限额写进冷却。识别词表是 tools/llm_runtime/rate_limits.pyLLM_RATE_LIMIT_REGEX,但词表只在 durable 错误内容上匹配,不在整段 stderr 上扫。

第二,跳过冷却 scope 前先 live probe,provider 恢复就自动解冻。router 要跳过一个标记冷却的 scope 前,先看冷却记录里的 next_probe_at:若已过探测点,就发一个最小 "ping" 探测,provider 已恢复就当场 record_scope_success 解冻、继续用它;仍限额就 bump_next_probe 推后探测点再跳过。这样撞过一次 429、但 provider 早已恢复的 scope,不会被一直跳到记录里的 reset 时间,而是在下一个探测点自动复活。

真冷却和虚假冷却怎么分:provider 的速率窗口(GLM 报的 "5 hour usage limit"、Kimi 的 5h API 窗口)和网页端显示的余额、月度用量是两套数字,窗口耗尽时 API 返回 429,即便网页端余额充足。所以"网页能用但 router 报冷却"有两种情形:真窗口限额(等窗口 reset 或换 provider),或虚假冷却(撞过一次但已恢复,现在 live probe 会自动解冻)。

需要手工介入的少数情况:

# 查所有 scope 状态
python3 tools/llm_runtime/quota_state.py status
# 确认 provider 可用后手工解冻某个 scope
python3 tools/llm_runtime/quota_state.py record-success --scope <zai|kimi|openai|anthropic>
# 主动探测一个 scope,按真实结果更新状态
python3 tools/llm_runtime/wake_resume.py probe --scope <s> -- <最小请求命令>

各 scope 默认 backoff:ZAI 15 分钟、Codex(openai)30 分钟、Kimi 与 Anthropic 5 小时 5 分。Kimi 最长,一次误判会锁 5 小时,所以 live probe 对它收益最大。机制代码真源在 tools/llm_runtime/rate_limits.py 识别、quota_state.py 状态与 backoff、wake_resume.py 探测;router 侧集成在 tools/cli_agent/router.py 的 dispatch fallback loop。

OpenCode 生产经验(量化交易实验总结)

以下来自在 某量化交易实验项目中用 OpenCode + Grok 4.20 跑 回测实验的实战经验。

权限模型:文件必须在项目根目录下

OpenCode agent 无法访问项目根目录之外的路径(包括 /tmp/)。所有 file IO(prompt 输入文件、JSON 输出文件)必须放在 server 启动时的工作目录下。

# ❌ 错误:/tmp 会被 agent 拒绝访问
prompt_path = Path("/tmp/opencode_prompt.txt")

# ✅ 正确:放在 run 目录或项目本地目录
prompt_path = run_dir / "opencode_prompts" / f"{invocation_id}.txt"
# 或 fallback 到项目根目录下
prompt_path = Path(".opencode_tmp") / f"{invocation_id}.txt"

可靠性:stdout JSON 兜底

即使 prompt 明确要求"写入文件",agent 有时会直接在 stdout 输出 JSON 而不写文件(或写入空文件)。生产环境必须实现 stdout JSON 提取作为 fallback

import re

def _extract_json_from_text(text: str) -> dict | None:
    """从 stdout 中提取 JSON 对象(兜底方案)"""
    # 优先匹配 ```json 代码块
    m = re.search(r"```json\s*(\{.*?\})\s*```", text, re.DOTALL)
    if m:
        return json.loads(m.group(1))
    # 回退:找最大的 {...} 块
    candidates = re.findall(r"\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}", text)
    for c in sorted(candidates, key=len, reverse=True):
        try:
            return json.loads(c)
        except json.JSONDecodeError:
            continue
    return None

并发能力

一个 opencode serve 进程可以处理多个并发的 run --attach 请求。每个请求创建独立的 session。实测 2 并发稳定,更高并发取决于 LLM provider 的 rate limit。

Grok 4.20 不支持的参数

xai/grok-4.20-experimental-beta-0304-non-reasoning 不支持 presence_penaltyfrequency_penaltystop 参数。如果 OpenCode 转发了这些参数,API 会报错。

典型调用流程(文件响应模式)

1. 写 prompt → run_dir/opencode_prompts/XXXX.txt
2. 构造 driver prompt: "Read from {prompt_path}, write JSON to {response_path}"
3. opencode run --attach http://localhost:14097 -m model "driver_prompt"
4. 读 run_dir/opencode_responses/XXXX.json
5. 如果文件为空 → 从 stdout 提取 JSON(fallback)
6. 如果仍然失败 → retry(最多 3 次)

关键数据


参考


← 返回道层 skill 索引 · 返回方法论区