OpenAI Agents SDK
Run the OpenAI Agents SDK against sference: Responses API, tools, handoffs, guardrails, and background steps on the 24h window.
OpenAI Agents SDK
The OpenAI Agents SDK is built on the Responses API, which sference serves natively. Point the client at sference and agents, handoffs, and guardrails run on open models.
Install
pip install -U openai-agentsPoint the SDK at sference
import os
from agents import set_default_openai_client, set_default_openai_api
from openai import AsyncOpenAI
client = AsyncOpenAI(
base_url="https://api.sference.com/v1",
api_key=os.environ["SFERENCE_API_KEY"],
)
set_default_openai_client(client)
set_default_openai_api("responses")Model names are catalog ids:
from agents import Agent, Runner
agent = Agent(
name="Assistant",
model="zai-org/GLM-5.3",
instructions="You are a concise assistant. Answer in one paragraph.",
)
result = await Runner.run(agent, "Explain prefix caching in one paragraph.")
print(result.final_output)Tools
The SDK's function-tool decorator produces the OpenAI tool schema, which sference accepts unchanged:
from agents import function_tool
@function_tool
def search_docs(query: str) -> str:
"""Search the internal documentation."""
return docs_index.search(query)
agent = Agent(
name="Docs assistant",
model="moonshotai/Kimi-K3",
instructions="Answer using search_docs. Cite the document title.",
tools=[search_docs],
)
result = await Runner.run(agent, "How do I rotate an API key?")Structured output
Use output_type with a Pydantic model — the SDK maps it to a JSON schema on the Responses API:
from pydantic import BaseModel
class Triage(BaseModel):
severity: str
team: str
summary: str
agent = Agent(
name="Triage",
model="zai-org/GLM-5.3",
instructions="Classify the ticket.",
output_type=Triage,
)
result = await Runner.run(agent, ticket_text)
triage: Triage = result.final_outputHandoffs
from agents import Agent, handoff
billing = Agent(name="Billing", model="zai-org/GLM-5.3-Flash", instructions="Handle billing questions.")
technical = Agent(name="Technical", model="zai-org/GLM-5.3", instructions="Handle technical questions.")
triage = Agent(
name="Triage",
model="zai-org/GLM-5.3-Flash",
instructions="Route the user to the right specialist.",
handoffs=[handoff(billing), handoff(technical)],
)
result = await Runner.run(triage, "My invoice is wrong.")Use a cheap, fast model for the router and a stronger one for the specialist — the catalog spans GLM-5.3-Flash (0.20 / 0.60) to Kimi-K3 (3.00 / 15.00), so routing decisions are the natural place to economize.
Guardrails
from agents import Agent, GuardrailFunctionOutput, input_guardrail, Runner
@input_guardrail
async def no_pii(ctx, agent, input):
flagged = contains_pii(str(input))
return GuardrailFunctionOutput(output_info={"pii": flagged}, tripwire_triggered=flagged)
agent = Agent(
name="Support",
model="zai-org/GLM-5.3",
instructions="Answer support questions.",
input_guardrails=[no_pii],
)Background steps on the 24h window
The SDK's Runner is synchronous from your code's perspective, but individual steps do not have to be. For long-horizon work — research passes, bulk classification, overnight evaluation — submit the step as a background response and collect it later:
response = await client.responses.create(
model="zai-org/GLM-5.3",
input=research_question,
background=True,
metadata={"completion_window": "24h"},
)
print(response.id) # collect later, or register a webhookBackground responses bill at 0.5 × the list rate. For steps where someone is waiting but which are not on the critical path, service_tier: "flex" gives 0.7 ×. See Pricing.
`store` and conversation state
sference answers every request from the content you send — there is no server-side thread to point at. Pass the full conversation in input on each turn (the SDK does this by default) and do not rely on previous_response_id or a stored conversation. See API compatibility.
Tracing
The SDK's tracing exports to OpenAI's platform by default. To disable it or point it elsewhere:
from agents import set_tracing_disabled
set_tracing_disabled(True)Cost control
client = AsyncOpenAI(
base_url="https://api.sference.com/v1",
api_key=os.environ["SFERENCE_API_KEY"],
default_headers={"X-Sference-Run": run_id}, # your own correlation header
)prompt_cache_key— set it to the run id so the system prompt and tool definitions bill at the cached rate on every step. See Prompt caching.max_queue_wait_s— bound the wait and fail over. See Max queue wait.- Cheap routers, strong specialists — handoffs and guardrails rarely need the largest model.