Every LLM project accumulates configuration — prompts, model settings, tool definitions, agent behaviour — and picking the wrong format for it produces a specific, recognisable misery: prompts crammed onto one line with escaped newlines, invisible in code review, edited nervously. The choice is not arbitrary, and it is not the same choice you would make for data.
The short version
YAML for config humans edit — prompts, agent definitions, model settings. Multiline text is the deciding factor and YAML handles it properly.
JSON for data machines exchange — API payloads, tool schemas, model output, anything crossing a trust boundary.
Validate both against a JSON Schema. The format is a serialisation choice; the contract is separate.
The deciding factor: multiline text
A prompt is a paragraph. Sometimes several. Watch what each format does with one.
The JSON version is not merely uglier. It is unreviewable: a one-character prompt change shows in a diff as a modification to a 400-character line, so nobody can see what changed. Since prompts are the part of an LLM system most likely to be edited and most consequential when edited badly, that is a real operational cost rather than an aesthetic complaint.
💡 The two block scalar styles
| preserves newlines — use it for prompts, where line breaks are meaningful.
> folds lines into one paragraph — use it for long descriptions you want wrapped in the file but joined in the value.
Both accept a - suffix (|-) to strip the trailing newline, which is usually what you want for a prompt that is followed by other content.
YAML's traps are real
YAML's readability comes from inferring types from unquoted text, and that inference is where it bites.
These are not hypothetical. The Norway problem has broken real deployments, and the version-number truncation is common in model configuration, where 1.20 and 1.2 may be entirely different releases.
🚨 Quote every value that is not obviously a number
The reliable rule: if a value is meant to be a string, quote it. Version numbers, country codes, model identifiers, anything containing a colon, and anything that could be read as a boolean.
Two more worth knowing. Indentation must be spaces — a tab character is a parse error, and it is invisible. And YAML is a superset of JSON, so any valid JSON is valid YAML, which is occasionally useful during a migration.
The security difference
This one is categorical rather than a matter of taste.
JSON cannot express this. It has six types and no mechanism for instantiating anything, which makes parsing untrusted JSON a bounded operation by construction.
The practical rules that follow:
- Always use the safe-load variant of your YAML library. There is essentially never a reason to use the full loader on config.
- Never load YAML from a user, an upload or a network response. Use JSON at trust boundaries.
- YAML for files in your repository, written by your team, reviewed in pull requests. That is a different trust category and YAML is fine there.
A note on token cost
If your config is sent to a model — as an agent definition, a tool list, a set of examples — the format affects your bill. YAML is modestly cheaper than JSON for nested structures because it drops braces, brackets and most quotes, but it is not a large saving and both lose badly to CSV for repeated records. The full comparison is in token-efficient data formats.
For config specifically, this rarely decides anything. Config is small and sent once; the readability difference matters far more than a handful of tokens.
Validate either one
The most common mistake in this area is treating format choice as a substitute for a contract. It is not — a typo in YAML fails just as silently as a typo in JSON.
additionalProperties: false is the line that earns its place. Without it, temperatue: 0.9 parses cleanly, validates cleanly, and silently uses the default temperature forever. With it, the config fails at load with a message naming the unexpected key.
⚠️ Prompts in config are still code
Because config files feel like settings, prompts stored in them often escape the review discipline applied to code. That is backwards — a prompt change can alter system behaviour more dramatically than most code changes.
Version prompts alongside your code, review changes to them properly, and keep enough structure to know which prompt version produced which output. YAML's readable diffs are what make that review possible, which is the strongest argument for using it here.
A layout that works
The split follows the audience. Files people write and review are YAML. Files that are contracts or travel to an API are JSON, because that is what the API expects and there is no readability requirement to trade against. If you need to move between the two during a migration, our YAML to JSON converter does it in the browser with nothing uploaded.
Converting between YAML and JSON?
Convert and validate config files entirely in your browser — nothing is uploaded to a server.
Open YAML to JSON →Summary
- YAML for human-edited config, JSON for machine exchange and trust boundaries.
- Multiline handling decides it. Escaped prompts in JSON are unreviewable in a diff.
- Use
|for prompts,>for folded descriptions. - Quote every string value. NO becomes false; 1.20 becomes 1.2.
- Always safe-load YAML. Full loaders can instantiate objects.
- Never parse untrusted YAML — that is what JSON is for.
- Validate against a JSON Schema either way, with
additionalProperties: false. - Prompts in config are code. Review them like code.
Frequently Asked Questions
Should I use YAML or JSON for prompt configuration?
YAML, in most cases. Prompts are multiline text with quotes and special characters, which YAML block scalars handle cleanly and JSON forces you to escape into an unreadable single line. For machine-generated config or data moving between services, JSON remains the better choice.
What is the Norway problem in YAML?
In the widely used YAML 1.1 behaviour, the unquoted value 'no' is parsed as the boolean false — so a country code list containing NO for Norway silently becomes false. The same applies to yes, on, off and several other words, which is why value quoting matters in YAML far more than people expect.
How do I put a multiline prompt in JSON?
You escape the newlines as backslash-n and put everything on one line, which works but is unreadable and unreviewable in a diff. If your prompts live in JSON, the usual workaround is to keep them in separate text files and reference the paths from the config instead.
Is YAML safe to load from untrusted sources?
Only with a safe loader. Full YAML can instantiate arbitrary objects in some language bindings, which makes loading untrusted YAML a code execution risk. Always use the safe-load variant, and prefer JSON for anything crossing a trust boundary.
Can I validate YAML with JSON Schema?
Yes. YAML parses to the same basic data structures as JSON, so the standard approach is to load the YAML and validate the resulting object against a JSON Schema. This gives you readable config files with the same validation guarantees as JSON.