How the Background Task and Cron Job System Works in Kimi Code
Kimi Code runs background work and scheduled jobs entirely inside the agent engine using a three-layer architecture that converts cron firings into synthetic transcript turns, enabling uniform handling of user and scheduled inputs.
The background task and cron job system in MoonshotAI/kimi-code is engineered to handle long-running operations and recurring schedules without relying on external schedulers. By unifying task management, cron scheduling, and transcript generation into a cohesive event-driven pipeline, the system ensures that background execution remains fully inspectable and replayable alongside regular agent turns.
System Architecture
The implementation spans three distinct layers that operate within the agent core:
- Task Management – Handles creation, enumeration, termination, and output streaming for long-running background tasks launched by agents (e.g.,
bashtools, file downloads, or custom tools). Core logic resides inpackages/agent-core/src/tools/background/*. - Cron Scheduler – Parses standard cron expressions, maintains an in-memory store of recurring tasks, computes next fire times, and emits
cron.firedevents when schedules are due. Implemented inpackages/agent-core/src/tools/cron/*. - Event-Turn Mapping – Translates cron events into synthetic transcript turns with
origin.kind: "cron_job"andkind: "cron", allowing the agent to process scheduled triggers exactly like user input. This bridge lives inpackages/transcript/src/history/groupTurns.tsandpackages/transcript/src/model/turn.ts.
Background Task Tools
Background tasks are exposed through three discrete tools re-exported from packages/agent-core/src/tools/background/index.ts. Each tool manages a specific aspect of task lifecycle and inspection.
TaskListTool
TaskListTool retrieves active tasks for the current session by querying the session store for running TaskRecord instances. The implementation in task-list.ts returns metadata including task IDs, start times, and tool origins, enabling agents to monitor their own resource usage.
TaskOutputTool
TaskOutputTool streams stdout and stderr from running tasks as live task_output events. Located in task-output.ts, this tool reads from a task’s pipe buffers and emits incremental TaskOutputEvents. The UI subscribes to this event channel to render live logs without polling.
TaskStopTool
TaskStopTool terminates a specified task, optionally respecting a graceful timeout. The task-stop.ts implementation invokes the task’s kill() method and records a TaskStopped marker in the session log, ensuring deterministic cleanup even if the underlying process hangs.
Cron Job Lifecycle
Cron jobs proceed through a five-phase lifecycle managed entirely within the agent engine.
Creation
When an agent calls cron.create, the handler in cron-create.ts validates the expression using cron-expr.ts, instantiates a CronTask object, and persists it to the per-session CronSessionStore (cron/session-store.ts). A CronCreated event is emitted and recorded in the transcript.
Scheduling
The CronScheduler (cron/scheduler.ts) runs on every engine tick (approximately once per second). It pulls all enabled CronTasks from the session store, invokes the expression parser to calculate the next fire time, and maintains an internal queue of upcoming executions.
Firing
When the wall-clock reaches a task’s next fire time, the scheduler emits a cron.fired event defined in packages/protocol/src/events.ts (validated by cronFiredEventSchema). The Kap-Server’s transcript service (packages/kap-server/src/services/transcript/coreEventMap.ts) intercepts this event.
Execution
The transcript service creates a synthetic turn whose origin.kind is "cron_job" and whose kind is "cron" per the union variant in packages/transcript/src/model/turn.ts. The turn’s prompt field carries the cron payload (e.g., "ping"). The agent receives this turn exactly like a user message, executes its skills, and may generate a response. The interaction is persisted in the transcript log and supports full replay.
Management and Deletion
cron-delete.ts and cron-list.ts provide runtime management. They manipulate the in-memory task store and emit cron.deleted or cron.updated events, allowing agents to cancel or inspect schedules dynamically without restarting the engine.
Integration with the Transcript System
The transcript layer treats cron activity as first-class history entries rather than side-channel metadata.
- Turn Model –
packages/transcript/src/model/turn.tsdefines a union variant| { kind: 'cron'; taskId?: TaskId; payload?: unknown }that captures scheduled execution context. - Origin Mapping – In
packages/transcript/src/history/groupTurns.ts, origin types'cron_job'and'cron_missed'are mapped to thecronturn kind, preserving the original payload for debugging and audit trails. - Event Schemas – All cron events conform to Zod schemas in
packages/protocol/src/events.ts, ensuring type safety across the SDK, server, and UI boundaries.
Practical Usage Examples
Scheduling a Recurring Job
Use the SDK to create a cron task that fires every minute:
import { createCron } from '@moonshot-ai/agent-core';
await createCron({
cron: '* * * * *', // standard cron syntax
payload: 'ping', // data passed to the generated turn
recurring: true, // repeat indefinitely
});
Source: packages/agent-core/src/tools/cron/cron-create.ts
Listing Active Cron Jobs
Inspect currently scheduled jobs:
import { listCrons } from '@moonshot-ai/agent-core';
const jobs = await listCrons();
console.log(jobs);
// [{ jobId: 'j1', cron: '* * * * *', nextFire: Date }]
Source: packages/agent-core/src/tools/cron/cron-list.ts
Streaming Task Output
Subscribe to live logs from a background task:
import { subscribeTaskOutput } from '@moonshot-ai/agent-core';
const stream = subscribeTaskOutput({ taskId: 't42' });
stream.on('data', (chunk: string) => console.log(chunk));
Source: packages/agent-core/src/tools/background/task-output.ts
Stopping a Background Task
Terminate a task with a graceful timeout:
import { stopTask } from '@moonshot-ai/agent-core';
await stopTask({
taskId: 't42',
gracePeriodMs: 5000
});
Source: packages/agent-core/src/tools/background/task-stop.ts
Handling Cron Events Internally
When the engine processes a cron.fired event, the transcript service maps it to a marker operation:
// Inside kap-server/src/services/transcript/coreEventMap.ts
case 'cron.fired':
return [this.markerOp('cron.fired', restOf(event))];
Source: packages/kap-server/src/services/transcript/coreEventMap.ts
Summary
- Unified Execution Model – By converting cron firings into regular transcript turns, Kimi Code applies the same UI, audit, and replay pipelines to scheduled actions as it does to user input.
- Fault Isolation – Background tasks receive unique identifiers (e.g.,
TaskId,CronTaskIDs); stopping or failing a task does not corrupt the main session state. - Event-Driven Extensibility – New cron operations (pause, resume, modify) are implemented by extending the
cronnamespace and emitting strongly typed events defined inpackages/protocol/src/events.ts. - In-Memory Scheduling – The
CronSchedulerandCronSessionStorekeep scheduled tasks ephemeral to the session, avoiding external database dependencies for transient agent workflows.
Frequently Asked Questions
How does Kimi Code parse and validate cron expressions?
Kimi Code uses the parser implemented in packages/agent-core/src/tools/cron/cron-expr.ts to validate standard cron syntax and compute next fire times. When createCron is invoked, cron-create.ts calls this parser before persisting the task to CronSessionStore, ensuring malformed expressions are rejected at creation time.
What happens when a cron job fires while the agent is busy?
The CronScheduler emits a cron.fired event that the transcript service (coreEventMap.ts) converts into a synthetic turn with kind: 'cron'. This turn enters the same queue as user messages, so the agent processes it when ready. The turn preserves the original payload and cron_job origin, ensuring deterministic replay even if execution is delayed.
Can I view logs from a background task after it starts?
Yes. The TaskOutputTool exposes a streaming interface via subscribeTaskOutput that emits TaskOutputEvents containing stdout and stderr increments. These events flow through the same channel as agent responses, allowing the CLI, TUI, or web UI to render live logs without polling the filesystem.
Where are cron tasks stored during a session?
Cron tasks reside in the CronSessionStore (packages/agent-core/src/tools/cron/session-store.ts), an in-memory data structure keyed to the current session. This design keeps scheduled jobs transient and scoped to the agent’s lifecycle; they are not persisted to disk unless explicitly captured in the transcript log via the cron.created and cron.fired events.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →