In a few-shot prompt that extracts structured fields from invoices, why is a distinctive stop sequence (like a custom END_INVOICE marker) better than a paragraph break or the natural end of response?
You're an LLM engineer designing a few-shot prompt that extracts structured fields (vendor, total, line items) from invoice text. You're picking how the model should signal the end of each extracted record. Walk through why a distinctive stop sequence (like a custom END_INVOICE marker) is better than a paragraph break or relying on the model's natural end of response, and what properties make a stop sequence robust.
A marker like END_INVOICE is collision-safe, self-anchoring through few-shot demos, decoupled from format changes, and composable across tasks. Pair it with the API's stop_sequences for byte-level enforcement.
Imagine you are training a friend to read invoices and write down what they see. You could tell them 'stop when you reach a blank line' but invoices have blank lines inside them. Instead you say 'when you are done with each invoice, write THE END on its own line'. Now you have a clear signal that will not be confused with anything inside the invoice. You also show them ten example invoices that all end with THE END, so they pick up the habit. And you tell the machine reading their notes to ignore anything after THE END. Three layers, one clean signal.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Stop-sequence design looks like a small implementation detail and is one of the highest-leverage decisions in a structured-extraction prompt. Get it right and the pipeline produces clean records with high reliability. Get it wrong and the long tail of edge cases (records truncated mid-field, premature termination on internal blank lines, downstream parsers choking on commentary) compounds into a quality problem that is hard to diagnose because each individual failure looks like a different bug.
The right framing is that the terminator is a contract between three layers: the few-shot demonstrations that train the model to emit the marker, the model's actual generation behavior, and the API's stop_sequences parameter that enforces the boundary at the byte level. The contract works only if all three layers agree on what the marker is and what it means.
The deep dive walks through what makes a terminator robust, why the few-shot layer is the source of the self-anchoring property, how the API parameter provides the only structural enforcement in the stack, the composability advantages of distinct terminators per record type, and the parser layer that catches the long tail.
What makes a stop sequence robust
Four properties together. First, collision safety: the marker is structurally impossible inside legitimate output. Paragraph breaks fail this because real invoices have blank lines between address lines, line items, and totals blocks. Single common words like END fail because they appear inside English text. The marker should be a multi-character distinctive sequence (END_INVOICE, </invoice>, ###RECORD_END###) that you can confidently say will never appear inside a real record.
Second, self-anchoring: the marker appears in every few-shot demonstration in the prompt. The model treats the demonstrations as the strongest signal of what the output should look like, and a marker that appears in every demonstration becomes part of the shape the model wants to produce. A marker that is only described in the system-prompt instruction is much weaker; the model may or may not emit it depending on phrasing.
Third, decoupling from the format: the marker should not depend on the structure of the record. A closing brace as a terminator couples the termination contract to the JSON format; changing to a list of fields format requires a new terminator. A custom sentinel does not change when the format does.
Fourth, composability: in a multi-task prompt, each record type gets its own terminator so the boundaries between records remain unambiguous when outputs are concatenated. Reusing one terminator across record types loses this advantage.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- Anthropic's prompt-engineering cookbook recommends XML-style closing tags as stop sequences for structured extraction with Claude Opus 4.7, with the tag demonstrated in every few-shot example.
- OpenAI's GPT-5.5 vision-extraction examples for invoices and receipts pair a distinctive END_RECORD sentinel with the stop parameter and few-shot demonstrations of the terminator.
What an interviewer would ask next. Try answering before peeking at the approach.
QHow would you handle a case where the model genuinely needs to emit content containing your terminator?
Pick a structurally impossible sentinel (long uppercase identifier like END_INVOICE_RECORD_V1), or escape conflicts in few-shot demonstrations, or switch to a structured-output mode where the SQL or text is inside a JSON field that does the escaping for you.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Using a paragraph break as the terminator on a structured-extraction prompt, then watching extractions get truncated whenever the model produces a blank line inside a multi-line address or line-item block.
60 second bullets to scan on the way to the call.
Why paragraph breaks are unsafe as terminators on structured extraction
The self-anchoring property and how few-shot examples create it
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.