C.W.K.
Stream
Lesson 07 of 08 · published

Sessions, Resume, and JSONL Truth

~16 min · sessions, resume, jsonl, persistence

Level 0Observer
0 XP0/64 lessons0/13 achievements
0/150 XP to next level150 XP to go0% complete

Sessions are the SDK's memory

The Agent SDK assigns a session id and persists conversation state internally. With ClaudeSDKClient, the session lives as long as the client; with query(), it is single-use. You can resume a session by id to continue where you left off — the SDK reloads internal state and applies your new prompt.

JSONL as the durable record

The SDK can stream events to a JSONL file. Each line is a typed event: prompt, response chunk, tool use, tool result. cwkPippa makes this its ground truth — SQLite and ChromaDB are derived mirrors that can be rebuilt from the JSONL. Recovery is purge-and-replay, not patch-and-reconcile.

Resume across processes

If your worker process restarts, you can spin up a new ClaudeSDKClient with the same session id and the SDK will recover. This is what enables cwkPippa's heartbeat jobs to survive a server restart without losing conversational state.

Principle: Treat JSONL as the source of truth. Anything else (DB rows, indices) is a cache that must be rebuildable.

Code

Stream events to JSONL·python
import json, pathlib
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions

async def run_with_jsonl(conv_id: str, prompt: str):
    log_path = pathlib.Path(f"/var/lib/myagent/sessions/{conv_id}.jsonl")
    log_path.parent.mkdir(parents=True, exist_ok=True)
    log = log_path.open("a", buffering=1)  # line-buffered

    client = ClaudeSDKClient(options=ClaudeAgentOptions(cwd="/srv"))
    await client.connect()
    try:
        async for event in client.send_message(prompt):
            log.write(json.dumps({"event": event.dict()}) + "\n")
            log.flush()  # write before show
            forward_to_user(event)
    finally:
        await client.disconnect()
        log.close()
Resume a session by id·python
# session_id is whatever the SDK assigned (or you assigned at connect time).
options = ClaudeAgentOptions(
    cwd="/srv",
    resume=session_id,  # SDK reloads internal state
)
client = ClaudeSDKClient(options=options)
await client.connect()
async for event in client.send_message("Continue where we left off."):
    print(event)

External links

Exercise

Add JSONL streaming to one Agent SDK call in your project. Crash the process mid-stream. Restart with the same session id and confirm you can continue the conversation. Verify the JSONL has every delta from the crashed turn.
Hint
If your downstream store and the JSONL disagree, trust the JSONL — purge and replay. That is the discipline.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.