cd /news/artificial-intelligence/til-jsonl-is-the-format-ai-agents-we… · home topics artificial-intelligence article
[ARTICLE · art-90901] src=kondasamy.com ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

TIL: JSONL Is the Format AI Agents Were Missing

Cloudflare's post on orchestrating AI code review across thousands of merge requests highlights JSONL as the response surface for unreliable, long-running agent processes, where each line is a complete JSON object that remains parseable even if the process crashes mid-stream. JSONL's line-based format enables crash-safe parsing, appendability, streaming, and concurrency, making it ideal for agent orchestration, fine-tuning datasets, and structured logging. The format is already used by OpenAI, Anthropic, Gemini, Llama, Mistral, and agent runtimes like OpenCode and Claude Code.

read4 min views3 publishedAug 5, 2026
TIL: JSONL Is the Format AI Agents Were Missing
Image: Kondasamy (auto-discovered)

Today I finally understood why JSONL keeps showing up in agent tooling. I used it years ago for big data files and never thought much of it. This week I read Cloudflare’s post on orchestrating AI code review across thousands of merge requests, and the same line kept popping up: every agent process emits JSONL on stdout. That clicked. JSONL is not just a file format here. It is a response surface for unreliable processes.

The Problem With Plain JSON Here #

Standard JSON wraps a dataset inside one array or object. A parser has to see the closing ]

before it can give you a single record. For an agent orchestration job that runs up to 25 minutes across seven concurrent LLM sessions, that is a bad deal. If the process runs out of memory or crashes halfway, you get zero parseable output. Exactly when you need the debug logs, they are unparseable.

[
  { "event": "step_start", "agent": "coordinator", "ts": 1722816000 },
  { "event": "step_finish", "agent": "security", "tokens": 8421 },
  /* process dies here, no closing bracket */
]

That whole blob is invalid JSON. The two records before the crash are gone.

JSONL Just Gives You the Records #

JSONL (JSON Lines) drops the enclosing brackets. Each line is one complete, valid JSON object. Read a line, parse it, move on. No buffering the whole stream into memory. No waiting on a bracket that may never come.

{"event": "step_start", "agent": "coordinator", "ts": 1722816000}
{"event": "step_finish", "agent": "security", "tokens": 8421}

The process dies after line 2? You still have line 1 and line 2. Cloudflare pipes OpenCode with --format json

so all stdout arrives as JSONL events, then buffers and flushes every 100 lines (or 50ms) to save disk from a stream of appendFileSync

calls.

Why This Maps to Agents So Well #

Property Plain JSON JSONL
Crash-safe parsing No, whole doc invalid Yes, each line independent
Appendable No, rewrite the file Yes, just write a new line
Streamable mid-write No, need the close Yes, consumers read as you go
Split across workers No fixed boundaries Line breaks are valid split points
Corrupted record impact Breaks the whole file Skip the bad line, keep going
Diff-friendly One blob, messy diffs git diff works line by line

This is exactly the shape of agent work: long-running, crash-prone, streaming, concurrent. You spawn sub-agents that may take minutes, may hit max_tokens

, may hang for 60 seconds then die. You need a format where partial output is still output.

Where You Will Already See It #

  • Fine-tuning datasets for OpenAI, Anthropic, Gemini, Llama, and Mistral use JSONL. Each line is one training example: an instruction-response pair or a multi-turn conversation.
  • Structured loggers like pino

,structlog

, andzap

emit one JSON object per line so aggregators can index entries without re-parsing the whole file. - OpenCode, Claude Code, and similar agent runtimes expose JSONL event streams on stdout so orchestrators can pull token usage, errors, and truncation signals in real time.

Reading a JSONL Stream in Python #

The pattern stays the same regardless of language: read line by line, parse each line, never hold the whole file.

import json

with open("events.jsonl", "r") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        try:
            event = json.loads(line)
        except json.JSONDecodeError:
            continue  # skip corrupted line, keep the rest
        yield event

That continue

on a bad line is the whole point. One corrupt record does not sink the file.

What I Learned #

  • JSONL exists because plain JSON forces you to close the whole document before any record is parseable, which is the wrong trade for long-running and crash-prone processes.
  • For agent orchestration, JSONL is not just storage. It is the streaming response surface between a parent process and several concurrent LLM sessions.
  • Corrupt one line in JSONL and you lose one record. Corrupt one byte in a JSON array and you lose everything after it.
  • Every major fine-tuning API ships datasets as JSONL because each training example is an independent unit, and append-and-go beats rewrite-the-array.
  • If you are building anything that emits structured output from an LLM agent, start with JSONL. Re-inventing it is a tax, and every agent stack already speaks it.
── more in #artificial-intelligence 4 stories · sorted by recency
── more on @cloudflare 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/til-jsonl-is-the-for…] indexed:0 read:4min 2026-08-05 ·