For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
DiscordPlatform
DocumentationIntegrationsAPI referenceSDKsChangelog
DocumentationIntegrationsAPI referenceSDKsChangelog
  • Integrations
    • Overview
      • OpenAI SDK
      • Instructor
      • Anthropic SDK
      • Google GenAI
      • LiteLLM
      • RubyLLM
      • Vertex AI
      • AWS Bedrock
      • Ollama
      • Watsonx
      • Together AI
      • Aleph Alpha
      • HuggingFace
      • Replicate
      • SageMaker
      • Respan API
LogoLogo
DiscordPlatform
On this page
  • Setup
  • Configuration
  • Attributes
  • In Respan()
  • With propagate_attributes
  • Decorators (optional)
  • Examples
  • Streaming
  • Tool calls
  • Structured output
  • Setup
  • Switch models
  • Prompt management
  • Chat Completions
  • Responses API
  • Respan parameters
IntegrationsLLM SDKs

OpenAI SDK

Was this page helpful?
Previous

Instructor

Next
Built with

The OpenAI SDK is the official client for OpenAI’s APIs, available for both Python and TypeScript/JavaScript. It supports Chat Completions and the Responses API. Respan gives you full observability over every OpenAI call, streamed response, and tool invocation — and gateway routing to 250+ models with prompt management.

Set up Respan

Create an account at platform.respan.ai and grab an API key. For gateway, also add credits or a provider key.

Run npx @respan/cli setup to set up with your coding agent.

Example projects
  • Python examples
  • TypeScript examples
Tracing
Gateway

Setup

1

Install packages

$pip install respan-ai respan-instrumentation-openai openai
2

Set environment variables

$export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
$export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"

OPENAI_API_KEY is used for OpenAI requests. RESPAN_API_KEY is used to export traces to Respan.

3

Initialize and run

1from openai import OpenAI
2from respan import Respan
3from respan_instrumentation_openai import OpenAIInstrumentor
4
5respan = Respan(instrumentations=[OpenAIInstrumentor()])
6
7client = OpenAI()
8
9response = client.chat.completions.create(
10 model="gpt-4.1-nano",
11 messages=[{"role": "user", "content": "Say hello in three languages."}],
12)
13print(response.choices[0].message.content)
14respan.flush()
4

View your trace

Open the Traces page to see your auto-instrumented LLM spans.

Configuration

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to RESPAN_API_KEY env var.
base_urlstr | NoneNoneFalls back to RESPAN_BASE_URL env var.
instrumentationslist[]Plugin instrumentations to activate (e.g. OpenAIInstrumentor()).
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag (e.g. "production").

Attributes

In Respan()

Set defaults at initialization — these apply to all spans.

1from respan import Respan
2from respan_instrumentation_openai import OpenAIInstrumentor
3
4respan = Respan(
5 instrumentations=[OpenAIInstrumentor()],
6 customer_identifier="user_123",
7 metadata={"service": "chat-api", "version": "1.0.0"},
8)

With propagate_attributes

Override per-request using a context scope.

1from openai import OpenAI
2from respan import Respan, propagate_attributes
3from respan_instrumentation_openai import OpenAIInstrumentor
4
5respan = Respan(instrumentations=[OpenAIInstrumentor()])
6client = OpenAI()
7
8def handle_request(user_id: str, question: str):
9 with propagate_attributes(
10 customer_identifier=user_id,
11 thread_identifier="conv_abc_123",
12 metadata={"plan": "pro"},
13 ):
14 response = client.chat.completions.create(
15 model="gpt-4.1-nano",
16 messages=[{"role": "user", "content": question}],
17 )
18 print(response.choices[0].message.content)
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related messages into a conversation.
metadatadictCustom key-value pairs. Merged with default metadata.

Decorators (optional)

Decorators are not required. All OpenAI calls are auto-traced by the instrumentor. Use @workflow and @task (Python) or withWorkflow and withTask (TypeScript) to add structure when you want to group related calls into a named workflow with nested tasks.

1from openai import OpenAI
2from respan import Respan, workflow, task
3from respan_instrumentation_openai import OpenAIInstrumentor
4
5respan = Respan(instrumentations=[OpenAIInstrumentor()])
6client = OpenAI()
7
8@task(name="generate_outline")
9def outline(topic: str) -> str:
10 response = client.chat.completions.create(
11 model="gpt-4.1-nano",
12 messages=[
13 {"role": "system", "content": "Create a brief outline."},
14 {"role": "user", "content": topic},
15 ],
16 )
17 return response.choices[0].message.content
18
19@workflow(name="content_pipeline")
20def pipeline(topic: str):
21 plan = outline(topic)
22 response = client.chat.completions.create(
23 model="gpt-4.1-nano",
24 messages=[
25 {"role": "system", "content": "Write content from this outline."},
26 {"role": "user", "content": plan},
27 ],
28 )
29 print(response.choices[0].message.content)
30
31pipeline("Benefits of API gateways")
32respan.flush()

Examples

Streaming

Streaming responses are auto-traced like regular completions.

1stream = client.chat.completions.create(
2 model="gpt-4.1-nano",
3 messages=[{"role": "user", "content": "Write a haiku about Python."}],
4 stream=True,
5)
6
7for chunk in stream:
8 content = chunk.choices[0].delta.content
9 if content:
10 print(content, end="", flush=True)

Tool calls

Function calling is auto-traced. Wrap the workflow with @workflow and @task decorators for a structured trace tree.

1import json
2from openai import OpenAI
3from respan import Respan, workflow, task
4from respan_instrumentation_openai import OpenAIInstrumentor
5
6respan = Respan(instrumentations=[OpenAIInstrumentor()])
7client = OpenAI()
8
9tools = [
10 {
11 "type": "function",
12 "function": {
13 "name": "get_weather",
14 "description": "Get the weather for a city.",
15 "parameters": {
16 "type": "object",
17 "properties": {"city": {"type": "string"}},
18 "required": ["city"],
19 },
20 },
21 }
22]
23
24@task(name="get_weather")
25def get_weather(city: str) -> str:
26 return f"Sunny, 72F in {city}"
27
28@workflow(name="weather_assistant")
29def run(question: str):
30 messages = [{"role": "user", "content": question}]
31
32 response = client.chat.completions.create(
33 model="gpt-4.1-nano",
34 messages=messages,
35 tools=tools,
36 )
37 message = response.choices[0].message
38
39 if message.tool_calls:
40 messages.append(message)
41 for tc in message.tool_calls:
42 args = json.loads(tc.function.arguments)
43 result = get_weather(**args)
44 messages.append(
45 {"role": "tool", "tool_call_id": tc.id, "content": result}
46 )
47
48 final = client.chat.completions.create(
49 model="gpt-4.1-nano",
50 messages=messages,
51 tools=tools,
52 )
53 print(f"Answer: {final.choices[0].message.content}")
54
55run("What's the weather in Paris?")
56respan.flush()

Structured output

JSON mode with Pydantic models is auto-traced.

1from pydantic import BaseModel
2from openai import OpenAI
3
4client = OpenAI()
5
6class MovieReview(BaseModel):
7 title: str
8 rating: int
9 summary: str
10 pros: list[str]
11 cons: list[str]
12
13response = client.beta.chat.completions.parse(
14 model="gpt-4.1-nano",
15 messages=[
16 {"role": "system", "content": "You are a film critic. Rate movies 1-10."},
17 {"role": "user", "content": "Review: The Matrix"},
18 ],
19 response_format=MovieReview,
20)
21result = response.choices[0].message.parsed
22print(f"{result.title} - {result.rating}/10")