Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
docs(config): document scheduler.agent_timeout_secs
The `scheduler` config block had no user-facing documentation. In
particular `agent_timeout_secs` defaults to 0, which means "no timeout",
and that value is easy to miss because nothing states it.

This matters because cron jobs are dispatched serially on a single
scheduler thread: a job that never exits delays every other scheduled
job, including heartbeats, for as long as it hangs. Shell-type jobs are
already capped at 60s, so agent-type jobs were the only unbounded kind.

Adds a `scheduler` section to the English and Chinese configuration
guides, and a matching `scheduler` block to config.example.json.

Also notes two behaviours an operator would otherwise have to discover
the hard way: `max_concurrent` is parsed but not enforced, and the
timeout is read once at startup, so a daemon restart is required for a
config change to take effect.

Docs and example config only; no runtime behaviour changed.
  • Loading branch information
vernonstinebaker committed Oct 5, 2026
commit c62b74d303bcc858029db6f853d2d390a387cc80
7 changes: 7 additions & 0 deletions config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,13 @@
]
},

"scheduler": {
"enabled": true,
"max_tasks": 64,
"max_concurrent": 4,
"agent_timeout_secs": 900
},

"autonomy": {
"level": "supervised",
"workspace_only": true,
Expand Down
35 changes: 35 additions & 0 deletions docs/en/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,41 @@ Notes:
- Failover order for bare model refs: primary provider first, then each listed `fallback_provider`.
- Provider-qualified fallback refs such as `openai/gpt-4o` route directly to that provider and skip the generic provider fanout.
- `api_keys`: (Optional) List of extra API keys for rotation on rate-limit (429) errors.

### `scheduler`

- Configures the cron scheduler that runs scheduled jobs.
- `enabled`: Master switch for cron scheduling (default: `true`).
- `max_tasks`: Maximum number of jobs the scheduler tracks (default: `64`).
- `max_concurrent`: Parsed and reported by `nullclaw cron status`, but **not currently enforced** — the cron scheduler runs one job at a time (see the note below).
- `agent_timeout_secs`: Hard wall-clock limit, in seconds, on a single cron **agent** job (default: `0` = **no timeout**).

Example:

```json
{
"scheduler": {
"enabled": true,
"max_tasks": 64,
"max_concurrent": 4,
"agent_timeout_secs": 900
}
}
```

#### Why `agent_timeout_secs` matters

Cron jobs are dispatched **serially on a single scheduler thread**. A due job is spawned and awaited before the scheduler looks at the next one, so a job that never exits delays every other scheduled job — including heartbeats — for as long as it hangs. With the default of `0` there is no deadline: the scheduler waits indefinitely for the job's output to reach EOF.

Set a non-zero value on any host that runs scheduled agent jobs:

- Pick a value comfortably above your slowest healthy job, and well below the interval between jobs. A 2-hour cron with a 15-minute cap leaves ample headroom while bounding a stall.
- The timeout covers **agent-type jobs only**. Shell-type cron jobs are already capped separately at 60 seconds and ignore this value.
- The limit is read once at daemon startup, alongside the rest of `scheduler`. There is no SIGHUP reload — **restart the daemon for a change to take effect**.
- On expiry the job's child process is killed and the run is recorded as an error, so the next tick proceeds normally.

Known limitation: the kill is delivered to the job's direct child process only, not to its descendants. A grandchild that inherits the job's output pipe can keep the scheduler waiting past the timeout.

### `identity` (AIEOS v1.1)

Use this section when you want the runtime identity to come from an AIEOS document.
Expand Down
35 changes: 35 additions & 0 deletions docs/zh/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,41 @@ NullClaw 内置了原生的 Anthropic provider,可直接连接 Anthropic API
- 裸模型名的故障转移顺序:先尝试主要提供方,再依次尝试每个列出的 `fallback_provider`。
- 像 `openai/gpt-4o` 这样的显式 `provider/model` 备用项会直接路由到对应 provider,不会再走通用 provider 扇出链路。
- `api_keys`: (可选) 用于在速率限制 (429) 错误时轮换的额外 API 密钥列表。

### `scheduler`

- 配置运行定时任务的 cron 调度器。
- `enabled`:定时任务调度的总开关(默认值:`true`)。
- `max_tasks`:调度器可跟踪的任务数量上限(默认值:`64`)。
- `max_concurrent`:会被解析并由 `nullclaw cron status` 展示,但**当前并未生效** —— cron 调度器同一时刻只运行一个任务(见下方说明)。
- `agent_timeout_secs`:单个 cron **agent** 任务的硬性墙钟时间上限,单位为秒(默认值:`0`,即**不设超时**)。

示例:

```json
{
"scheduler": {
"enabled": true,
"max_tasks": 64,
"max_concurrent": 4,
"agent_timeout_secs": 900
}
}
```

#### `agent_timeout_secs` 为何重要

定时任务在**单个调度线程上串行执行**。到期的任务会被启动并等待结束,调度器才会去看下一个任务,因此一个永远不退出的任务会把其余所有定时任务(包括心跳)一起拖延同样长的时间。在默认值 `0` 下没有截止时间:调度器会无限期等待该任务的输出到达 EOF。

凡是运行定时 agent 任务的主机,都应设置一个非零值:

- 取值应明显高于最慢的正常任务,同时远小于任务之间的间隔。例如 2 小时的 cron 配上 15 分钟上限,既留足余量,又能限制卡死时长。
- 该上限只作用于 **agent 类型**任务。shell 类型的 cron 任务另有 60 秒的独立上限,不受此值影响。
- 该值与其余 `scheduler` 配置一样,只在 daemon 启动时读取一次。系统不支持 SIGHUP 重载 —— **修改后需要重启 daemon 才会生效**。
- 超时触发时,任务子进程会被杀掉,本次运行记为错误,随后下一次触发即可正常进行。

已知限制:kill 只会作用于该任务的直接子进程,不会作用于其后代进程。如果某个孙进程继承了任务的输出管道,调度器仍可能在超时之后继续等待。

### `identity`(AIEOS v1.1)

如果你希望运行时身份来自 AIEOS 文档,可以使用这一节。配置后,nullclaw 会把解析后的 AIEOS 内容连同 `AGENTS.md`、`IDENTITY.md` 等工作区身份文件一起注入 system prompt:
Expand Down
Loading