Output Handling
Output Handling is 2.6% of the CCDV-F blueprint. It tests the seam between a response and the code consuming it: typed content blocks, branching on the stop signal, assembling a stream, and validating meaning rather than shape.
Written by Kiran Manne
2.6% of the CCDV-F blueprint, which is roughly 1 question of 53. It sits inside Prompt and Context Engineering, worth 11% in total.
Output Handling accounts for 2.6% of the blueprint, one or two scored questions, and it has the best facts-per-minute ratio in its domain because nearly every point is a precise, checkable mechanic rather than a judgement call.
The subject is the seam between a model response and the code consuming it, and that seam has three parts. Getting the response into a shape your code expects. Reading it correctly once it arrives. Behaving sensibly when the shape does not hold. The middle part is where working developers are most often caught out: a response body is a list of typed content blocks rather than a string, and assuming the answer is the first block is a bug waiting for the day somebody enables reasoning or the model decides to call a tool.
The third part is what the exam presses hardest. Constraining a format removes the ordinary failure and leaves the extraordinary ones, and each carries a distinct signal. A generation that ran out of room, a request that was declined, a turn that ended because a tool is wanted: your parser should never see any of them, because a branch upstream should already have decided what happens next.
Learn the block structure and the stop signals and this becomes free marks.
What the exam tests here
- Reading a response as an ordered list of typed blocks rather than as a single string
- Branching on the stop signal before any parsing or downstream effect happens
- Assembling a streamed response, including tool arguments that arrive as fragments of JSON
- Separating schema conformance from semantic correctness during validation
- Recovering from a generation that stopped short without repeating side effects
A response is a list of blocks
Content comes back as an ordered array of typed blocks. Text is one type, a tool request is another, and on a reasoning-enabled request the model's deliberation arrives in its own block type ahead of the answer. Any of these can be absent, and more than one text block can appear in a single response.
So indexing into the first element and reading its text is fragile in a specific, delayed way: it works throughout development and breaks the day reasoning is switched on or a tool is chosen, because position zero is no longer the answer. Filter by block type and join the text blocks you actually want. The same discipline applies when appending the assistant turn back into the conversation, where the whole list must be preserved rather than flattened.
Branch on the stop signal, then parse
Every response carries a reason it stopped, and each value implies a different next action. A normal completion is the only one where handing the body to a parser is correct. A generation that hit its ceiling is truncated and its JSON will not close. A turn that paused to call a tool has no final answer yet and belongs back in the loop. A declined request returns successfully with little or nothing usable, and no exception handler will catch it because nothing was thrown.
Structure the consuming code accordingly: read the stop signal, dispatch on it, and let only the completed case reach the parser. Code that wraps everything in a try block instead conflates truncation, refusal and genuinely malformed output into one path and applies the same retry to all three.
Streaming changes assembly, not semantics
A streamed response arrives as a sequence of events: blocks opening, deltas appending to them, blocks closing, and a final event carrying the stop reason together with the token usage. Nothing is complete until its block closes, and one consequence catches people out.
Tool arguments stream as fragments of JSON text, appended piece by piece, so a fragment is not parseable on its own and a parser run per delta fails on every one of them. Accumulate first, decode once. The final event is also where the stop reason lives, which means a client that stops listening the moment it has enough text to display has discarded exactly the field it needs to decide whether the answer was finished.
Valid is not correct
A schema guarantees structure and says nothing about truth. A response can satisfy every constraint you wrote while containing an invented order number, a date outside the range its source supports, or a total that does not match its own line items. Constrained generation moves the failure from parse errors to plausible-looking wrong values, which is a better place for it and not the end of the work.
Keep a semantic layer behind the structural one: check identifiers against the systems that own them, compute arithmetic in code rather than trusting a generated total, and confirm that quoted material appears in the source. This is also why enumerations and required fields earn their keep, each converting a class of semantic error into a structural one you can catch mechanically.
Where candidates go wrong
Trap 1: reading the answer as the first content block
This is the most common runtime break in production code consuming the Messages API, and it stays invisible until configuration changes. It survives every test written against a plain text response and fails as soon as reasoning is enabled, or a tool is offered and taken, because the leading block is now something other than the answer.
Its quieter cousin is dropping non-text blocks when appending the assistant turn back to the history, which corrupts the conversation for the following request. Select by block type in both directions.
Trap 2: retrying a truncated response from the top
When output stops short, resending the identical request is the obvious move and the wrong one: the same ceiling produces the same cut, and you pay a second time for tokens you already had. Raise the limit if the answer legitimately needs the room, or split the task so each call produces a smaller unit.
The retry carries a correctness risk too. A partially completed sequence of tool calls replayed from the beginning will repeat whatever already succeeded, unless those operations were built to tolerate being run twice.
Trap 3: extracting JSON with a regular expression
Where a prompt merely asks for JSON, the consuming code usually grows a helper that finds the first brace, strips a code fence, or matches delimiters with a pattern. It works until the model writes a sentence of preamble, emits two objects, or produces a string field containing a brace. Each of those is a support ticket.
Constrain the format at the API instead of improving the extractor, and where the value is a tool argument, define the schema strictly so arguments arrive already validated. An option that hardens the pattern is treating the symptom.
Common questions
How many CCDV-F questions come from Output Handling?
2.6% of a 53-question paper is one or two. It is the smallest of the three sub-skills in its domain and the densest in exact, memorisable facts, which makes it unusually good value for the time invested.
Why did my code break when I enabled reasoning?
Almost certainly because it reads the first content block. Enabling reasoning inserts a block of a different type ahead of the text, so code that assumed position zero held the answer now returns the wrong thing or nothing. Select blocks by their type and concatenate the text ones.
What should I do with a response that stopped mid-sentence?
Detect it from the stop signal rather than from the ragged text, then decide between a larger generation allowance and a smaller task. Resending the same request unchanged reproduces the same truncation. If the turn had already performed actions, make sure replaying it cannot repeat them.
How do I read tool arguments while streaming?
Accumulate them. Arguments arrive as successive fragments of JSON text that are individually invalid, so decode only after the block closes. Building the string across deltas and parsing once at the end is the whole technique, and attempting to parse each fragment produces an unbroken run of errors.
The rest of Prompt and Context Engineering
- Prompt Engineering (4.6%)
- Context Engineering (3.8%)
Practise this
The CCDV-F bank covers every sub-skill in the blueprint, weighted the way the real paper is. Free sample questions need no account.
Free CCDV-F questions