Managing Background Tasks and Cron Jobs in Kimi Code: A Complete Guide

Kimi Code provides a unified, type-safe system for scheduling recurring work via cron jobs and executing long-running background tasks, both built on the same underlying task model and exposed through built-in tools.

Managing background tasks and cron jobs in Kimi Code requires understanding its session-based persistence layer and turn-based execution model. The architecture ensures that scheduled jobs appear as natural transcript turns while background processes run independently of the conversation flow. This guide covers the core implementation details based on the MoonshotAI/kimi-code repository.

Core Architecture Components

The system is organized into distinct layers that handle persistence, scheduling, and execution.

Task Store Layer

The Task Store persists task definitions per session. For cron jobs, the SessionCronStore in packages/agent-core/src/tools/cron/session-store.ts stores CronTask objects. Background tasks use a generic store located in packages/agent-core/src/tools/background/task-list.ts. Both storage mechanisms maintain state across session reconnections.

Cron Scheduler

The Scheduler computes next fire times using the createCronScheduler function in packages/agent-core/src/tools/cron/scheduler.ts. It leverages the clock abstraction (SYSTEM_CLOCKS) and parses expressions via cron-expr.ts. The scheduler also supports optional jitter through packages/agent-core/src/tools/cron/jitter.ts to prevent thundering herd problems.

Turn Generation and Events

When a cron fires, the engine creates a turn with origin.kind === 'cron' as defined in packages/transcript/src/model/turn.ts. The mapping of cron origins to turn headers occurs in packages/transcript/src/history/groupTurns.ts. A cron.fired event is emitted on the WebSocket/REST surface, mapped through packages/kap-server/src/services/transcript/coreEventMap.ts using cronFiredEventSchema.

Background Task Management

Long-running work executes outside normal turn flow through tools in packages/agent-core/src/tools/background/. The task-list.ts manages registration, task-output.ts handles streaming, and task-stop.ts provides cancellation capabilities.

Cron Job Lifecycle

Understanding the five-phase lifecycle helps implement reliable recurring automation.

1. Create

An agent invokes the cron-create tool (CronCreateTool in packages/agent-core/src/tools/cron/cron-create.ts). The request validates against CronCreateInputSchema and persists to SessionCronStore.

2. Schedule

The CronScheduler watches stored tasks, parses cron expressions, computes next fire times, and optionally applies jitter before setting timers.

3. Fire

At the scheduled time, the scheduler creates a new turn with origin.kind === 'cron' containing the original prompt. A cron.fired event emits to connected clients.

4. Missed Execution Handling

If the server was down during a scheduled fire time, the system generates a cron_missed event upon recovery, allowing agents to detect and handle missed work.

5. Delete

The cron-delete tool removes tasks from the store, emitting a cron_deleted telemetry event defined in cron-telemetry-events.ts.

Background Task Lifecycle

Background tasks follow a simpler three-phase model independent of transcript turns.

Start

Agents invoke built-in background tools (e.g., subprocess runners). Tasks register in TaskList (packages/agent-core/src/tools/background/task-list.ts) with unique identifiers.

Run

Execution proceeds asynchronously. Output streams through task-output.ts, decoupled from the turn queue.

Stop

The task-stop tool aborts running tasks, removing them from the store and terminating underlying processes.

Practical Implementation Examples

These examples demonstrate the Node SDK interface defined in packages/node-sdk/src/session.ts.

Creating a Recurring Cron Job

import { Session } from '@moonshot-ai/kimi-code-sdk';

async function scheduleHealthCheck(session: Session) {
  await session.invokeTool('cron.create', {
    cron: '* * * * *',
    prompt: 'ping',
    payload: { note: 'health check' },
    recurring: true,
  });
}

Implementation note: This maps to CronCreateTool in packages/agent-core/src/tools/cron/cron-create.ts.

Listing Active Cron Jobs

import { Session } from '@moonshot-ai/kimi-code-sdk';

async function listCronJobs(session: Session) {
  const jobs = await session.invokeTool('cron.list', {});
  console.log('Scheduled cron jobs:', jobs);
}

Implementation note: Calls CronListTool in packages/agent-core/src/tools/cron/cron-list.ts.

Handling Cron Events via WebSocket

session.on('event', (ev) => {
  if (ev.type === 'cron.fired') {
    console.log('Cron fired:', ev.origin);
    // React to the turn inserted into transcript
  }
});

Implementation note: Event schema lives in packages/kap-server/src/protocol/events-zod.ts.

Starting Long-Running Background Tasks

await session.invokeTool('background.run', {
  command: ['ffmpeg', '-i', 'input.mp4', '-c:v', 'libx264', 'output.mp4'],
});

Implementation note: Managed by packages/agent-core/src/tools/background/task-list.ts and task-output.ts.

Stopping Background Tasks

await session.invokeTool('background.stop', { taskId: 'abc123' });

Implementation note: Executed by packages/agent-core/src/tools/background/task-stop.ts.

Summary

Frequently Asked Questions

How does Kimi Code handle missed cron executions when the server restarts?

Kimi Code tracks expected fire times in SessionCronStore. When the scheduler initializes after downtime, it compares the current time against missed schedules and emits cron_missed events through the transcript event system, allowing recovery logic to run immediately upon reconnection.

Can background tasks outlive the agent session that created them?

Yes. Background tasks persist in packages/agent-core/src/tools/background/task-list.ts independently of the turn flow. They continue running even if the initiating agent disconnects, and their output remains accessible via task-output.ts until explicitly stopped via task-stop.ts.

What cron expression format does Kimi Code support?

The system uses the parser defined in packages/agent-core/src/tools/cron/cron-expr.ts, supporting standard five-field cron syntax (minute, hour, day of month, month, day of week). The scheduler also supports optional jitter configuration through packages/agent-core/src/tools/cron/jitter.ts to distribute load.

How do agents distinguish between user-initiated turns and cron-generated turns?

Turns originating from cron jobs carry origin.kind === 'cron' in their metadata, as defined in packages/transcript/src/model/turn.ts. The mapping logic in packages/transcript/src/history/groupTurns.ts ensures these turns display appropriate headers in the transcript view, distinguishing them from user or assistant turns.

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 →