OpenAI Chat Completions
This launch path supports synchronous and asynchronous, non-streaming chat.completions.create calls under an explicit @st.agent root.
For the pinned onboarding sample with exact environment variables and expected trace shape, start with Launch quickstart. This page is the detailed OpenAI reference.
Install
pip install "staso[openai]"
export STASO_API_KEY=ak_...Synchronous example
import json
import staso as st
from openai import OpenAI
st.init(agent_name="weather-agent")
client = OpenAI()
TOOLS = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the weather for a city.",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}
]
@st.tool
def get_weather(city: str) -> dict:
return {"city": city, "temperature_c": 18}
@st.agent
def answer(question: str) -> dict | str:
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": question}],
tools=TOOLS,
)
except st.GuardBlocked as blocked:
return f"Blocked: {blocked.reason}"
tool_call = response.choices[0].message.tool_calls[0]
return get_weather(**json.loads(tool_call.function.arguments))st.init() patches the installed OpenAI SDK. @st.agent supplies the supported root; @st.tool records the real tool call.
Asynchronous example
import staso as st
from openai import AsyncOpenAI
client = AsyncOpenAI()
@st.agent
async def answer_async(question: str) -> str:
response = await client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": question}],
)
return response.choices[0].message.content or ""Do not pass stream=True on the supported launch path.
Guard behavior
When a non-streaming response contains tool proposals, Staso evaluates configured Guard policies before the response reaches the normal dispatch loop.
- Audit findings emit a
guard:would-block:<tool>child span and allow the response through. - A block emits a
guard:blocked:<tool>child span and raisesst.GuardBlocked. @st.toolrecords execution after an allowed proposal is dispatched. It does not run Guard itself.
Guard fails open when no policy decision is available by default. See manual checks for the optional fail-closed setting and stable failure fields.
Captured fields
The LLM span records supported fields exposed by the provider SDK, plus token usage when the response includes it. Cost is estimated by the Staso service for recognized models and may be unavailable.
| Capture category | OpenAI Chat Completions fields |
|---|---|
request | User/request messages and request options such as sampling and stop settings. |
system_prompt | system and developer messages. |
tool_schema | tools, tool_choice, and structured response-format settings. |
tool_arguments | Function-call arguments in request or response messages. |
output | Assistant text/refusal content, prior assistant/tool-result messages, and response tool-call payloads. |
Tool-call names, IDs, model, token counts, latency, status, and response IDs can remain as operational correlation data when their content category is suppressed. Arguments embedded in assistant output require both tool_arguments and output.
All categories default to enabled. Configure them with st.init(capture_<category>=...) or STASO_CAPTURE_<CATEGORY>. See SDK setup for precedence and suppression semantics.