How to chain structured output calls
Quick answer
Use the
response_format parameter in AI API calls to define expected output schemas, then pass outputs from one call as inputs to the next to chain calls. This enables reliable multi-step workflows with typed data between calls.PREREQUISITES
Python 3.8+OpenAI API key (free tier works)pip install openai>=1.0
Setup
Install the openai Python SDK and set your API key as an environment variable.
- Run
pip install openai - Set
export OPENAI_API_KEY='your_api_key'on Linux/macOS orsetx OPENAI_API_KEY "your_api_key"on Windows
pip install openai Step by step
This example demonstrates chaining two structured output calls using the OpenAI SDK. The first call extracts user info as a structured JSON object. The second call uses that output to generate a personalized greeting.
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
# Step 1: Extract structured user info
response1 = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Extract name and age from: 'Alice is 30 years old.'"}],
response_format={
"type": "json_schema",
"json_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "age"]
}
}
)
user_info = response1.choices[0].message.content
# Step 2: Use structured output from step 1 to generate greeting
response2 = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a friendly assistant."},
{"role": "user", "content": f"Generate a greeting for a person named {user_info['name']} who is {user_info['age']} years old."}
]
)
print("Extracted user info:", user_info)
print("Greeting:", response2.choices[0].message.content) output
Extracted user info: {'name': 'Alice', 'age': 30}
Greeting: Hello Alice! It's great to know you are 30 years old. Common variations
You can chain structured outputs asynchronously using async Python with the OpenAI SDK. Also, you can use different models like gpt-4.1 or Anthropic's claude-3-5-sonnet-20241022 with similar structured output parameters. For streaming, handle partial outputs but chaining requires waiting for full structured output.
import asyncio
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
async def main():
response1 = await client.chat.completions.acreate(
model="gpt-4.1",
messages=[{"role": "user", "content": "Extract city and country from: 'Paris, France'"}],
response_format={
"type": "json_schema",
"json_schema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"country": {"type": "string"}
},
"required": ["city", "country"]
}
}
)
location = response1.choices[0].message.content
response2 = await client.chat.completions.acreate(
model="gpt-4.1",
messages=[{"role": "user", "content": f"Describe the weather in {location['city']}, {location['country']}."}]
)
print("Location:", location)
print("Weather description:", response2.choices[0].message.content)
asyncio.run(main()) output
Location: {'city': 'Paris', 'country': 'France'}
Weather description: Paris, France typically enjoys mild spring weather with occasional showers and pleasant temperatures. Troubleshooting
- If the structured output is missing or malformed, verify your
response_formatJSON schema matches the expected output format. - Ensure the model supports structured output (e.g.,
gpt-4oor newer). - If chaining fails, check that you correctly extract and pass the structured output between calls.
Key Takeaways
- Use the
response_formatparameter to define expected output schemas for reliable data extraction. - Chain calls by passing structured outputs as inputs to subsequent calls to build multi-step workflows.
- Use async calls for concurrency but await full structured output before chaining.
- Validate your JSON schema to avoid malformed outputs.
- Choose models like
gpt-4oorgpt-4.1that support structured output.