← The Tickd Guide

Tutorials & Guides

How to Use Claude Prefilling to Force Complex JSON Outputs

Structured outputs are great, but they can slow down your pipeline. Here is how to use Claude's powerful assistant prefill feature to force perfectly schema-compliant JSON every single time.

Updated 9/1/2026

We have all been there. You write a beautifully crafted system prompt, define a rigorous JSON schema, and send it off to an LLM. Most of the time, things run smoothly. But then, a rogue string escapes, or the model decides to wrap its output in conversational pleasantries like "Here is the JSON you requested:". Your parser chokes, the pipeline halts, and you are left writing custom regex patterns to clean up the mess.

While native structured output modes are highly useful, they can sometimes introduce unwanted latency or restrict your ability to stream responses fluidly. If you are building on /platforms/claude, there is a simpler, more elegant way to guarantee schema compliance without sacrificing speed: assistant message prefilling.

By feeding Claude the first few characters of its own response, you skip the pleasantries, bypass model laziness, and force the output directly into your desired format. Let us look at how this works and how to implement it in your Python backend.

Understanding the Prefill Technique

Most API calls to Claude are structured as a alternating conversation: a user message, followed by an assistant response. In a standard API setup, the assistant's response is generated entirely from scratch by the model.

However, Claude allows you to pass a partially completed assistant message in your API payload. If you open the message with the exact syntax you expect—such as an open curly bracket { or a custom XML tag like <json_output>—the model is forced to continue writing from that exact point. It cannot say "Sure, here is your data", because you have already written the first part of its response for it.

This single trick eliminates conversational filler, ensures the output starts exactly where your parser expects, and significantly lowers the chance of syntax errors. If you are new to these concepts, checking our /glossary for a breakdown of token generation and completions will help you see why this works so reliably.

Step-by-Step Implementation in Python

Let us build a simple helper function to extract structured user profiles. We want Claude to return a specific JSON schema with three fields: name, skills (an array), and years_of_experience (an integer).

To ensure we get perfect JSON, we will prefill the assistant response with the opening curly bracket { and the first key name "name":.

Here is how to set this up using the official Anthropic SDK:

`python import json import os from anthropic import Anthropic

Initialize the client client = Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))

def extract_user_profile(raw_text: str) -> dict: system_prompt = ( "You are a strict data extraction tool. Extract the user's name, list of skills, " "and years of experience from the text. Respond ONLY with a valid JSON object. " "Do not include any markdown formatting, backticks, or introductory text." )

user_prompt = f"Extract data from this bio: '{raw_text}'"

We prefill the assistant's response to force the schema prefill_content = '{\n "name":'

response = client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=1000, temperature=0.0, # Keep it deterministic system=system_prompt, messages=[ {"role": "user", "content": user_prompt}, # This is where the magic happens: {"role": "assistant", "content": prefill_content} ] )

Reconstruct the full JSON string by prepending our prefill full_json_string = prefill_content + response.content[0].text

try: return json.loads(full_json_string) except json.JSONDecodeError as e: print(f"Parsing failed. Raw output: {full_json_string}") raise e

Test run bio = "Hi, I'm Sarah. I've been a Python developer for 8 years, working mostly with Django and FastAPI." profile = extract_user_profile(bio) print(profile) ```

When Claude receives this payload, it does not have the option to write markdown code blocks or say "Certainly!". It sees {\n "name": as its own past output, so it immediately writes the name string and completes the rest of the object.

Leveraging XML Prefills for Nested Arrays

Sometimes you need more than a simple flat JSON object. If you are generating complex, deeply nested JSON or lists of objects, starting with { might not be enough to keep Claude on the rails over a long generation.

In these scenarios, combining XML tags with prefilling is incredibly effective. For complex architectures, check out our /prompts library for structured system designs, but here is the core pattern for your code:

1. Instruct Claude to place its final JSON inside <response> tags in your system prompt. 2. Prefill the assistant message with `<response>{ `. 3. Extract everything between the tags using a simple utility function.

This keeps your API response incredibly clean, structured, and easy to parse, even if Claude decides to output some internal reasoning beforehand (though with the prefill, we usually bypass the reasoning step altogether for maximum speed).

Handling Potential Parsing Edge Cases

While prefilling gets things ticking along beautifully, you should still design your parsing logic defensively. Here are two common edge cases to watch out for:

  • Max Token Limits: If your schema is huge and the model hits its max_tokens limit, the JSON will be cut off, resulting in an invalid string. Always set a comfortable limit and handle partial JSON parsing if you are streaming.
  • Trailing Commas: Occasionally, Claude might add a trailing comma to the last key-value pair in a JSON object. While Python's standard json library rejects this, you can use a library like dirtyjson or json5 to parse slightly malformed strings gracefully.

If you run into persistent validation or connection issues with the API, it is always worth visiting the official developer support portal at https://claude-support.com to check for current rate-limiting policies or platform updates.

Prefilling is a simple, low-overhead pattern that immediately upgrades the reliability of your production LLM pipelines. Give it a try on your next data extraction workflow and stop fighting with conversational noise.

claudeprompt-engineeringpythonjsontutorials

Keep going

Build something with the prompt generator, decode the jargon in the glossary, or compare the tools on our platform deep-dives.