Blog

Codex CLI, structured JSON outputs, and cron-safe AI workers

Naly 工程笔记:Codex CLI、结构化 JSON 与 Cron 安全 AI Worker

本说明描述了 Naly 如何通过结合 Cron 调度、严格的 JSON 合同和外部化日志,将 Codex CLI 从终端编码代理转为确定性的生产 Worker。它解释了为什么可靠性来自于运维不变量——加锁、重试与校验——而模型本身可以被替换。

June 25, 20269 sources

摘要

Naly 将 Codex CLI 用作定时 AI 工作的控制面:每条 cron 记录都会执行一段已入库脚本,启动一个带 web search 与严格输出约束的受限助手任务,然后写入经验证的 JSON 工件供下游发布、重放与重试。这样一来,模型工作更像可运维的流程——同一条命令、明确的 schema、明确的工件——而不是可变的交互式工作流。截止 2026-06-25,这一差异是增长关键内容基础设施的可靠性优势。

在 Naly 中的位置

Naly 已围绕发现、留存和分发流程建立了活跃的 GST 优先级。该模式可直接对接该执行层:

  • Cron 作业会按每个用例调用一个 tsx 脚本,因此每次运行都置于版本化代码中,而不是临时 shell 片段。
  • Codex CLI 负责推理与检索工作,而 Naly 负责编排控制:调度、重试、加锁和持久化工件。
  • 结构化输出喂给基于 Next.js、React、Drizzle ORM 和 Neon 的下游系统,无需下游自行猜测 schema。
  • 外部日志与运行元数据被写入到 NALY_LOG_ROOT,让复盘可复现,且不依赖进程输出缓冲。

该论点是:在生产场景下,LLM 质量只是系统的一半;围绕该 LLM 的确定性边界是另一半。

技术机制

1) 合同优先的 Worker 入口

每个任务由三个不可变输入启动:

  • 一个编码后的提示模板与任务意图。
  • 一个必须校验的响应 schema。
  • 一个运行包络(run_idsource_queryattemptenv),在 API 调用前持久化。

Naly 在 cron 中以批处理模式调用 Codex CLI,而非交互模式。Codex 被定义为本地代码代理,并以独立 CLI 形式发布,支持开源分发并保持活跃发布,可在脚本化环境中运行 Codex CLIOpenAI Codex 仓库

2) 为什么结构化输出是不可协商的

OpenAI 的结构化输出指南说明了 parser 支持的 schema 抽取和机器化流水线所需的 strict 模式行为。在 Naly 中,模型输出被视作中间工件,而非最终真相,因此 JSON 合同是可靠性实施点:

  • 必填字段(headline、evidence list、confidence、citations、failure reason)
  • 带默认值的可选字段
  • 数值型置信度与有界枚举
  • 明确将 parser 失败作为运行错误上报,而不是悄悄自动修正文案。

3) 含并发控制的 Cron 到 agent 生命周期

Cron 按标准五字段时间语法执行计划行,并在字段匹配时启动命令 crontab. 为保证生产安全,Naly 增加了:

  • 锁保护(每个任务单一活动运行)
  • 幂等运行键
  • 带抖动的有界重试策略
  • 每个阶段的外部日志采集
  • 由 Drizzle/Neon 管理数据库表中的运行后状态更新。

flock 该模式正是为这种防线而设计:获取锁、执行关键区块、若已被锁定则干净退出 flock。因为锁状态与文件描述符绑定,重叠的 cron 时间窗会被明确拒绝,而非损坏状态。

4) MCP 在该模式中的作用

Model Context Protocol 通过 JSON-RPC、能力协商与结构化工具调用,形式化主机/客户端/服务端工具合同 MCP。在 Naly 中,MCP 风格的边界减少了隐式耦合:网络检索可表示为受控的工具接口,具备显式能力,而不是自由形式的 shell 级行为。

文献观点

最新研究显示,可靠性并不等于原始能力。AI Agent Reliability 论文报告了任务准确率与跨运行一致性之间存在显著差距,并提出了显式的可靠性评估维度(一致性、鲁棒性、可预测性、安全性) Towards a Science of AI Agent Reliability。这支持了 Naly 的“先运行态”设计:如果一次运行成功却无法通过清晰的工件重复复现,它就不具备生产级品质。

对于结构化输出,ToolPRM 认为结构化工具调用行为需要明确监控,并且当建模内部函数调用过程而不仅仅是最终结果时,改进会更显著 ToolPRM: Fine-Grained Inference Scaling of Structured Outputs for Function Calling。这与 Naly 的 schema-first runner 循环一致:质量闸门位于接口边界,而不仅仅是内容流畅性。

同一前沿的第三篇论文 SLOT 在 LLM 之上通过模型无关的输出塑形层提供了可行替代路径 SLOT: Structuring the Output of Large Language Models。它进一步强化同一原则:即使基础模型质量较高,结构化可靠性仍是工程问题。

设计权衡

  1. 严格 schema 与模型可移植性:严格 schema 减少了下游歧义,但当不同供应商对约束解释差异较大时,可能增加偶发解析抖动。
  2. Cron 简洁性与队列弹性:cron 简单且可见,但突发工作负载下需要支持锁感知退避或队列层,以避免重叠运行和错过窗口。
  3. 任务内网络检索与确定性重放:实时 web search 提升时效性,但会带来来源波动,因此 Naly 在运行工件中保存查询文本、来源列表与原始引用。
  4. 外部日志与仅 DB 日志:文件系统日志可在进程重启后继续存在,且便于采集;数据库日志便于查询分析,但若分区不当,在开环场景下可能失败。

故障模式

  • Schema 漂移:供应商输出违反 schema;缓解为严格校验快速失败、schema 版本固定,以及死信运行。
  • Cron 执行重叠:重复写入或重复外部动作;缓解为 advisory lock + 进程退出保护。
  • 搜索不稳定:上游工具响应在多次尝试间发生变化;缓解为重试上限、指数级退避以及持久化上游引用。
  • 时间陷阱:夏令时与主机时区差异会影响调度语义;缓解为 UTC 调度策略和显式环境检查。
  • 静默部分写入:解析成功但下游写入失败;缓解为事务性持久化顺序与幂等 upsert。
  • 安全/上下文泄漏:任何具备工具能力的 agent 路径都可能越界,因此需要 MCP 式最小权限边界,以及明确的 consent/auth 假设,尤其当工具执行路径触及网络资源时 MCP 安全提示

实施建议

  • 每个业务任务仅保留一个 worker 命令位于 scripts/ 中,并仅允许 cron 调用该入口点。
  • 将 schema 文件哈希存入运行元数据,以便模型升级后可审计解析器预期。
  • 在封装脚本中设置 set -euo pipefail-风格行为,并始终在日志名中包含运行 ID。
  • 将三个检查点写入日志: startedcodex_result_parsedartifact_persisted
  • 使用 NALY_LOG_ROOT 以确保运行时 trace 不污染仓库状态,并在重启场景中可继续存在。
  • 持久化 attemptexit_coderetry_reasonvalidation_errors 以便 GST 与审计看板将不稳定基础设施与真实模型回归分离。

参考文献

Sources