# How to Debug Kimi-Code Sessions Using the Kap-Server REST and WebSocket APIs

> Debug Kimi-Code sessions via kap-server REST API for snapshots or WebSocket API for real-time events. Access transcript data and operational batches efficiently.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: how-to-guide
- Published: 2026-07-25

---

**You can debug Kimi-Code sessions by querying the REST API for transcript snapshots and incremental operation batches, or by subscribing to the WebSocket API for real-time events with configurable transcript grades.**

Kimi-Code, developed by MoonshotAI, runs an engine-side server (`kap-server`) that exposes comprehensive debugging surfaces for session introspection. Whether you need to inspect historical transcripts or monitor live agent operations, the combination of REST endpoints and WebSocket streams provides full visibility into session state. This guide explains how to debug Kimi-Code sessions using these APIs based on the actual source code implementation in the `MoonshotAI/kimi-code` repository.

## REST API Endpoints for Session Transcripts

The **REST API** provides stable, request-response access to session data through four primary endpoints defined in [`packages/kap-server/src/routes/transcript.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kap-server/src/routes/transcript.ts). These endpoints leverage the `TranscriptService` class, which maintains a live `TranscriptStore` per in-memory session and journals every dispatched batch with a monotonic `seq` number.

### Full Transcript Retrieval

Fetch a paginated, turn-granular transcript for a specific agent:

```bash
curl -s "http://localhost:58627/api/v1/sessions/${SESSION_ID}/transcript?agent_id=main&page_size=50"

```

Use `before_turn=t5` to page backward or `after_turn=t6` to page forward. The endpoint uses `TranscriptService.forSessionLive` for active sessions or performs a cold rebuild from persisted wire logs for archived sessions.

### Incremental Operations Catch-Up

Retrieve only the operation batches that occurred after a specific sequence number:

```bash
curl -s "http://localhost:58627/api/v1/sessions/${SESSION_ID}/transcript/ops?agent_id=main&since_seq=${LAST_SEQ}"

```

The JSON response contains:
- `batches`: Array of operation batches, each with `seq` and `TranscriptOperation` arrays
- `seq`: The latest sequence number
- `complete`: Boolean indicating whether the journal still covers the requested range

When `complete` is `false`, the journal no longer contains the requested history, and you must fall back to a full transcript fetch.

### Plan Document Retrieval

Inspect plan documents generated by specific tool calls:

```bash
curl -s "http://localhost:58627/api/v1/sessions/${SESSION_ID}/transcript/plan?agent_id=main&tool_call_id=${CALL_ID}"

```

Omit the `tool_call_id` parameter to retrieve all plans for the specified agent.

### User Messages Filter

Project only user-message events for streamlined debugging:

```bash
curl -s "http://localhost:58627/api/v1/sessions/${SESSION_ID}/transcript/user-messages?agent_id=main"

```

## WebSocket API for Real-Time Monitoring

The **WebSocket API** at `ws://<host>/api/v1/ws` enables subscription to live session events, including global facts, per-agent events, and graded transcript streams. The implementation resides in [`packages/kap-server/src/transport/ws/v1/wsConnectionV1.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kap-server/src/transport/ws/v1/wsConnectionV1.ts).

### Connection Handshake and Subscription

Upon connection, the server sends a `server_hello` frame describing the protocol version and buffer limits. Clients must subscribe to sessions using specific frame types:

```javascript
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:58627/api/v1/ws');

ws.on('open', () => {
  // Handshake
  ws.send(JSON.stringify({ type: 'client_hello', payload: {} }));
  
  // Legacy subscription for all session events
  ws.send(JSON.stringify({
    type: 'subscribe',
    payload: { session_id: SESSION_ID }
  }));
  
  // Modern grade-based subscription
  ws.send(JSON.stringify({
    type: 'subscribe_v2',
    payload: {
      session_id: SESSION_ID,
      grades: [{ agent_id: 'main', grade: 'turn' }]
    }
  }));
});

```

### Transcript Grades

The `subscribe_v2` frame supports four **grades** that control the granularity of transcript events:
- `off`: No transcript events
- `block`: Block-level operations
- `turn`: Turn-level operations (recommended for debugging)
- `agent`: Agent-level aggregation

The `SessionEventBroadcaster` (located in [`packages/kap-server/src/transport/ws/v1/sessionEventBroadcaster.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kap-server/src/transport/ws/v1/sessionEventBroadcaster.ts)) applies these filters and respects the `suppressedByTranscript` flag to prevent duplicate delivery of events already included in the transcript stream.

### Buffering and Back-Pressure

Outbound frames are coalesced into a buffer with a default flush interval of **16ms** and a maximum of **64 frames** to optimize network usage while maintaining low latency. This logic is implemented in the `WsConnectionV1` class between lines 58-66.

## Step-by-Step Debugging Workflow

Follow this workflow to effectively debug Kimi-Code sessions using both API surfaces:

1. **Identify the session ID** from CLI output, UI logs, or by enumerating live sessions via `/api/v1/sessions`.

2. **Establish a baseline** by fetching the current transcript via REST to understand the session's current state.

3. **Open a WebSocket connection** and subscribe to `turn` grade events for real-time monitoring.

4. **Track the sequence cursor** (`seq`) from WebSocket `transcript.ops` payloads to request incremental updates via REST if the connection drops.

5. **Inspect plan documents** when debugging tool execution failures using the `/transcript/plan` endpoint.

6. **Monitor for resync signals** via the WebSocket connection.

## Handling Resync Scenarios

When a client's cursor (combination of `seq` and `epoch`) falls too far behind the server's journal, the `WsConnectionV1` class sends a `resync_required` control frame. This occurs in the `onMessage` handler when processing `subscribe_v2` requests (lines 119-138).

The payload includes a `reason` field (`gap`, `epoch_mismatch`, etc.). Upon receiving this frame:

```javascript
ws.on('message', (data) => {
  const frame = JSON.parse(data);
  if (frame.type === 'resync_required') {
    // Fetch full operation history via REST
    fetch(`http://localhost:58627/api/v1/sessions/${SESSION_ID}/transcript/ops?agent_id=main&since_seq=0`)
      .then(r => r.json())
      .then(json => {
        console.log('Recovered ops:', json.data.batches);
        // Re-subscribe with fresh state
        ws.send(JSON.stringify({
          type: 'subscribe_v2',
          payload: {
            session_id: SESSION_ID,
            grades: [{ agent_id: 'main', grade: 'turn' }]
          }
        }));
      });
  }
});

```

## Post-Mortem Analysis with Session Event Journals

For offline debugging, the `SessionEventJournal` class (in [`packages/kap-server/src/transport/ws/v1/sessionEventJournal.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kap-server/src/transport/ws/v1/sessionEventJournal.ts)) records every inbound envelope before it reaches the broadcaster. This journal enables complete replay of session events and is particularly useful for diagnosing race conditions or message ordering issues.

## Summary

- The **REST API** provides four endpoints (`/transcript`, `/transcript/ops`, `/transcript/plan`, `/transcript/user-messages`) for stable snapshot retrieval and incremental catch-up.
- The **WebSocket API** supports real-time subscriptions with configurable grades (`off`, `block`, `turn`, `agent`) via `subscribe_v2` frames.
- **Resync handling** is required when the client's `seq` cursor falls behind the journal; recovery involves fetching `since_seq=0` via REST and re-subscribing.
- Core implementation files include [`transcriptService.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/transcriptService.ts) for session management, [`wsConnectionV1.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/wsConnectionV1.ts) for WebSocket protocol handling, and [`sessionEventBroadcaster.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/sessionEventBroadcaster.ts) for event distribution.
- Frame buffering coalesces messages into 16ms batches with a 64-frame maximum to balance latency and throughput.

## Frequently Asked Questions

### How do I handle a `resync_required` error when debugging?

When the WebSocket connection sends a `resync_required` frame, your client's cursor is too stale for the server to catch up. Fetch the full operation history via the REST endpoint `/api/v1/sessions/{session_id}/transcript/ops?since_seq=0`, then re-issue the `subscribe_v2` frame to restart the stream from the current position.

### What are the different transcript grades available in the WebSocket API?

The WebSocket API supports four grades: `off` (no events), `block` (fine-grained blocks), `turn` (conversation turns), and `agent` (high-level agent summaries). Specify these in the `grades` array of the `subscribe_v2` payload to filter the event stream.

### How can I retrieve only user messages from a session transcript?

Use the dedicated REST endpoint `GET /api/v1/sessions/{session_id}/transcript/user-messages` with the `agent_id` parameter. This projects only user-message events, filtering out system operations and agent responses for focused debugging.

### What is the difference between `subscribe` and `subscribe_v2` WebSocket frames?

The `subscribe` frame is the legacy allowlist approach that subscribes to all events for a session. The `subscribe_v2` frame provides granular control via **grades**, allowing you to receive only specific transcript granularities (`block`, `turn`, etc.) per agent, and is the recommended approach for new debugging implementations.