Response Prefilling for Format Control
Response prefilling was once the standard way to force Claude into a format through the API. That has changed. The latest Claude models reject prefilled responses, and Anthropic now gives you better tools for the same job. This lesson explains what prefilling was, where it still works, and what to use for format control today.
What Response Prefilling Is
In the Claude API, a conversation is a list of messages with user and assistant roles. Normally you send user messages and Claude writes the assistant messages. Prefilling meant writing the start of the assistant message yourself, so Claude had to continue from it.
Here is what a prefilled request looked like:
{
"messages": [
{
"role": "user",
"content": "Analyze the sentiment of this review: 'The product broke after one week.'"
},
{
"role": "assistant",
"content": "{"
}
]
}
Claude received the partial { and completed the JSON object. People used the same trick with a code fence to get code only, or with an opening XML tag to get XML.
Prefilling No Longer Works on Current Models
Starting with the Claude 4.6 models, the API no longer supports a prefilled response on the last assistant turn. A request that ends with a partial assistant message returns a 400 error. This applies to every model released since then, including the whole current lineup.
Three things to know:
- Older models still accept prefill. If you maintain code that runs on a model from before the 4.6 generation, the prefill still works there. It will break when you move that code to a newer model.
- Assistant messages earlier in the conversation are fine. Only a partial assistant message at the very end of the list is rejected. Normal multi-turn history is not affected.
- You rarely need it now. Anthropic's guidance is that current models follow format instructions well enough that most prefill use cases no longer need a prefill.
So treat prefilling as a legacy technique. You should recognize it in old code and know how to replace it. The rest of this lesson covers the replacements.
Replacement 1: Structured Outputs
Structured outputs are the direct replacement for the { prefill. You pass a JSON schema with the request, and the API constrains Claude's response to match it. You do not hope for valid JSON. The response is built to fit your schema.
In the Messages API, the schema goes in output_config.format:
import json
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "Analyze the sentiment of this review: 'The product broke after one week.'",
}
],
output_config={
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"sentiment": {
"type": "string",
"enum": ["positive", "neutral", "negative"],
},
"reason": {"type": "string"},
},
"required": ["sentiment", "reason"],
"additionalProperties": False,
},
}
},
)
text = next(block.text for block in response.content if block.type == "text")
result = json.loads(text)
A few rules to remember:
- Every object in the schema needs
"additionalProperties": false. - List the fields you always want under
required. - Check
stop_reasonbefore you parse. If Claude refuses the request (refusal) or runs out of room (max_tokens), the output may not match the schema. - Compare
enumvalues without case sensitivity. Claude can occasionally change the capitalization of a value.
The Python SDK also has a client.messages.parse() helper that accepts a Pydantic model and returns a parsed object, so you do not have to write the schema by hand.
For classification, you have a second option: define a tool with an enum field that holds your valid labels. Both approaches limit Claude to the values you allow.
Replacement 2: Format Instructions in the System Prompt
Prefills such as Here is the summary: were used to skip the introduction. Today a direct instruction does that job. Put it in the system prompt so it applies to every turn:
Current models follow instructions like these reliably. When the output feeds a parser, add a simple safety net in code: strip any stray text before the first {, or retry the request if parsing fails.
This is also the right tool when you cannot change the API request. The Claude apps, Projects, and many third-party tools do not let you set output_config. Clear format instructions work everywhere.
Replacement 3: XML Tags for the Output
The old XML prefill opened a tag such as <analysis> and let Claude continue inside it. You can get the same result by asking for the tags in your prompt:
Your code then reads the text between the tags. This works well when you want free-form text in clearly marked sections, where a strict JSON schema would be too rigid. It is the same idea as the XML output tags you learned earlier in this course, used here to control the shape of the response.
For code-only output, the pattern is the same. Ask for the code in a single fenced code block, with no explanation before or after, and extract the block in code.
Choosing the Right Tool
| You need | Use |
|---|---|
| JSON that must match a schema every time | Structured outputs (output_config.format) |
| One label from a fixed list | Structured outputs, or a tool with an enum field |
| No preamble, a certain tone or length | Format instructions in the system prompt |
| Free-form text in labeled sections | XML tags in the prompt |
| Format control in the Claude apps or Projects | Format instructions and XML tags |
| Old code on a model from before the 4.6 generation | Prefill still works, but plan to migrate |
Try It: Format Control with Instructions
The playground below uses format instructions alone, with no prefill. Run it and check that the response is a bare JSON object. Then remove the last line and run it again to see what the instruction was doing.
In an API integration, you would move the list of keys into a JSON schema and pass it as a structured output. The schema then does the work that the last instruction line does here.
Migrating an Old Prefill
If you find a prefill in existing code, use this map to replace it.
Exercise: Design a Format-Controlled Extraction Prompt
You are building a document processing pipeline. Users submit legal contract excerpts and your application needs structured data about the parties, dates, and key obligations. Design a prompt that returns this information as JSON reliably on current Claude models, without a prefilled assistant turn.
Key Takeaways
Response prefilling meant writing the start of Claude's reply yourself, so Claude had to continue from it. It only works on older models. Starting with the Claude 4.6 models, a request that ends with a partial assistant message returns a 400 error. For JSON that must match a schema, use structured outputs with output_config.format. To remove preamble or set a style, put direct format instructions in the system prompt. For labeled sections of free-form text, ask for XML tags. These tools cover what prefilling used to do, and format instructions and XML tags also work in the Claude apps, where prefilling was never available.
Up next · Lesson 10 of 26
Claude Projects and Custom Instructions
5 min read
9 of 26 lessons done

