OpenAI & Anthropic SDKs: Structured Outputs & Function Calling
Master official Python SDKs for OpenAI and Anthropic: Enforce 100% deterministic JSON schemas with Structured Outputs and implement multi-step Tool/Function Calling.
Key Takeaways
- Structured Outputs (`response_format=PydanticModel`) guarantee 100% adherence to defined JSON schemas, eliminating JSON parse errors in production
- Function Calling / Tool Calling enables models to intelligently select and format arguments for external Python functions and database queries
- Anthropic Messages API and OpenAI Chat Completions follow structured multi-turn conversation formats (`system`, `user`, `assistant`, `tool`)
- Managing context window token limits and caching prompts (`prompt_caching`) slashes API costs by up to 90%
The Diagnostic Context
Parsing unstructured text or hoping an LLM returns valid JSON using prompt engineering is unreliable in production. Modern OpenAI and Anthropic SDKs support constrained decoding (Structured Outputs) and native Tool Calling to guarantee deterministic integration with backend systems.
The Core Technique
100% Deterministic Structured Outputs (OpenAI SDK)
from openai import OpenAI
from pydantic import BaseModel, Field
client = OpenAI()
class OrderExtraction(BaseModel):
order_id: str = Field(description="Order identifier starting with ORD-")
customer_name: str
items_count: int = Field(ge=1)
total_amount: float = Field(description="Total currency amount in USD")
is_expedited_shipping: bool
# Constrained decoding guarantees the model output strictly matches the Pydantic schema:
completion = client.beta.chat.completions.parse(
model="gpt-4o-2024-08-06",
messages=[
{"role": "system", "content": "Extract structured order information from customer emails."},
{"role": "user", "content": "Hi, this is Alice Smith. Regarding my order ORD-88192 for 3 laptops totaling $4,200.00, please make sure it's sent via expedited overnight shipping!"}
],
response_format=OrderExtraction,
)
# Parsed response is already an instantiated, validated Pydantic model object:
order: OrderExtraction = completion.choices[0].message.parsed
print(f"Parsed Order ID: {order.order_id}, Expedited: {order.is_expedited_shipping}")
Function / Tool Calling Mechanics in Anthropic Claude 3.5
import anthropic
client = anthropic.Anthropic()
tools_definition = [
{
"name": "get_stock_price",
"description": "Retrieves the current stock market price and daily change for a given ticker symbol.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {"type": "string", "description": "The stock ticker symbol (e.g., AAPL, GOOGL)"}
},
"required": ["ticker"]
}
}
]
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
tools=tools_definition,
messages=[
{"role": "user", "content": "Can you check the current stock price of Apple (AAPL)?"}
]
)
# Check if model decided to call a tool:
for block in response.content:
if block.type == "tool_use":
print(f"Model requested tool: {block.name} with arguments: {block.input}")
# Execute local Python function: get_stock_price(ticker="AAPL")
Try This Right Now
Implement a complete tool-calling loop: Define a mock `get_weather(city: str)` tool, send a prompt to the model, inspect the `tool_use` response, execute the local function, and send the tool result back to the model for the final synthesized answer.
Tip: Knowledge only becomes capability once you run the prompt yourself.