Staso Docs
Quickstart

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 raises st.GuardBlocked.
  • @st.tool records 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 categoryOpenAI Chat Completions fields
requestUser/request messages and request options such as sampling and stop settings.
system_promptsystem and developer messages.
tool_schematools, tool_choice, and structured response-format settings.
tool_argumentsFunction-call arguments in request or response messages.
outputAssistant 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.

Next