Available for: Python and TypeScript.
wrapOpenAI() (TypeScript) or patch the openai module with patch_openai() (Python). Every chat.completions.create call your existing code makes is traced automatically — no changes to call sites required.
Only
chat.completions.create is instrumented today — this covers standard chat and streaming chat calls, including function/tool calling. embeddings.create, the Responses API, and other OpenAI endpoints (images, audio, moderations) are not currently traced by either SDK.Installation
Setup
wrapOpenAI() returns a wrapped client instance — pass it to any function that makes OpenAI calls, and use it exactly like the original client. In Python, patch_openai() monkey-patches openai.resources.chat.completions.Completions.create in place, so openai.OpenAI() (constructed after patching) is traced automatically with no wrapping step.
Example
What gets captured
Prompt and completion text is stored by default, with PII redaction applied before transmission. Set
storePrompts: false (store_prompts=False in Python) in zespan.init() to disable prompt/completion storage entirely.Streaming
Both wrappers support streaming. Token counts and tool calls are accumulated from the stream chunks, and time-to-first-token (ttft_ms) is recorded on the first chunk.
Tool and function calls
Passtools as usual. Zespan records the tool definitions from the request and, once the model responds, the names and arguments of any tools it decided to call — for both streaming and non-streaming calls, in both languages.
Guardrails
Passguardrails: true (guardrails=True in Python) to run pre- and post-call content checks against your configured guardrail policies.
GuardrailBlockedError — catch it to return a safe fallback instead of letting the exception propagate. See Guardrails for the full configuration options (pre/post/failClosed), the GuardrailBlockedError shape, and how to call guardrail checks directly outside of a wrapped call.
Error handling
On failure, both wrappers re-throw (Python: re-raise) the original OpenAI SDK error after recording anerror-status event with error_message — your existing try/catch (try/except) around the call keeps working unchanged.
- Status classification. TypeScript inspects
err.statusand reportsrate_limitedfor HTTP 429 andtimeoutfor HTTP 408 (in addition toerrorfor everything else, andguardrail_blockedas theerror_codewhen aGuardrailBlockedErroris thrown). The Python wrapper does not currently classify errors this way — every exception is recorded with statuserror. - Guardrail blocks. In TypeScript, a guardrail block still enqueues an
error-status event (witherror_code: "guardrail_blocked") before re-throwing. In Python,GuardrailBlockedErroris re-raised immediately without an error event being recorded. - Config-driven resilience. Retries, timeouts, concurrency limits, fallback models, and A/B testing are not options you pass to
wrapOpenAI()/patch_openai()directly — they’re project-level rules pushed from the Zespan dashboard via config propagation and applied automatically to every call. The TypeScript wrapper applies all of these (model override, A/B test, retry with backoff, timeout, concurrency limiting, and fallback-on-error). The Python wrapper currently applies model override, A/B testing, and fallback-on-error, but not retry, timeout, or concurrency limiting.
Next steps
- Guardrails — full guardrail configuration and
GuardrailBlockedErrorreference - Config propagation — how model overrides, fallbacks, retries, and timeouts get pushed to running apps
- Agent tracing — wrap multi-step agent logic
- Manual spans — add custom spans around non-LLM operations
- PII redaction — automatically redact sensitive data before storage

