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., bash tools, file downloads, or custom tools). Core logic resides in packages/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.fired events when schedules are due. Implemented in packages/agent-core/src/tools/cron/*.
  • Event-Turn Mapping – Translates cron events into synthetic transcript turns with origin.kind: "cron_job" and kind: "cron", allowing the agent to process scheduled triggers exactly like user input. This bridge lives in packages/transcript/src/history/groupTurns.ts and packages/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.

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, CronTask IDs); 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 cron namespace and emitting strongly typed events defined in packages/protocol/src/events.ts.
  • In-Memory Scheduling – The CronScheduler and CronSessionStore keep 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →