@respan/cli 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/setup/doctor.d.ts +0 -1
- package/dist/commands/setup/doctor.js +25 -40
- package/dist/commands/setup/gateway.d.ts +16 -0
- package/dist/commands/setup/gateway.js +33 -0
- package/dist/commands/setup/index.d.ts +4 -33
- package/dist/commands/setup/index.js +11 -762
- package/dist/commands/setup/tracing.d.ts +16 -0
- package/dist/commands/setup/tracing.js +33 -0
- package/dist/lib/agents.d.ts +16 -0
- package/dist/lib/agents.js +75 -0
- package/dist/lib/auth.js +24 -0
- package/dist/lib/colors.d.ts +7 -0
- package/dist/lib/colors.js +10 -0
- package/dist/lib/integrate.d.ts +6 -0
- package/dist/lib/integrate.js +11 -0
- package/dist/lib/setup-base-command.d.ts +84 -0
- package/dist/lib/setup-base-command.js +649 -0
- package/dist/lib/skill-content.d.ts +1 -0
- package/dist/lib/skill-content.js +16 -0
- package/dist/lib/skill-refs.generated.d.ts +3 -2
- package/dist/lib/skill-refs.generated.js +423 -102
- package/oclif.manifest.json +238 -75
- package/package.json +2 -1
|
@@ -1,19 +1,269 @@
|
|
|
1
1
|
// AUTO-GENERATED by scripts/embed-skill-refs.mjs
|
|
2
|
-
// Source: skills/references/{tracing,prompts,evals,monitors}.md
|
|
2
|
+
// Source: skills/SKILL.md and skills/references/{tracing,gateway,prompts,evals,monitors}.md
|
|
3
3
|
// Do not edit directly — edit the markdown sources and rebuild.
|
|
4
|
-
export const
|
|
4
|
+
export const SKILL_MD = `# Respan
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Use the Respan CLI and SDK for LLM observability — tracing, evals, prompts, datasets, and gateway routing.
|
|
7
|
+
|
|
8
|
+
## When To Use
|
|
9
|
+
|
|
10
|
+
- **Set up tracing** (instrument your app to capture LLM calls — install + decorators, propagation, processors) → read [references/tracing.md](references/tracing.md)
|
|
11
|
+
- **Set up gateway** (route LLM calls through the Respan proxy — wiring + model switching, fallbacks, caching) → read [references/gateway.md](references/gateway.md)
|
|
12
|
+
- **Prompt management** (create, version, deploy) → read [references/prompts.md](references/prompts.md)
|
|
13
|
+
- **Evals** (datasets, evaluators, experiments) → read [references/evals.md](references/evals.md)
|
|
14
|
+
- **Monitors & automation** (alerts, online evals, webhooks) → read [references/monitors.md](references/monitors.md)
|
|
15
|
+
|
|
16
|
+
Tracing and gateway are separate setups — configure one at a time, never both in the same pass.
|
|
17
|
+
|
|
18
|
+
## Core Principles
|
|
19
|
+
|
|
20
|
+
1. **Read the reference first.** Each reference file has the exact setup steps, API patterns, MCP tools, and CLI commands.
|
|
21
|
+
2. **Use MCP tools** for platform operations (prompts, datasets, evaluators, experiments, traces, logs).
|
|
22
|
+
3. **Use CLI** when MCP is not available: \`respan traces list\`, \`respan prompts list\`, etc.
|
|
23
|
+
4. **Fetch docs** for integration-specific details not covered in references.
|
|
24
|
+
|
|
25
|
+
## Quick Reference
|
|
26
|
+
|
|
27
|
+
| Task | Reference / Command |
|
|
28
|
+
|------|--------------------|
|
|
29
|
+
| Set up tracing (steps + decorators, propagation) | [references/tracing.md](references/tracing.md) |
|
|
30
|
+
| Set up gateway (steps + features) | [references/gateway.md](references/gateway.md) |
|
|
31
|
+
| Prompt management | [references/prompts.md](references/prompts.md) |
|
|
32
|
+
| Evals & experiments | [references/evals.md](references/evals.md) |
|
|
33
|
+
| Monitors & automation | [references/monitors.md](references/monitors.md) |
|
|
34
|
+
| List traces | \`respan traces list --limit 10\` |
|
|
35
|
+
| View a trace | \`respan traces get <id>\` |
|
|
36
|
+
| Check auth | \`respan auth status\` |
|
|
37
|
+
|
|
38
|
+
## Documentation Access
|
|
39
|
+
|
|
40
|
+
Any doc page can be fetched as markdown:
|
|
41
|
+
\`https://respan.ai/docs/integrations/openai-sdk.md\`
|
|
42
|
+
\`https://respan.ai/docs/sdks/typescript-sdk/overview.md\`
|
|
43
|
+
|
|
44
|
+
Full docs index: \`https://www.respan.ai/docs/llms.txt\`
|
|
45
|
+
|
|
46
|
+
Platform: \`https://platform.respan.ai\`
|
|
47
|
+
`;
|
|
48
|
+
export const TRACING_MD = `# Tracing
|
|
49
|
+
|
|
50
|
+
Set up and configure Respan SDK tracing: instrument an app to capture LLM calls as
|
|
51
|
+
structured traces, then refine with decorators, context propagation, and processors.
|
|
52
|
+
|
|
53
|
+
This file covers **both** the initial setup steps and the advanced reference. Tracing
|
|
54
|
+
is a separate setup from the gateway — do one at a time, never both in the same pass.
|
|
7
55
|
|
|
8
56
|
Docs: \`https://respan.ai/docs/documentation/features/tracing/traces/tracing-sdk.md\`
|
|
57
|
+
Full docs index: \`https://www.respan.ai/docs/llms.txt\`
|
|
9
58
|
|
|
10
59
|
---
|
|
11
60
|
|
|
12
|
-
##
|
|
61
|
+
## Setup
|
|
62
|
+
|
|
63
|
+
Use this section when the user asks to set up Respan tracing in their project.
|
|
13
64
|
|
|
14
|
-
|
|
65
|
+
### Hard Rules
|
|
66
|
+
|
|
67
|
+
- **Interactive mode:** Ask the user questions when you need input. Do not assume.
|
|
68
|
+
- **Only add Respan code.** Do not refactor or modify unrelated code.
|
|
69
|
+
- **Pin exact versions.** Never use \`latest\` or unpinned ranges.
|
|
70
|
+
- **Do not guess APIs.** Use only the patterns from the integration docs linked below.
|
|
71
|
+
- **If Respan is already installed/configured, do not duplicate work.** Check for existing \`respan\` imports first.
|
|
72
|
+
- **Read the code before proposing changes.** Understand the actual workflow, not just the dependencies.
|
|
73
|
+
|
|
74
|
+
The API key is stored in \`.env\` as \`RESPAN_API_KEY\`.
|
|
75
|
+
|
|
76
|
+
### 1. Analyze the Project
|
|
77
|
+
|
|
78
|
+
**1a. Detect language and package manager:**
|
|
79
|
+
- Check \`package.json\` (JS/TS) or \`pyproject.toml\` / \`requirements.txt\` (Python)
|
|
80
|
+
- Detect package manager from lock files
|
|
81
|
+
|
|
82
|
+
**1b. Detect libraries in priority order:**
|
|
83
|
+
|
|
84
|
+
Check higher-priority categories first. If a match is found, use that instrumentation — do NOT also add lower-level SDK instrumentation.
|
|
85
|
+
|
|
86
|
+
**Priority 1 — Agent Frameworks & High-Level SDKs:**
|
|
87
|
+
|
|
88
|
+
| Library | Python package | JS/TS package | Respan instrumentation (Python) | Respan instrumentation (JS/TS) | Docs |
|
|
89
|
+
|---------|---------------|---------------|--------------------------------|-------------------------------|------|
|
|
90
|
+
| Vercel AI SDK | — | \`ai\` | — | \`@respan/instrumentation-vercel\` | [docs](https://respan.ai/docs/integrations/vercel-ai-sdk.md) |
|
|
91
|
+
| OpenAI Agents SDK | \`openai-agents\` | \`@openai/agents\` | \`respan-instrumentation-openai-agents\` | \`@respan/instrumentation-openai-agents\` | [docs](https://respan.ai/docs/integrations/openai-agents-sdk.md) |
|
|
92
|
+
| Claude Agent SDK | \`claude-agent-sdk\` | — | \`respan-instrumentation-claude-agent-sdk\` | — | [docs](https://respan.ai/docs/integrations/claude-agents-sdk.md) |
|
|
93
|
+
| Pydantic AI | \`pydantic-ai\` | — | \`respan-instrumentation-pydantic-ai\` | — | [docs](https://respan.ai/docs/integrations/pydantic-ai.md) |
|
|
94
|
+
| LangChain | \`langchain\` | \`langchain\` | via OpenInference | — | [docs](https://respan.ai/docs/integrations/langchain.md) |
|
|
95
|
+
| LangGraph | \`langgraph\` | — | via OpenInference | — | [docs](https://respan.ai/docs/integrations/langgraph.md) |
|
|
96
|
+
| CrewAI | \`crewai\` | — | \`respan-instrumentation-crewai\` | — | [docs](https://respan.ai/docs/integrations/crewai.md) |
|
|
97
|
+
| LlamaIndex | \`llama-index\` | — | via OpenInference | — | [docs](https://respan.ai/docs/integrations/llama-index.md) |
|
|
98
|
+
| Haystack | \`haystack-ai\` | — | \`respan-instrumentation-haystack\` | — | [docs](https://respan.ai/docs/integrations/haystack.md) |
|
|
99
|
+
| Mastra | — | \`mastra\` | — | via OTEL | [docs](https://respan.ai/docs/integrations/mastra.md) |
|
|
100
|
+
| Google ADK | \`google-adk\` | — | via OpenInference | — | [docs](https://respan.ai/docs/integrations/google-adk.md) |
|
|
101
|
+
|
|
102
|
+
If a Priority 1 framework is found, use its instrumentation. Do NOT also add Priority 2 instrumentation for the same provider.
|
|
103
|
+
|
|
104
|
+
**Priority 2 — Direct LLM SDKs** (only if no P1 framework covers this provider):
|
|
105
|
+
|
|
106
|
+
These are **auto-instrumented** — just \`Respan()\` / \`new Respan()\`, no extra packages needed:
|
|
107
|
+
|
|
108
|
+
| Library | Python package | JS/TS package | Docs |
|
|
109
|
+
|---------|---------------|---------------|------|
|
|
110
|
+
| OpenAI SDK | \`openai\` | \`openai\` | [docs](https://respan.ai/docs/integrations/openai-sdk.md) |
|
|
111
|
+
| Anthropic SDK | \`anthropic\` | \`@anthropic-ai/sdk\` | [docs](https://respan.ai/docs/integrations/anthropic.md) |
|
|
112
|
+
| Azure OpenAI | \`openai\` (azure config) | \`openai\` | [docs](https://respan.ai/docs/integrations/providers/azure.md) |
|
|
113
|
+
| Google Vertex AI | \`google-cloud-aiplatform\` | — | [docs](https://respan.ai/docs/integrations/vertex-ai.md) |
|
|
114
|
+
| AWS Bedrock | \`boto3\` | — | [docs](https://respan.ai/docs/integrations/aws-bedrock.md) |
|
|
115
|
+
| Cohere | \`cohere\` | — | [docs](https://respan.ai/docs/integrations/providers/cohere.md) |
|
|
116
|
+
| Together AI | \`together\` | — | [docs](https://respan.ai/docs/integrations/together-ai.md) |
|
|
117
|
+
|
|
118
|
+
**Note:** LiteLLM in JS uses the OpenAI-compatible API, so the OpenAI auto-instrument covers it. For Python LiteLLM, see [LiteLLM guide](https://respan.ai/docs/integrations/litellm.md). For Google GenAI (\`@google/genai\`), see [Google GenAI guide](https://respan.ai/docs/integrations/google-genai.md).
|
|
119
|
+
|
|
120
|
+
**1c. Read the actual code and understand the workflow:**
|
|
121
|
+
|
|
122
|
+
This is the most important step. Read the entrypoint and all files that make LLM calls. Map out:
|
|
123
|
+
|
|
124
|
+
- What is the **overall workflow**? (e.g. "user sends question → retrieve context → generate answer → format response")
|
|
125
|
+
- What are the **individual steps/tasks**? (e.g. "embed query", "search DB", "call GPT", "parse output")
|
|
126
|
+
- Are there **agent loops**? (e.g. a loop that calls tools until done)
|
|
127
|
+
- Are there **tool calls**? (e.g. functions the LLM invokes)
|
|
128
|
+
|
|
129
|
+
### 2. Propose an Implementation Plan
|
|
130
|
+
|
|
131
|
+
Present the user with a concrete plan before making any changes. The plan should include:
|
|
132
|
+
|
|
133
|
+
**a) Packages to install** — core SDK + instrumentation package (with exact versions)
|
|
134
|
+
|
|
135
|
+
**b) Initialization code** — where to add it (which file, which line)
|
|
136
|
+
|
|
137
|
+
**c) Workflow structure** — how to wrap the existing code:
|
|
138
|
+
|
|
139
|
+
For **agent frameworks** (Priority 1): The framework instrumentation auto-captures the workflow structure. Usually just need init code, no manual wrapping needed. Fetch and follow the integration doc.
|
|
140
|
+
|
|
141
|
+
For **direct LLM SDKs** (Priority 2): Individual LLM calls will be auto-traced as flat spans. Propose wrapping the logical workflow with Respan decorators/wrappers to get structured nested traces:
|
|
142
|
+
|
|
143
|
+
TypeScript example:
|
|
144
|
+
\`\`\`typescript
|
|
145
|
+
// Before: flat traces — each LLM call is an isolated span
|
|
146
|
+
const outline = await openai.chat.completions.create({...});
|
|
147
|
+
const draft = await openai.chat.completions.create({...});
|
|
148
|
+
|
|
149
|
+
// After: structured traces — nested spans showing the workflow
|
|
150
|
+
const result = await withWorkflow({ name: "write_article" }, async () => {
|
|
151
|
+
const outline = await withTask({ name: "generate_outline" }, async () => {
|
|
152
|
+
return await openai.chat.completions.create({...});
|
|
153
|
+
});
|
|
154
|
+
const draft = await withTask({ name: "write_draft" }, async () => {
|
|
155
|
+
return await openai.chat.completions.create({...});
|
|
156
|
+
});
|
|
157
|
+
return draft;
|
|
158
|
+
});
|
|
159
|
+
\`\`\`
|
|
160
|
+
|
|
161
|
+
Python example:
|
|
162
|
+
\`\`\`python
|
|
163
|
+
# Before: flat traces
|
|
164
|
+
outline = client.chat.completions.create(...)
|
|
165
|
+
draft = client.chat.completions.create(...)
|
|
166
|
+
|
|
167
|
+
# After: structured traces
|
|
168
|
+
@workflow(name="write_article")
|
|
169
|
+
def write_article(topic):
|
|
170
|
+
outline = generate_outline(topic)
|
|
171
|
+
return write_draft(outline)
|
|
172
|
+
|
|
173
|
+
@task(name="generate_outline")
|
|
174
|
+
def generate_outline(topic):
|
|
175
|
+
return client.chat.completions.create(...)
|
|
176
|
+
|
|
177
|
+
@task(name="write_draft")
|
|
178
|
+
def write_draft(outline):
|
|
179
|
+
return client.chat.completions.create(...)
|
|
180
|
+
\`\`\`
|
|
181
|
+
|
|
182
|
+
**Ask the user which approach they prefer:**
|
|
183
|
+
1. **Auto-trace only** — just add init code, every LLM call is automatically captured as a flat span. Zero code changes beyond initialization. Good for quick setup or simple projects.
|
|
184
|
+
2. **Structured traces** — wrap existing code with workflow/task decorators for nested spans showing how the app flows. Better for complex projects with multiple LLM calls.
|
|
185
|
+
|
|
186
|
+
If the user picks option 1, skip the wrappers entirely — just install + init code.
|
|
187
|
+
|
|
188
|
+
If the user picks option 2:
|
|
189
|
+
- **If multiple independent workflows are detected** (e.g. \`writeArticle()\`, \`summarizeDoc()\`, \`classifyEmail()\`), list them and ask which ones to instrument. Don't assume all of them.
|
|
190
|
+
- **Show the user what the trace will look like** — describe the span hierarchy:
|
|
191
|
+
\`\`\`
|
|
192
|
+
workflow: write_article
|
|
193
|
+
├── task: generate_outline
|
|
194
|
+
│ └── llm: openai.chat (auto-captured)
|
|
195
|
+
└── task: write_draft
|
|
196
|
+
└── llm: openai.chat (auto-captured)
|
|
197
|
+
\`\`\`
|
|
198
|
+
|
|
199
|
+
Wait for user confirmation before proceeding.
|
|
200
|
+
|
|
201
|
+
### 3. Implement
|
|
202
|
+
|
|
203
|
+
**a) Install packages:**
|
|
204
|
+
|
|
205
|
+
For direct LLM SDKs (Priority 2) — just the core SDK:
|
|
206
|
+
\`\`\`bash
|
|
207
|
+
# Python
|
|
208
|
+
pip install respan-ai
|
|
209
|
+
|
|
210
|
+
# TypeScript
|
|
211
|
+
npm install @respan/respan
|
|
212
|
+
\`\`\`
|
|
213
|
+
|
|
214
|
+
For agent frameworks (Priority 1) — also install the instrumentor. Check the docs link in the table above for the exact packages.
|
|
215
|
+
|
|
216
|
+
**b) Add initialization code** — at the top of the entrypoint, before any LLM client is created:
|
|
217
|
+
|
|
218
|
+
For **direct LLM SDKs** (auto-instrumented):
|
|
219
|
+
\`\`\`python
|
|
220
|
+
# Python
|
|
221
|
+
from respan import Respan
|
|
222
|
+
Respan()
|
|
223
|
+
\`\`\`
|
|
224
|
+
\`\`\`typescript
|
|
225
|
+
// TypeScript
|
|
226
|
+
import { Respan } from "@respan/respan";
|
|
227
|
+
const respan = new Respan();
|
|
228
|
+
await respan.initialize();
|
|
229
|
+
\`\`\`
|
|
230
|
+
|
|
231
|
+
For **agent frameworks** (explicit instrumentor — fetch the docs URL from the table for the exact pattern):
|
|
232
|
+
\`\`\`python
|
|
233
|
+
# Python example (OpenAI Agents)
|
|
234
|
+
from respan import Respan
|
|
235
|
+
from respan_instrumentation_openai_agents import OpenAIAgentsInstrumentor
|
|
236
|
+
Respan(instrumentations=[OpenAIAgentsInstrumentor()])
|
|
237
|
+
\`\`\`
|
|
238
|
+
\`\`\`typescript
|
|
239
|
+
// TypeScript example (OpenAI Agents)
|
|
240
|
+
import { Respan } from "@respan/respan";
|
|
241
|
+
import { OpenAIAgentsInstrumentor } from "@respan/instrumentation-openai-agents";
|
|
242
|
+
const respan = new Respan({ instrumentations: [new OpenAIAgentsInstrumentor()] });
|
|
243
|
+
await respan.initialize();
|
|
244
|
+
\`\`\`
|
|
245
|
+
|
|
246
|
+
**c) Add workflow wrappers** — if the user chose structured traces in the plan.
|
|
247
|
+
|
|
248
|
+
### 4. Verify (final test — always run this)
|
|
249
|
+
|
|
250
|
+
As the final step, **run the user's program once with a small request** and confirm tracing works end to end:
|
|
15
251
|
|
|
16
|
-
|
|
252
|
+
- The app runs without errors
|
|
253
|
+
- A trace appears at https://platform.respan.ai or via \`respan traces list --limit 5\`
|
|
254
|
+
- If wrappers were added, the trace shows the expected nested span hierarchy
|
|
255
|
+
|
|
256
|
+
If no trace appears, the instrumentation isn't taking effect — debug (init placement, missing \`flush()\`, wrong entrypoint) and re-run before declaring setup done.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Reference
|
|
261
|
+
|
|
262
|
+
Advanced tracing configuration: decorators, context propagation, processors, and span attributes.
|
|
263
|
+
|
|
264
|
+
### Decorators
|
|
265
|
+
|
|
266
|
+
Wrap functions to create structured span hierarchies. All decorators share the same signature.
|
|
17
267
|
|
|
18
268
|
| Decorator | Purpose |
|
|
19
269
|
|-----------|---------|
|
|
@@ -22,7 +272,7 @@ Wrap functions to create structured span hierarchies. All decorators share the s
|
|
|
22
272
|
| \`@agent\` / \`withAgent\` | Agent loop span |
|
|
23
273
|
| \`@tool\` / \`withTool\` | Tool/function call span |
|
|
24
274
|
|
|
25
|
-
|
|
275
|
+
#### Python
|
|
26
276
|
|
|
27
277
|
\`\`\`python
|
|
28
278
|
from respan import Respan, workflow, task, agent, tool
|
|
@@ -43,7 +293,7 @@ def write_draft(outline: str):
|
|
|
43
293
|
return client.chat.completions.create(...)
|
|
44
294
|
\`\`\`
|
|
45
295
|
|
|
46
|
-
|
|
296
|
+
#### TypeScript
|
|
47
297
|
|
|
48
298
|
\`\`\`typescript
|
|
49
299
|
import { Respan, withWorkflow, withTask } from "@respan/respan";
|
|
@@ -61,7 +311,7 @@ const result = await withWorkflow({ name: "write_article" }, async () => {
|
|
|
61
311
|
});
|
|
62
312
|
\`\`\`
|
|
63
313
|
|
|
64
|
-
|
|
314
|
+
#### Decorator Parameters
|
|
65
315
|
|
|
66
316
|
\`\`\`python
|
|
67
317
|
@workflow(
|
|
@@ -77,17 +327,15 @@ const result = await withWorkflow({ name: "write_article" }, async () => {
|
|
|
77
327
|
|
|
78
328
|
All parameters are optional. Without any, the function name is used as the span name.
|
|
79
329
|
|
|
80
|
-
|
|
330
|
+
#### Async Support
|
|
81
331
|
|
|
82
332
|
Decorators work with \`async def\`, generators, and async generators automatically.
|
|
83
333
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
## Context Propagation
|
|
334
|
+
### Context Propagation
|
|
87
335
|
|
|
88
336
|
Attach attributes to **all spans** within a scope, including auto-instrumented LLM calls.
|
|
89
337
|
|
|
90
|
-
|
|
338
|
+
#### propagate_attributes
|
|
91
339
|
|
|
92
340
|
\`\`\`python
|
|
93
341
|
from respan import Respan, propagate_attributes
|
|
@@ -104,7 +352,7 @@ with propagate_attributes(
|
|
|
104
352
|
result = run_pipeline()
|
|
105
353
|
\`\`\`
|
|
106
354
|
|
|
107
|
-
|
|
355
|
+
##### Available attributes
|
|
108
356
|
|
|
109
357
|
| Attribute | Description |
|
|
110
358
|
|-----------|-------------|
|
|
@@ -118,7 +366,7 @@ with propagate_attributes(
|
|
|
118
366
|
| \`metadata\` | Dict of custom key-value pairs (merged in nested contexts) |
|
|
119
367
|
| \`prompt\` | Dict with \`prompt_id\` and \`variables\` for prompt logging |
|
|
120
368
|
|
|
121
|
-
|
|
369
|
+
##### TypeScript
|
|
122
370
|
|
|
123
371
|
\`\`\`typescript
|
|
124
372
|
const result = await respan.propagateAttributes(
|
|
@@ -133,14 +381,14 @@ const result = await respan.propagateAttributes(
|
|
|
133
381
|
);
|
|
134
382
|
\`\`\`
|
|
135
383
|
|
|
136
|
-
|
|
384
|
+
##### Nesting behavior
|
|
137
385
|
|
|
138
386
|
- Nested \`propagate_attributes\` calls merge with the outer context
|
|
139
387
|
- \`metadata\` dicts are merged (not replaced)
|
|
140
388
|
- For duplicate keys, inner values override outer
|
|
141
389
|
- Async-safe via \`contextvars\`
|
|
142
390
|
|
|
143
|
-
|
|
391
|
+
#### respan_span_attributes
|
|
144
392
|
|
|
145
393
|
Attaches attributes to the **current active span only** (not auto-instrumented child spans):
|
|
146
394
|
|
|
@@ -156,9 +404,7 @@ with respan_span_attributes({
|
|
|
156
404
|
|
|
157
405
|
Use \`propagate_attributes\` when you need attributes on all nested spans (most common). Use \`respan_span_attributes\` when you only want to tag the current span.
|
|
158
406
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
## Imperative Span Creation
|
|
407
|
+
### Imperative Span Creation
|
|
162
408
|
|
|
163
409
|
For runtime-determined span names, use the client API instead of decorators:
|
|
164
410
|
|
|
@@ -172,9 +418,7 @@ with client.start_span(name="dynamic_step", kind="task") as span:
|
|
|
172
418
|
# span is automatically closed and exported
|
|
173
419
|
\`\`\`
|
|
174
420
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
## Updating the Current Span
|
|
421
|
+
### Updating the Current Span
|
|
178
422
|
|
|
179
423
|
Add attributes or change status on the active span at runtime:
|
|
180
424
|
|
|
@@ -202,9 +446,7 @@ except Exception as e:
|
|
|
202
446
|
client.record_exception(e)
|
|
203
447
|
\`\`\`
|
|
204
448
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
## Custom Processors
|
|
449
|
+
### Custom Processors
|
|
208
450
|
|
|
209
451
|
Route spans to multiple destinations with filtering:
|
|
210
452
|
|
|
@@ -231,9 +473,7 @@ def sensitive_step():
|
|
|
231
473
|
...
|
|
232
474
|
\`\`\`
|
|
233
475
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
## Flush
|
|
476
|
+
### Flush
|
|
237
477
|
|
|
238
478
|
Always call \`flush()\` before process exit to ensure all spans are exported:
|
|
239
479
|
|
|
@@ -245,9 +485,7 @@ respan.flush()
|
|
|
245
485
|
|
|
246
486
|
In serverless/Lambda: call \`flush()\` at the end of every handler invocation.
|
|
247
487
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
## Trace Hierarchy Example
|
|
488
|
+
### Trace Hierarchy Example
|
|
251
489
|
|
|
252
490
|
\`\`\`
|
|
253
491
|
workflow: handle_request
|
|
@@ -263,19 +501,152 @@ workflow: handle_request
|
|
|
263
501
|
|
|
264
502
|
LLM calls within decorated functions are automatically nested as child spans.
|
|
265
503
|
`;
|
|
266
|
-
export const GATEWAY_MD = `# Gateway
|
|
504
|
+
export const GATEWAY_MD = `# Gateway
|
|
505
|
+
|
|
506
|
+
Set up and use the Respan **gateway** — routing an app's LLM calls through the Respan
|
|
507
|
+
proxy for logging, caching, key management, fallbacks, and model switching.
|
|
267
508
|
|
|
268
|
-
|
|
509
|
+
This file covers **both** the setup steps and the feature reference. Gateway is a
|
|
510
|
+
separate setup from tracing — do one at a time, never both in the same pass. Gateway
|
|
511
|
+
setup does **not** install instrumentation packages; it repoints the LLM client's base
|
|
512
|
+
URL at the Respan proxy and applies the framework's specific wiring.
|
|
269
513
|
|
|
270
514
|
Docs: \`https://respan.ai/docs/documentation/features/gateway/gateway-quickstart.md\`
|
|
515
|
+
Full docs index: \`https://www.respan.ai/docs/llms.txt\`
|
|
271
516
|
|
|
272
517
|
---
|
|
273
518
|
|
|
274
519
|
## Setup
|
|
275
520
|
|
|
521
|
+
Use this section when the user asks to set up the Respan gateway.
|
|
522
|
+
|
|
523
|
+
### Hard Rules
|
|
524
|
+
|
|
525
|
+
- **Interactive mode:** Ask the user questions when you need input. Do not assume.
|
|
526
|
+
- **Only add Respan wiring.** Do not refactor or modify unrelated code.
|
|
527
|
+
- **The gateway serves only the completion / text-generation operation**, exposed per provider:
|
|
528
|
+
- OpenAI-compatible → \`https://api.respan.ai/api/chat/completions\`
|
|
529
|
+
- Anthropic Messages → \`https://api.respan.ai/api/anthropic/\`
|
|
530
|
+
- Google Gemini → \`https://api.respan.ai/api/google/gemini/...\`
|
|
531
|
+
|
|
532
|
+
**Use the exact base path from the per-SDK gateway doc you fetch in Step 4** — it is authoritative. Do **NOT** repoint clients used for any other operation — embeddings, moderation, images, audio/speech, assistants, batch, fine-tuning — they are not supported and will fail (e.g. 404). Leave those untouched.
|
|
533
|
+
- **Use chat completions, not the Responses API.** The gateway serves chat completions (\`/api/chat/completions\`), not the OpenAI Responses API (\`/api/responses\`). SDKs that *default* to the Responses API are still fully supported — you just switch them to chat-completions mode, per their per-SDK doc:
|
|
534
|
+
- **OpenAI Agents SDK** — Python: \`set_default_openai_client(AsyncOpenAI(base_url=..., api_key=os.environ["RESPAN_API_KEY"]))\` + \`set_default_openai_api("chat_completions")\` (TS: \`setDefaultOpenAIClient(...)\` + \`setOpenAIAPI("chat_completions")\`).
|
|
535
|
+
- **Vercel AI SDK / \`@ai-sdk/openai\`** — use \`provider.chat(model)\`, not the default \`provider(model)\` (which targets the Responses API).
|
|
536
|
+
- **Scope the wiring — do not blanket-rewrite.** Wire only the client(s) that make the completion call you are setting up. Do **NOT** repoint every client instance in the repo (especially in example/monorepo projects with many independent scripts).
|
|
537
|
+
- **Do NOT install instrumentation packages.** Gateway routing does not use them. (That is tracing setup — see \`tracing.md\`.)
|
|
538
|
+
- **Do not guess APIs or doc slugs.** Use only the patterns from the live integration doc you fetch, and the exact slug from the map below.
|
|
539
|
+
- **Pin exact versions** if you install a framework SDK that is genuinely missing.
|
|
540
|
+
- **If the gateway is already wired up, do not duplicate work.** Check for an existing \`base_url\`/\`baseURL\` pointing at \`api.respan.ai\` first.
|
|
541
|
+
- **Read the code before proposing changes.** Find where the client is actually instantiated.
|
|
542
|
+
|
|
543
|
+
The API key is stored in \`.env\` as \`RESPAN_API_KEY\`. Gateway base URL: \`https://api.respan.ai/api\` (the proxy completions path is \`https://api.respan.ai/api/chat/completions\`).
|
|
544
|
+
|
|
545
|
+
### 1. Detect
|
|
546
|
+
|
|
547
|
+
Identify:
|
|
548
|
+
- **Language & package manager** — \`package.json\` (JS/TS), \`pyproject.toml\` / \`requirements.txt\` (Python), \`Gemfile\` (Ruby). Detect the package manager from lock files.
|
|
549
|
+
- **LLM library / framework in use** — match the project's dependencies against the **Detection → slug map** below.
|
|
550
|
+
|
|
551
|
+
### 2. Map to slug
|
|
552
|
+
|
|
553
|
+
Match the detected package(s) against the map. **Use the slug from the map verbatim — never auto-derive a slug from a display name** (the kebab-casing is irregular).
|
|
554
|
+
|
|
555
|
+
Apply the **priority rule:** a high-level framework wins over the raw SDK beneath it.
|
|
556
|
+
For example, a project with both \`crewai\` and \`openai\` maps to \`crew-ai\` (not \`open-ai-sdk\`),
|
|
557
|
+
because their gateway wiring differs. **If two frameworks match, ask the user which to configure.**
|
|
558
|
+
|
|
559
|
+
#### Detection → slug map
|
|
560
|
+
|
|
561
|
+
URL pattern: \`https://respan.ai/docs/integrations/gateway/<slug>.md\`
|
|
562
|
+
|
|
563
|
+
| Detected package(s) | Slug |
|
|
564
|
+
|---|---|
|
|
565
|
+
| \`@openai/agents\` / \`openai-agents\` | \`open-ai-agents\` |
|
|
566
|
+
| \`claude-agent-sdk\` | \`claude-agent-sdk\` |
|
|
567
|
+
| \`ai\` (Vercel AI SDK) | \`vercel-ai-sdk\` |
|
|
568
|
+
| \`pydantic-ai\` | \`pydantic-ai\` |
|
|
569
|
+
| \`crewai\` | \`crew-ai\` |
|
|
570
|
+
| \`haystack-ai\` | \`haystack\` |
|
|
571
|
+
| \`langchain\` | \`lang-chain\` |
|
|
572
|
+
| \`llama-index\` | \`llama-index\` |
|
|
573
|
+
| \`autogen\` / \`autogen-agentchat\` | \`auto-gen\` |
|
|
574
|
+
| \`dspy\` / \`dspy-ai\` | \`ds-py\` |
|
|
575
|
+
| \`google-adk\` | \`google-adk\` |
|
|
576
|
+
| \`openai\` | \`open-ai-sdk\` |
|
|
577
|
+
| \`anthropic\` / \`@anthropic-ai/sdk\` | \`anthropic-sdk\` |
|
|
578
|
+
| \`google-genai\` / \`@google/genai\` | \`google-gen-ai\` |
|
|
579
|
+
| \`litellm\` | \`lite-llm\` |
|
|
580
|
+
| \`ruby_llm\` (gem) | \`ruby-llm\` |
|
|
581
|
+
| \`google-cloud-aiplatform\` | \`vertex-ai\` |
|
|
582
|
+
|
|
583
|
+
> Namespace note: OpenAI, Anthropic, and Vertex each have both an SDK-level gateway page (\`open-ai-sdk\`, \`anthropic-sdk\`, \`vertex-ai\`) and a \`model-providers/*\` page. The SDK-level slugs above are the correct targets for this map.
|
|
584
|
+
|
|
585
|
+
### 3. Confirm
|
|
586
|
+
|
|
587
|
+
Show the user what was detected and which doc will be used. Wait for confirmation.
|
|
588
|
+
|
|
589
|
+
> Detected:
|
|
590
|
+
> - Language: [TypeScript/Python/Ruby]
|
|
591
|
+
> - Framework / SDK: [e.g. OpenAI Agents]
|
|
592
|
+
> - Gateway doc: https://respan.ai/docs/integrations/gateway/open-ai-agents.md
|
|
593
|
+
>
|
|
594
|
+
> Set up the gateway for this? (yes/no)
|
|
595
|
+
|
|
596
|
+
### 4. Fetch the live doc
|
|
597
|
+
|
|
598
|
+
Fetch \`https://respan.ai/docs/integrations/gateway/<slug>.md\` for the chosen slug.
|
|
599
|
+
Use the slug from the map verbatim.
|
|
600
|
+
|
|
601
|
+
If a pinned URL fails to resolve, that signals the **map is stale** and the table should be
|
|
602
|
+
updated — it does **not** mean you should guess an alternative slug.
|
|
603
|
+
|
|
604
|
+
### 5. Read the project's client code
|
|
605
|
+
|
|
606
|
+
Find where the LLM client / \`base_url\` is instantiated, and identify **which client(s) make
|
|
607
|
+
completion / text-generation calls** (chat completions, Anthropic \`messages.create\`, Gemini
|
|
608
|
+
\`generate_content\`) — that is the only path you repoint. This is the step that determines the
|
|
609
|
+
correct wiring — do not skip it.
|
|
610
|
+
|
|
611
|
+
If the project has multiple clients or many scripts (e.g. an examples repo), repoint **only**
|
|
612
|
+
the completion ones. Leave clients that call embeddings, moderation, images, audio,
|
|
613
|
+
assistants, batch, or fine-tuning exactly as they are — the gateway does not serve them.
|
|
614
|
+
|
|
615
|
+
### 6. Apply the framework-specific wiring
|
|
616
|
+
|
|
617
|
+
Apply the exact pattern from the fetched doc:
|
|
618
|
+
|
|
619
|
+
- Ensure \`RESPAN_API_KEY\` is set (it is in \`.env\`).
|
|
620
|
+
- Repoint \`base_url\` / \`baseURL\` to the gateway path from the fetched doc (e.g. \`https://api.respan.ai/api\` for OpenAI-compatible, \`…/api/anthropic/\` for Anthropic) — **only on the completion client(s)** identified in step 5, not on every client in the project.
|
|
621
|
+
- Apply the framework's exact wiring — e.g. OpenAI Agents requires \`set_default_openai_client(AsyncOpenAI(base_url=...))\`, **not** env vars.
|
|
622
|
+
- Install the framework SDK only if it is genuinely missing.
|
|
623
|
+
- **Do NOT install instrumentation packages.**
|
|
624
|
+
|
|
625
|
+
### 7. Verify (final test — always run this)
|
|
626
|
+
|
|
627
|
+
As the final step, **run the user's program once with a small request** through the
|
|
628
|
+
configured gateway and confirm it works:
|
|
629
|
+
|
|
630
|
+
\`\`\`bash
|
|
631
|
+
respan logs list --limit 5
|
|
632
|
+
\`\`\`
|
|
633
|
+
|
|
634
|
+
Confirm:
|
|
635
|
+
- The app runs without errors
|
|
636
|
+
- The request appears in the gateway logs (via the CLI above, or the Respan platform at https://platform.respan.ai)
|
|
637
|
+
|
|
638
|
+
If no log entry appears, the request is not actually routing through the gateway — debug
|
|
639
|
+
the \`base_url\`/wiring and re-run before declaring setup done.
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
## Reference
|
|
644
|
+
|
|
645
|
+
### Wiring Patterns
|
|
646
|
+
|
|
276
647
|
Point the LLM client's \`base_url\` at the Respan gateway. The Respan API key authenticates both the proxy and tracing.
|
|
277
648
|
|
|
278
|
-
|
|
649
|
+
#### Python (OpenAI SDK)
|
|
279
650
|
|
|
280
651
|
\`\`\`python
|
|
281
652
|
import os
|
|
@@ -292,7 +663,7 @@ response = client.chat.completions.create(
|
|
|
292
663
|
)
|
|
293
664
|
\`\`\`
|
|
294
665
|
|
|
295
|
-
|
|
666
|
+
#### TypeScript (OpenAI SDK)
|
|
296
667
|
|
|
297
668
|
\`\`\`typescript
|
|
298
669
|
import OpenAI from "openai";
|
|
@@ -308,7 +679,7 @@ const response = await client.chat.completions.create({
|
|
|
308
679
|
});
|
|
309
680
|
\`\`\`
|
|
310
681
|
|
|
311
|
-
|
|
682
|
+
#### Python (Anthropic SDK)
|
|
312
683
|
|
|
313
684
|
\`\`\`python
|
|
314
685
|
import os
|
|
@@ -320,7 +691,7 @@ client = anthropic.Anthropic(
|
|
|
320
691
|
)
|
|
321
692
|
\`\`\`
|
|
322
693
|
|
|
323
|
-
|
|
694
|
+
#### Environment variables
|
|
324
695
|
|
|
325
696
|
Set once, works everywhere:
|
|
326
697
|
|
|
@@ -330,53 +701,9 @@ export OPENAI_API_KEY="$RESPAN_API_KEY"
|
|
|
330
701
|
export OPENAI_BASE_URL="https://api.respan.ai/api"
|
|
331
702
|
\`\`\`
|
|
332
703
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
## Gateway + Tracing (Both)
|
|
336
|
-
|
|
337
|
-
Combine SDK tracing and gateway routing:
|
|
338
|
-
|
|
339
|
-
### Python
|
|
340
|
-
|
|
341
|
-
\`\`\`python
|
|
342
|
-
import os
|
|
343
|
-
from openai import OpenAI
|
|
344
|
-
from respan import Respan
|
|
345
|
-
|
|
346
|
-
respan_api_key = os.environ["RESPAN_API_KEY"]
|
|
347
|
-
respan_base_url = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
|
|
348
|
-
|
|
349
|
-
respan = Respan(api_key=respan_api_key, base_url=respan_base_url)
|
|
350
|
-
|
|
351
|
-
client = OpenAI(
|
|
352
|
-
api_key=respan_api_key,
|
|
353
|
-
base_url=respan_base_url,
|
|
354
|
-
)
|
|
355
|
-
\`\`\`
|
|
356
|
-
|
|
357
|
-
### TypeScript
|
|
358
|
-
|
|
359
|
-
\`\`\`typescript
|
|
360
|
-
import OpenAI from "openai";
|
|
361
|
-
import { Respan } from "@respan/respan";
|
|
362
|
-
|
|
363
|
-
const respanApiKey = process.env.RESPAN_API_KEY!;
|
|
364
|
-
const respanBaseUrl = process.env.RESPAN_BASE_URL || "https://api.respan.ai/api";
|
|
365
|
-
|
|
366
|
-
const respan = new Respan({ apiKey: respanApiKey, baseUrl: respanBaseUrl });
|
|
367
|
-
await respan.initialize();
|
|
368
|
-
|
|
369
|
-
const client = new OpenAI({
|
|
370
|
-
apiKey: respanApiKey,
|
|
371
|
-
baseURL: respanBaseUrl,
|
|
372
|
-
});
|
|
373
|
-
\`\`\`
|
|
374
|
-
|
|
375
|
-
---
|
|
376
|
-
|
|
377
|
-
## Framework-Specific Gateway Setup
|
|
704
|
+
### Framework-Specific Gateway Setup
|
|
378
705
|
|
|
379
|
-
|
|
706
|
+
#### CrewAI
|
|
380
707
|
|
|
381
708
|
\`\`\`python
|
|
382
709
|
import os
|
|
@@ -387,7 +714,7 @@ from crewai import Agent, Task, Crew
|
|
|
387
714
|
# CrewAI uses the env vars automatically
|
|
388
715
|
\`\`\`
|
|
389
716
|
|
|
390
|
-
|
|
717
|
+
#### Haystack
|
|
391
718
|
|
|
392
719
|
\`\`\`python
|
|
393
720
|
import os
|
|
@@ -398,7 +725,7 @@ from haystack.components.generators import OpenAIGenerator
|
|
|
398
725
|
# OpenAIGenerator picks up env vars automatically
|
|
399
726
|
\`\`\`
|
|
400
727
|
|
|
401
|
-
|
|
728
|
+
#### OpenAI Agents SDK
|
|
402
729
|
|
|
403
730
|
\`\`\`python
|
|
404
731
|
import os
|
|
@@ -406,7 +733,7 @@ os.environ["OPENAI_API_KEY"] = os.environ["RESPAN_API_KEY"]
|
|
|
406
733
|
os.environ["OPENAI_BASE_URL"] = os.getenv("RESPAN_BASE_URL", "https://api.respan.ai/api")
|
|
407
734
|
\`\`\`
|
|
408
735
|
|
|
409
|
-
|
|
736
|
+
#### Pydantic AI
|
|
410
737
|
|
|
411
738
|
\`\`\`python
|
|
412
739
|
import os
|
|
@@ -417,9 +744,7 @@ from pydantic_ai import Agent
|
|
|
417
744
|
agent = Agent(model="openai:gpt-4o-mini")
|
|
418
745
|
\`\`\`
|
|
419
746
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
## Model Switching
|
|
747
|
+
### Model Switching
|
|
423
748
|
|
|
424
749
|
The gateway supports 250+ models across providers. Use any model name:
|
|
425
750
|
|
|
@@ -439,11 +764,9 @@ response = client.chat.completions.create(model="llama-3.1-70b", ...)
|
|
|
439
764
|
|
|
440
765
|
No code changes needed — just change the model string. View all models at \`https://platform.respan.ai/platform/models\`.
|
|
441
766
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
## Advanced Features
|
|
767
|
+
### Advanced Features
|
|
445
768
|
|
|
446
|
-
|
|
769
|
+
#### Fallback Models
|
|
447
770
|
|
|
448
771
|
Automatic failover if the primary model fails:
|
|
449
772
|
|
|
@@ -457,7 +780,7 @@ response = client.chat.completions.create(
|
|
|
457
780
|
)
|
|
458
781
|
\`\`\`
|
|
459
782
|
|
|
460
|
-
|
|
783
|
+
#### Retries
|
|
461
784
|
|
|
462
785
|
\`\`\`python
|
|
463
786
|
response = client.chat.completions.create(
|
|
@@ -469,7 +792,7 @@ response = client.chat.completions.create(
|
|
|
469
792
|
)
|
|
470
793
|
\`\`\`
|
|
471
794
|
|
|
472
|
-
|
|
795
|
+
#### Caching
|
|
473
796
|
|
|
474
797
|
Enable response caching to save cost on repeated calls:
|
|
475
798
|
|
|
@@ -484,7 +807,7 @@ response = client.chat.completions.create(
|
|
|
484
807
|
)
|
|
485
808
|
\`\`\`
|
|
486
809
|
|
|
487
|
-
|
|
810
|
+
#### Streaming
|
|
488
811
|
|
|
489
812
|
Streaming works normally through the gateway:
|
|
490
813
|
|
|
@@ -498,7 +821,7 @@ for chunk in stream:
|
|
|
498
821
|
print(chunk.choices[0].delta.content, end="")
|
|
499
822
|
\`\`\`
|
|
500
823
|
|
|
501
|
-
|
|
824
|
+
#### Disable Logging
|
|
502
825
|
|
|
503
826
|
For sensitive data, disable logging on specific requests:
|
|
504
827
|
|
|
@@ -512,9 +835,7 @@ response = client.chat.completions.create(
|
|
|
512
835
|
)
|
|
513
836
|
\`\`\`
|
|
514
837
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
## Key Benefits
|
|
838
|
+
### Key Benefits
|
|
518
839
|
|
|
519
840
|
- **Unified key management** — one Respan API key for all providers
|
|
520
841
|
- **Automatic logging** — every request logged as a span
|