OpenAI SDK
No extra dependency: the client is duck-typed, so the official SDK, Azure OpenAI, vLLM, LiteLLM proxies and test fakes all work.
from openai import OpenAIfrom beacon.integrations.openai_sdk import validated_completion
client = OpenAI()result = validated_completion( client, model="gpt-4o", messages=[{"role": "user", "content": "Classify: I want to cancel"}], schema={"type": "object", "properties": {"intent": {"type": "string"}}, "required": ["intent"]},)# -> {'intent': 'cancel'}from openai import AsyncOpenAIfrom beacon.integrations.openai_sdk import avalidated_completion
result = await avalidated_completion(AsyncOpenAI(), model="gpt-4o", messages=msgs, output_model=Intent)# -> Intent(intent='cancel', confidence=0.93)Options
Section titled “Options”| Parameter | Meaning |
|---|---|
schema |
JSON Schema to validate against; defaults to output_model.model_json_schema() |
output_model |
Pydantic model class to build from the JSON |
select, kind |
passed to extract_json |
create |
use another endpoint, e.g. create=client.responses.create (reads output_text) |
**kwargs |
forwarded to the create call unchanged |
Failures
Section titled “Failures”- No JSON, malformed JSON or schema violations raise
MalformedOutputError/SchemaValidationError, with.rawset to the model text. - A refusal or empty content raises
MalformedOutputErrorwith codeopenai.no_content.
Tool calls
Section titled “Tool calls”from beacon.integrations.openai_sdk import validated_tool_call
calls = validated_tool_call(response, tool_schemas={ "get_weather": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},})# -> [{'name': 'get_weather', 'arguments': {'city': 'Paris'}}]Native message.tool_calls are used when present, and their JSON-string arguments are parsed strictly. Otherwise tool calls are parsed from the message text with parse_tool_calls, which covers models that write calls as text. With tool_schemas, each call’s arguments are validated, and a call to an unknown tool raises openai.unknown_tool.