Skip to content
Merged
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
6 changes: 5 additions & 1 deletion .changeset/cron-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
"@moonshot-ai/kimi-code": minor
---

Add session-scoped scheduled prompts so the assistant can register, list, and cancel recurring or one-shot reminders that fire later in the same session.
Add scheduled tasks:

You can now ask the assistant to remind you at a specific time, run a task on a recurring cron schedule (for example, check a deploy every 5 minutes or run a daily report every weekday at 9am), or come back on its own in a few minutes to continue what it was doing.

Schedules use the standard 5-field cron syntax.
3 changes: 3 additions & 0 deletions docs/en/configuration/data-locations.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ $KIMI_CODE_HOME (default ~/.kimi-code)
│ │ ├── <task_id>.json
│ │ └── <task_id>/
│ │ └── output.log
│ ├── cron/ # Scheduled task persistence
│ │ └── <id>.json
│ └── agents/
│ ├── main/
│ │ ├── wire.jsonl
Expand Down Expand Up @@ -95,6 +97,7 @@ The internal structure of a session directory includes:
- `agents/agent-0/`, `agents/agent-1/`, etc.: subagent instance directories, each with its own `wire.jsonl`. Subagent ids are generated by a per-session incrementing counter (`agent-` followed by an integer starting from 0).
- `logs/kimi-code.log`: the diagnostic log for this session. It only appears after a recorded diagnostic event; an ordinary conversation may not create this file.
- `tasks/`: background task persistence directory. Each task stores its metadata (status, pid, exit code, etc.) in `tasks/<task_id>.json`, with stdout and stderr written to `tasks/<task_id>/output.log`. Task ids use a `bash-` or `agent-` prefix followed by 8 random alphanumeric characters (for example, `bash-a1b2c3d4`).
- `cron/`: scheduled task persistence directory. Each task scheduled through `CronCreate` is mirrored to `cron/<id>.json`, where `<id>` is 8 lowercase hex characters. `kimi resume` rehydrates these tasks back into the in-memory scheduler. Tasks remain scoped to the resumed session id and do not bleed into new sessions. See [Scheduled tasks](../reference/tools.md#scheduled-tasks) for the tool surface.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Document forked-session cron carryover

When a user forks a session that has live cron jobs, the fork gets a new session id but SessionStore.fork() copies the entire source session directory recursively, including cron/<id>.json, and Agent.resume() later calls cron.loadFromDisk(). That means those tasks do carry into the fork and can fire there too, so this blanket statement about not bleeding into new sessions understates a duplicate-reminder scenario; either exclude cron files during fork or document the fork behavior.

Useful? React with 👍 / 👎.


`sessionId` is restricted to `[A-Za-z0-9._-]+` and cannot be `.` or `..`, preventing path injection. The session list is sorted by `updatedAt` in descending order, where `updatedAt` is the maximum mtime of the directory and its key files. See [Sessions](../guides/sessions.md) for details.

Expand Down
1 change: 1 addition & 0 deletions docs/en/configuration/env-vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ When neither `KIMI_CODE_OAUTH_HOST` nor `KIMI_OAUTH_HOST` is set, the OAuth auth
| `KIMI_CODE_PLUGIN_MARKETPLACE_URL` | Override the plugin marketplace JSON loaded by `/plugins`; useful for dev loopback servers, staging CDN files, or alternate marketplace directories | `https://cdn.kimi.com/kimi-code/plugins/marketplace.json`; also accepts `http://`, `file://` URLs, and local paths |
| `KIMI_SHELL_PATH` | Override the absolute path to Git Bash (`bash.exe`) on Windows; only needed when auto-detection fails on Windows | None |
| `KIMI_MODEL_MAX_COMPLETION_TOKENS` | Explicit hard cap for `max_completion_tokens` in a single-step LLM request. When unset, Kimi Code uses the safe remaining context window for models with a known context size. Set to `0` or a negative value to disable clamping entirely. **Currently effective only for providers of type `kimi`**; for Anthropic and other providers, use `[models.<alias>].max_output_size` instead (see [Config files](./config-files.md#models)) | Unset: computed from remaining context; unknown context falls back to `loop_control.reserved_context_size`, then 32000 |
| `KIMI_DISABLE_CRON` | Disable the scheduled-task tools entirely. Set to `1` to make `CronCreate` reject new schedules and short-circuit the scheduler's tick loop; existing tasks remain on disk but never fire while the variable is set. See [Scheduled tasks](../reference/tools.md#scheduled-tasks) | `1` to disable; unset by default |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe the cron kill switch narrowly

When KIMI_DISABLE_CRON=1 is set, it only makes CronCreate reject new schedules and makes the scheduler tick return early; CronList remains default-approved and CronDelete has no kill-switch branch, so users can still inspect or delete persisted jobs. Saying this disables the scheduled-task tools entirely is misleading for operators who expect a complete tool block; please describe it as disabling creation/firing, or explicitly note that list/delete remain available.

Useful? React with 👍 / 👎.


For example, to disable telemetry on a shared host:

Expand Down
24 changes: 24 additions & 0 deletions docs/en/guides/use-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,30 @@ Research the mainstream dependency injection options in TypeScript (tsyringe, in

Use `--yolo` or `/yolo` to skip approvals, or set an allow list under [permission configuration](../configuration/config-files.md#permission) for a safer middle ground.

## Scheduled tasks and reminders

Within an interactive session you can ask the assistant to set a one-shot reminder, run a task on a recurring schedule, or come back to you after a fixed delay. The agent maps the request to a 5-field cron expression in your local timezone and re-injects the prompt into the same session when it fires.

```
Remind me at 2:30pm today to check the deploy.
```

```
Every weekday at 9am, summarize the latest CI failures and post the result to me.
```

```
Hourly, poll the production health endpoint and let me know if anything looks off.
```

```
In about 10 minutes, come back and verify the build finished.
```

Schedules live inside the session: closing the terminal is fine, and `kimi resume`-ing the same session reloads them and resumes the schedule. They do not carry over into a brand-new session. Recurring tasks auto-expire after seven days — the agent gets a `stale` notice on the final fire and will either let the task end or refresh it depending on your earlier instructions. Use `--yolo` if you want the agent to schedule tasks without approval prompts; otherwise each `CronCreate` asks for confirmation against the exact schedule and prompt.

To see what is currently scheduled, just ask: `What scheduled tasks are pending?` (the agent runs the read-only `CronList` tool). To cancel one, ask the agent to drop it or quote its 8-character id. The full tool surface is documented under [Scheduled tasks](../reference/tools.md#scheduled-tasks), and the kill switch is `KIMI_DISABLE_CRON=1`.

## Generating and maintaining documentation

```
Expand Down
18 changes: 18 additions & 0 deletions docs/en/reference/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,21 @@ Background task tools manage background tasks started via `Bash` or `Agent`. Whe
**`TaskOutput`** returns the status and output of a specified task by `task_id`. The inline preview includes at most the most recent 32 KB of content; the full log is saved on disk, and the tool also returns `output_path` with a prompt to paginate it via `Read` (around 300 lines per page is recommended). Optional `block` (default false) and `timeout` (seconds to wait, default 30, range 0–3600) parameters can be used to wait for the task to finish before returning. In the response, `retrieval_status` is one of `success` / `timeout` / `not_ready`; tasks aborted by an external deadline timeout additionally include `timed_out: true` and `terminal_reason: timed_out`, and tasks explicitly terminated by `TaskStop` additionally include `stop_reason` and `terminal_reason: stopped`.

**`TaskStop`** accepts `task_id` and an optional `reason` (reason for stopping, default `Stopped by TaskStop`). It is safe to call on a task that is already in a terminal state — it returns the current status without error.

## Scheduled tasks

Scheduled task tools let the agent re-inject a prompt into the current session at a future time, either once (a reminder) or on a recurring cron schedule (a periodic check, daily report, deploy watcher, etc.). Schedules are scoped to the session: they survive `kimi resume` of the same session, but never carry over into a brand-new session. A session is capped at 50 live scheduled tasks. Setting `KIMI_DISABLE_CRON=1` blocks the entire feature — see [Environment variables](../configuration/env-vars.md#runtime-switches).

| Tool | Default approval | Description |
| --- | --- | --- |
| `CronCreate` | Requires approval | Schedule a prompt to fire at a future time |
| `CronList` | Auto-approved | List scheduled tasks |
| `CronDelete` | Requires approval | Cancel a scheduled task |

**`CronCreate`** accepts `cron` (a standard 5-field cron expression in the user's local timezone: `minute hour day-of-month month day-of-week`), `prompt` (the text to re-inject when the schedule fires, capped at 8 KB UTF-8), and an optional `recurring` (default `true`; pass `false` for a one-shot reminder that fires once and then auto-deletes). The tool requires the expression to have at least one fire within five years and rejects one-shot tasks whose next fire would land more than ~350 days in the future (typically a pinned day/month that already passed this year). On success it returns an 8-character hex `id`, a human-readable `humanSchedule` (e.g. `every 5 minutes`), the `recurring` flag, and `nextFireAt` (the ISO timestamp of the next post-jitter fire). The approval scope is tied to the exact `(cron, prompt, recurring)` payload — re-approving once does not authorize later schedules. `CronCreate` is also blocked in Plan mode.

To avoid synchronized fleet-wide fires on round minute marks, the scheduler applies a deterministic per-task jitter: recurring tasks shift forward by up to `min(10% of the period, 15 minutes)`; one-shot tasks landing on `:00` or `:30` shift earlier by up to 90 seconds. If the scheduler sleeps past several ideal fire times (laptop closed, long-running turn, etc.), it delivers only one fire when it wakes up — the prompt is wrapped in a `<cron-fire>` envelope carrying `coalescedCount` so the agent reacts to "I missed N checks; only the latest state matters" instead of running the prompt N times. Recurring tasks older than seven days fire one final time with `stale="true"` on the envelope and the system then auto-deletes the task; to keep the schedule running, just call `CronCreate` again. One-shot tasks are never marked stale.

**`CronList`** is read-only and takes no parameters. It returns one record per live task, each carrying `id`, `cron`, `humanSchedule`, the JSON-encoded `prompt` (truncated to ~200 UTF-8 bytes for context-window safety), `nextFireAt` (the post-jitter ISO timestamp the scheduler will actually fire on), `recurring`, `ageDays`, and `stale`. Records are separated by a line containing `---` in scheduling order. The empty case returns `cron_jobs: 0\nNo cron jobs scheduled.`. Use this to recall pending tasks after a context compaction, or to look up an `id` for `CronDelete`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Correct CronList ordering claim

When a session has multiple cron jobs added out of chronological order, this says CronList records are in scheduling order, so users/models may treat the first record as the next due task. The implementation does not sort by nextFireAt: CronList maps this.manager.store.list(), and SessionCronStore.list() returns the backing Map in insertion order, so this should not promise scheduling order (the zh mirror has the same claim).

Useful? React with 👍 / 👎.


**`CronDelete`** accepts a single `id` — the 8-character hex value returned by `CronCreate` or shown in `CronList`. For a recurring task it stops all future fires immediately; for a one-shot it cancels the pending fire. One-shot tasks that have already fired auto-delete themselves, so calling `CronDelete` on a fired one-shot returns `No cron job with id ...` — a signal that the model should call `CronList` rather than retry with the same id. Deletion is irreversible; recreate the task with `CronCreate` to undo. `CronDelete` is also blocked in Plan mode.
3 changes: 3 additions & 0 deletions docs/zh/configuration/data-locations.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ $KIMI_CODE_HOME (默认 ~/.kimi-code)
│ │ ├── <task_id>.json
│ │ └── <task_id>/
│ │ └── output.log
│ ├── cron/ # 定时任务持久化
│ │ └── <id>.json
│ └── agents/
│ ├── main/
│ │ ├── wire.jsonl
Expand Down Expand Up @@ -95,6 +97,7 @@ OAuth 凭据以文件形式存放在数据根下的 `credentials/` 子目录,
- `agents/agent-0/`、`agents/agent-1/` 等:子 Agent 实例的目录,各自包含 `wire.jsonl`。子 Agent id 由会话内的递增计数器生成(`agent-` 加从 0 起的整数)。
- `logs/kimi-code.log`:该会话的诊断日志。只有发生被记录的诊断事件时才会出现;普通对话不一定产生这个文件。
- `tasks/`:后台任务持久化目录。每个任务在 `tasks/<task_id>.json` 保存元信息(状态、pid、退出码等),标准输出与标准错误写入 `tasks/<task_id>/output.log`。任务 id 格式为 `bash-` 或 `agent-` 前缀加 8 位随机字母数字(如 `bash-a1b2c3d4`)。
- `cron/`:定时任务持久化目录。通过 `CronCreate` 安排的每个任务会镜像到 `cron/<id>.json`,其中 `<id>` 是 8 位小写 16 进制字符。执行 `kimi resume` 时这些任务会被重新加载到内存调度器中。任务仅绑定到恢复的会话 id,不会带入新会话。工具表面参见 [定时任务](../reference/tools.md#定时任务)。

`sessionId` 仅允许 `[A-Za-z0-9._-]+` 且不能为 `.` 或 `..`,以避免路径注入。会话列表按 `updatedAt` 倒序排序,`updatedAt` 取目录与各关键文件 mtime 的最大值。详见 [会话管理](../guides/sessions.md)。

Expand Down
1 change: 1 addition & 0 deletions docs/zh/configuration/env-vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ OAuth 流程默认连接 Kimi 官方的认证与托管端点,下列变量可
| `KIMI_CODE_PLUGIN_MARKETPLACE_URL` | 覆盖 `/plugins` 加载的 plugin marketplace JSON,适合 dev loopback server、测试 CDN 文件或替换 marketplace 目录 | `https://cdn.kimi.com/kimi-code/plugins/marketplace.json`;也接受 `http://`、`file://` URL 和本地路径 |
| `KIMI_SHELL_PATH` | 覆盖 Windows 上 Git Bash (`bash.exe`) 的绝对路径,仅在 Windows 自动探测失败时需要 | 无 |
| `KIMI_MODEL_MAX_COMPLETION_TOKENS` | 单步 LLM 请求 `max_completion_tokens` 的显式硬上限。未设置时,对于已知上下文窗口的模型,Kimi Code 会使用安全的剩余上下文窗口;设为 `0` 或负数则完全禁用 clamp。**目前只对 `kimi` 类型的供应商生效**;Anthropic 等其它供应商请改用 `[models.<alias>].max_output_size`(详见 [配置文件](./config-files.md#models)) | 未设置:按剩余上下文计算;未知上下文窗口时回退到 `loop_control.reserved_context_size`,再回退到 32000 |
| `KIMI_DISABLE_CRON` | 整体禁用定时任务工具。设为 `1` 时 `CronCreate` 会拒绝新计划,调度器的 tick 循环也会立即短路;磁盘上已有的任务保留,但只要变量仍然生效就不会触发。详见 [定时任务](../reference/tools.md#定时任务) | `1` 表示禁用;默认未设置 |

例如在共享主机上禁用遥测:

Expand Down
24 changes: 24 additions & 0 deletions docs/zh/guides/use-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,30 @@ src/parser/markdown.ts 目前几乎没有测试。请补一组单元测试,覆

用 `--yolo` 或 `/yolo` 跳过审批,或用 [permission 配置](../configuration/config-files.md#permission) 给特定工具加白名单。

## 定时任务与提醒

在交互式会话内,可以让助手设置一次性提醒、按周期运行某个任务,或者过一段时间后主动回到你这边。Agent 会根据你的请求生成一段本地时区下的 5 段 cron 表达式,并在触发时把 prompt 重新注入到同一个会话。

```
下午 2:30 提醒我去查一下部署。
```

```
每个工作日上午 9 点,帮我汇总最近的 CI 失败情况,并把结果发我。
```

```
每小时巡检一次生产环境的健康端点,看到异常就告诉我。
```

```
大约 10 分钟之后再回来,确认一下构建是否结束。
```

定时计划绑定在会话内:关掉终端没关系,对同一个会话执行 `kimi resume` 时会重新加载这些计划并继续按时触发;但它们不会带入全新的会话。周期任务在 7 天后会自动过期——Agent 会在最后一次触发时收到 `stale` 提示,并根据你之前的指示决定让任务结束还是续期。如果希望 Agent 安排任务时不再询问审批,可以使用 `--yolo`;否则每次 `CronCreate` 都会就具体的时间表与 prompt 内容请求确认。

想看当前安排了哪些任务时,直接问就行:「现在有哪些挂起的定时任务?」(Agent 会调用只读的 `CronList` 工具)。要取消某个任务,让 Agent 删除它或者引用对应的 8 位 id 即可。完整的工具表面见 [定时任务](../reference/tools.md#定时任务);整体关停开关是 `KIMI_DISABLE_CRON=1`。

## 生成与维护文档

```
Expand Down
18 changes: 18 additions & 0 deletions docs/zh/reference/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,21 @@ Plan 模式是一种受约束的工作状态:进入后 `Write` 与 `Edit` 工
**`TaskOutput`** 根据 `task_id` 返回指定任务的状态与输出。内联预览最多包含最近 32 KB 的内容;完整日志保存在磁盘上,工具会一并返回 `output_path` 并提示通过 `Read` 分页读取(建议每页约 300 行)。可选 `block`(默认 false)和 `timeout`(等待秒数,默认 30,取值范围 0–3600)参数可用于等待任务完成后再返回。返回结构中 `retrieval_status` 取 `success` / `timeout` / `not_ready`;任务因超时被外部 deadline 中止时会附带 `timed_out: true` 与 `terminal_reason: timed_out`,被 `TaskStop` 显式终止时会附带 `stop_reason` 与 `terminal_reason: stopped`。

**`TaskStop`** 接受 `task_id` 和可选的 `reason`(停止原因,默认 `Stopped by TaskStop`)。对已处于终止状态的任务也能安全调用,会直接返回当前状态而不报错。

## 定时任务

定时任务工具允许 Agent 把一段 prompt 在未来某个时间重新注入到当前会话中,既可以是一次性的提醒,也可以是按 cron 周期触发的任务(定期巡检、每日报表、部署监控等)。计划绑定到会话:同一会话执行 `kimi resume` 后仍然有效,但不会带入全新的会话。单个会话最多保留 50 个生效中的定时任务。设置 `KIMI_DISABLE_CRON=1` 可整体禁用该功能,详见 [环境变量](../configuration/env-vars.md#运行时开关)。

| 工具 | 默认审批 | 说明 |
| --- | --- | --- |
| `CronCreate` | 需审批 | 安排一个在未来时刻触发的 prompt |
| `CronList` | 自动放行 | 列出已安排的定时任务 |
| `CronDelete` | 需审批 | 取消已安排的定时任务 |

**`CronCreate`** 接受 `cron`(用户本地时区下标准的 5 段 cron 表达式:`minute hour day-of-month month day-of-week`)、`prompt`(触发时要重新注入的文本,UTF-8 编码上限 8 KB)以及可选的 `recurring`(默认 `true`;传 `false` 表示一次性提醒,触发后自动删除)。工具会校验表达式在未来 5 年内至少有一次触发,并拒绝那些下次触发会落在 350 天之后的一次性任务(通常意味着指定的日/月在今年已经过去)。成功时返回 8 位 16 进制 `id`、人类可读的 `humanSchedule`(如 `every 5 minutes`)、`recurring` 标记,以及 `nextFireAt`(下次抖动后触发时间的 ISO 时间戳)。审批范围与 `(cron, prompt, recurring)` 这组精确载荷绑定——一次性批准不会授权后续的其它计划。`CronCreate` 在 Plan 模式下同样会被拦截。

为了避免整批用户在整点同时触发,调度器会按任务 id 做确定性抖动:周期任务向后偏移 `min(周期的 10%, 15 分钟)`;一次性任务若恰好落在 `:00` 或 `:30`,则向前提前最多 90 秒。如果调度器错过了若干理想触发时刻(笔记本合盖、长时间运行的轮次等),唤醒后只会触发一次——prompt 会被包裹在 `<cron-fire>` 信封里并附带 `coalescedCount`,让 Agent 按「我错过了 N 次检查,只看最新状态」处理,而不是把 prompt 重复执行 N 次。周期任务存活超过 7 天后会以 `stale="true"` 的信封做最后一次触发,随后系统自动删除;想继续保留这条计划时,直接再调用一次 `CronCreate` 即可。一次性任务永远不会被标记为 stale。

**`CronList`** 是只读工具,不接受任何参数。它为每个生效中的任务返回一条记录,字段包括 `id`、`cron`、`humanSchedule`、JSON 编码的 `prompt`(出于上下文窗口安全考虑,截断到约 200 UTF-8 字节)、`nextFireAt`(抖动后调度器实际会触发的 ISO 时间戳)、`recurring`、`ageDays` 和 `stale`。记录之间用一行 `---` 分隔,按调度时间排列。空列表返回 `cron_jobs: 0\nNo cron jobs scheduled.`。上下文压缩后想要回忆挂起的任务,或者要找 `CronDelete` 所需的 `id`,都可以用这个工具。

**`CronDelete`** 只接受一个 `id`——即 `CronCreate` 返回或 `CronList` 中展示的 8 位 16 进制值。对周期任务,未来所有触发立即停止;对一次性任务,挂起的那次触发会被取消。已经触发过的一次性任务会自动删除,因此对已触发过的一次性任务再次调用 `CronDelete` 会返回 `No cron job with id ...`——这是提示模型应该先调用 `CronList` 而不是用同一个 id 重试。删除不可撤销,需要还原时只能再次 `CronCreate`。`CronDelete` 在 Plan 模式下同样会被拦截。
Loading