acpx 入门其实不难:建个 session、发个 prompt、拿到结果,十分钟就能跑起来。
真正开始见水平的,是你把它放进复杂工作流之后。 这时候问题就不再是“能不能调用 agent”,而变成:
- 输出怎么给脚本消费?
- 超时了怎么办?
- 失败要不要重试?
- 哪些步骤适合并行,哪些必须串行?
- 什么时候该 push,什么时候不该轮询?
也就是说,acpx 的高级用法,不在于记住更多命令,而在于你是否把它当成一个可编排的系统组件,而不是一个“会说话的命令行工具”。
这篇文章就集中讲四件事:
- 如何控制输出格式,尤其是 JSON/NDJSON 的消费方式
- 复杂流程里如何处理超时、重试和降级
- 三种常见 workflow 模式:扇出、链式、评审循环
- 为什么我更推荐 push-based,而不是到处写轮询
一、输出格式控制:先想清楚你的消费者是谁
很多人第一次用 acpx,会把它当成终端里的聊天输出工具。但一旦要接脚本、自动化、日志处理系统,输出格式就不只是“好不好看”,而是“好不好接”。
acpx 支持三种核心输出格式:
textjsonquiet
1. text:给人看,适合交互式观察
默认的 text 输出最适合在终端里盯着执行过程看。
它会给你比较友好的流式信息,包括进度、工具状态和最终结果。
这很适合这些场景:
- 本地手工调试
- 想知道 agent 正在做什么
- 需要边看边决定下一步
但如果你的下游是脚本,text 通常就不够稳了。因为人类喜欢“有点弹性”的文本,程序不喜欢。
2. quiet:只要最终答案,不要过程噪音
如果你只是想拿最终文本,quiet 很顺手:
acpx --format quiet exec '用三句话总结当前项目定位'
它特别适合:
- shell 脚本拼接
- 快速生成摘要
- 把最终文案传给下一个步骤
但要注意,quiet 的代价是你几乎放弃了中间状态。
一旦要调错,信息量就不够。
3. json:真正进入自动化世界的入口
我自己最喜欢的还是 json。
acpx --format json codex exec '审查当前分支改动并输出风险摘要'
json 实际上是 NDJSON 事件流,每一行是一个独立 JSON 事件。这种格式的好处非常明确:
- 可流式消费
- 可按事件类型过滤
- 适合管道处理
- 既能拿过程,也能拿结果
比如你可以这样筛工具调用:
acpx --format json codex exec 'review changed files' \
| jq -r 'select(.type=="tool_call") | [.status, .title] | @tsv'
一个关键建议:不要试图“正则解析 text 输出”
这是我最想强调的一点。
如果你已经进入自动化或编排场景,请直接用 json,别去拿 text 输出做脆弱解析。
原因很简单:
- 文本人类可读,不代表机器稳定可读
- 一旦输出文案变化,正则就碎
- 调试时你以为是 agent 出错,实际是解析器先炸了
所以先问自己一句:
这一步输出是给人看,还是给程序接?
给人看,用 text。
给程序接,用 json。
只要最终文本,用 quiet。
这一步想清楚,后面会省很多事。
二、JSON 输出怎么设计消费逻辑?
光有 JSON 不够,关键是你怎么消费。
我更推荐一种“事件驱动”的思路,而不是“等全量结束再整体处理”。
1. 按事件类型分层处理
例如你可以把流里的事件粗分成:
- 中间进度事件
- 工具调用事件
- 错误事件
- 最终完成事件
这样脚本就能做更清楚的决策:
- 看到中间进度就更新日志
- 看到工具调用就记录审计轨迹
- 看到错误事件就触发重试或降级
- 看到完成事件就取最终结果
2. 保留原始事件日志,不要只保留最终文本
这是我踩过坑之后最认同的一条。
如果你只保留最终结果,一旦流程出了问题,后面几乎没法复盘。反过来,如果你把 NDJSON 原样存下来,调试体验会好很多。
尤其是在复杂流水线里,原始事件日志能帮你回答很多关键问题:
- 超时前卡在哪个阶段
- 请求过哪些工具
- 哪一步失败最多
- 是否有权限请求被拒绝
3. 结构化输出不等于“把所有内容都塞成 JSON 字符串”
有些人会让 agent 自己再输出一层 JSON,然后外面再包 NDJSON 事件。不是不能做,但要克制。
更好的做法通常是:
- 外层由
acpx负责事件流结构 - 内层只在真正需要结构化业务结果时,再要求 agent 输出稳定 JSON
别把每一步都设计成“JSON 里套 JSON 再套 markdown”。 那种系统看起来高级,实际维护时会很烦。
三、错误处理:复杂 Workflow 拼的不是快乐,是恢复能力
只要工作流够长,失败就不是意外,而是常态。
所以 acpx 的高级用法里,错误处理比“跑通一次”更重要。
我会重点看三类策略:超时、重试、降级。
1. 超时:先承认有些任务不该无限等
acpx 支持 --timeout <seconds>,这在复杂流程里非常重要。
例如:
acpx --timeout 180 codex exec '生成当前仓库的发布说明草稿'
为什么超时要显式设? 因为很多工作流失败,不是完全报错,而是长时间卡住。没有超时的系统,最容易把整个流水线拖死。
2. 重试:不是所有失败都值得原样重来
重试当然有用,但别搞成无脑 while true。
我更推荐按失败类型分类:
适合重试的:
- 暂时性连接问题
- 偶发超时
- 依赖服务短暂不可用
不适合直接重试的:
- 权限被拒绝
- prompt 本身有歧义
- 输入上下文缺失
- 逻辑型错误导致的稳定失败
也就是说,重试应该是对暂态问题的恢复手段,不是对设计问题的遮羞布。
3. 降级:系统别只会成功或死亡
我非常看重降级策略。
比如一个完整流程原本希望:
- research
- draft
- review
- publish
但如果 review 阶段超时了,系统是不是只能整条失败? 不一定。
你可以设计成:
- review 成功 → 正常发布
- review 失败但 draft 成功 → 标记“待人工复核”,先保存草稿
- research 失败 → 直接终止,因为后续输入不可靠
这就是降级的价值:
不要把系统设计成“全对才有产出”。
真实工作流更好的目标,通常是“尽量产出可用中间结果”。
四、三种常见 Workflow 模式
我自己在用 acpx 时,最常见的是三类模式:扇出、链式、评审循环。
模式一:扇出(Fan-out)
适合把一个大问题拆成多个独立子问题,同时处理。
例如你要写一篇大文章,可以并行开几个 research session:
- 一个查协议能力
- 一个查权限模型
- 一个查 session/queue 机制
最后再汇总。
它适合:
- 多主题研究
- 多模块并行分析
- 多候选方案比较
它的优点是快,缺点是后面一定要做归并,不然你只是得到了三堆材料。
模式二:链式(Chaining)
这是最稳的一种。
前一步输出,成为后一步输入,比如:
- research 输出提纲
- writing 根据提纲写初稿
- review 根据初稿提问题
- publish 根据定稿落盘
这种方式速度未必最快,但最容易控制质量和责任边界。
如果你刚开始搭复杂工作流,我建议先把链式做好,再考虑更花的模式。
模式三:评审循环(Review loop)
这是我最常用也最容易失控的一种。
流程通常是:
- writer 产出草稿
- reviewer 提意见
- writer 根据意见改稿
- reviewer 再检查
这个模式特别适合:
- 文案润色
- 技术文档修订
- 代码 patch review
- 风险审查
但它最大的坑也很明显: 如果你不设停止条件,它会一直转。
所以评审循环一定要有边界,比如:
- 最多两轮
- 只处理高优先级问题
- 当剩余问题低于阈值时结束
别把“反复优化”误写成“无限循环”。
五、Push-based vs 轮询:我为什么更讨厌后者
这部分是实战里最容易踩坑的。
很多人写自动化时,第一反应是轮询:
- 每隔几秒查一次状态
- 看看有没有完成
- 没完成就再查
这在简单系统里能凑合,但在 Agent 编排里,轮询通常很烦:
- 浪费资源
- 延迟大
- 日志碎
- 出现竞态条件
- 很容易把“处理中”和“已失败未上报”搞混
我更偏向 push-based:
- 流式输出就流式消费
- 有事件就处理
- 有结果就推进下一步
- 阶段完成时再触发后续动作
acpx 的 NDJSON 流本身就很适合这种风格,因为它不是要你反复“去问一遍”,而是在执行过程中持续把状态推出来。
轮询最常见的几个坑
1. 过于频繁
几百毫秒一次地查状态,看似积极,实际只是制造噪音。
2. 状态定义不清
“running”“queued”“done”“cancelled”“failed”这些状态如果脚本层没处理清楚,轮询逻辑很容易写出鬼故事。
3. 误把“没有新消息”当成“系统挂了”
有些长任务只是暂时没输出,不代表死了。轮询系统往往很容易误判。
4. 恢复逻辑越来越复杂
你会发现最后不是在做编排,而是在写半套状态机。
如果能直接基于事件流推进,就别没事给自己加一个轮询层。
六、一个更稳的复杂 Workflow 思路
如果让我给一个比较稳的高级用法建议,大概会是这样:
1. 默认链式,必要时局部扇出
不要一上来就全并行。大多数系统真正需要的是清晰,不是表面速度。
2. 给每个阶段明确输入、输出、超时和降级策略
例如:
- research:输入主题,输出提纲,超时 5 分钟,失败则终止
- writing:输入提纲,输出初稿,超时 10 分钟,失败则保留半成品
- review:输入初稿,输出问题列表,超时 3 分钟,失败则转人工
- publish:输入定稿,输出文件路径,失败则回滚或保留待发状态
3. 机器消费一律优先 json
别在自动化里硬啃 text。
4. 尽量保留事件日志
这一步在系统还小的时候看不出价值,等你出第三次线上怪问题时就会感激自己。
5. 让主 Agent 收口
复杂流程跑完后,不要把原始事件流直接甩给人看。 最好由主 Agent 做最后的总结、解释和人工决策承接。
七、结语:高级用法的重点,不是更复杂,而是更可恢复
很多人说“高级用法”,容易想到更多参数、更多模式、更多并发。
但我对 acpx 的理解是:
真正高级的,不是把工作流堆得更复杂,而是让它在复杂时仍然有边界、有日志、有恢复能力。
输出格式控制,让你分清人和程序的消费方式; 超时、重试和降级,让系统不会一碰就碎; 扇出、链式、评审循环,让任务拆分更贴近真实协作; push-based 的思路,则帮你少踩很多轮询带来的烂坑。
说到底,acpx 真正适合的不是“演示型自动化”,而是要长期跑、反复跑、出问题还能排查的工作流。
这也是我越来越喜欢它的原因: 它不是把 Agent 包装得更神奇, 而是让 Agent workflow 终于有了点工程系统该有的样子。