Route LLM responses by what they actually are
When you process model output programmatically, the first question is always: what format is this? A response might be clean JSON, markdown, a code snippet, CSV rows, or plain prose — and treating one as another breaks your pipeline. This detector classifies the structural type, validates JSON for real, and flags responses that mix prose with a structured block so you can extract instead of parse.
The five response types and what breaks if you misidentify them
JSON — if you call JSON.parse on text that looks like JSON but has a trailing comma, an unquoted key, or surrounding prose, you get an exception. The fix differs by cause: strip prose before parsing, run a JSON repair, or re-prompt for clean JSON only.
Markdown — if you render markdown as plain text, you get raw symbols. If you try to JSON.parse markdown you get an exception. If you index it for search without stripping headings and bullets, your search quality degrades.
Source code — pasting code into a plaintext processor loses indentation meaning. Sending a code block to a text summarizer often produces poor results because the summarizer is not trained to handle code structure.
CSV — delimited rows parsed as plain text silently corrupt downstream data imports. The opposite — trying to JSON.parse a CSV response — fails immediately and obviously.
Mixed format — the most common pipeline-breaker. A model instructed to “return JSON” responds with a paragraph of explanation followed by a fenced JSON block. Calling JSON.parse on the whole response fails; you need to extract only the fenced block first.
How it works
The detector applies ordered heuristics. First it attempts to parse the text as JSON, both directly and after stripping a surrounding code fence, because valid JSON is the most actionable result. If that fails it scans for markdown signals — ATX headings, bullet and numbered lists, links, and emphasis. It detects source code by fenced language hints and common keyword density, and checks for consistent delimited rows that indicate CSV. The format with the strongest evidence is reported, along with a note on whether any embedded JSON or code block is present, which is the mixed-format case.
Practical example — catching a mixed-format response
Suppose you instruct a model: “Return a JSON object with fields name, role, and salary.”
The model responds:
Sure! Here's the JSON you requested:
```json
{"name": "Alex", "role": "Engineer", "salary": 85000}
This should work for your use case.
The structure detector flags this as **mixed format: prose + JSON block**. The embedded JSON is valid, but calling `JSON.parse` on the whole response would fail. You need to extract the fenced block first, then parse it. The detector shows you this before your code runs into the exception.
## Tips and notes
Use the parse result, not just the type label: a response can look like JSON but
fail to parse, and that distinction determines whether you can call JSON.parse
directly or need a repair step. When a response is flagged as mixed-format, reach
for an extraction step that pulls out the fenced block rather than parsing the
whole thing. Detection is heuristic, so for short or ambiguous inputs it can
misclassify — pair it with strict parsing in code. Everything runs
locally and instantly, so drop it into any debugging workflow without cost or
privacy concerns.