@zespan/sdk 1.0.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/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # @zespan/sdk
2
+
3
+ Agent observability for Node.js. Trace every AI call — latency, tokens, cost, errors — with one `init()`.
4
+
5
+ > For full documentation visit [docs.zespan.com](https://docs.zespan.com)
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @zespan/sdk
11
+ # or
12
+ pnpm add @zespan/sdk
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { init } from "@zespan/sdk";
19
+
20
+ init({
21
+ apiKey: "lqt_your_key_here",
22
+ projectId: "your_project_id",
23
+ });
24
+ ```
25
+
26
+ Get your API key and project ID from [app.zespan.com](https://app.zespan.com) → Project Settings → API Keys.
27
+
28
+ After `init()`, all calls to OpenAI, Anthropic, and Google GenAI are automatically traced. No further changes needed.
29
+
30
+ ## Auto-instrumentation
31
+
32
+ By default, `init()` patches OpenAI, Anthropic, and Google GenAI as soon as they are imported. You do not need to wrap anything.
33
+
34
+ ```ts
35
+ import { init } from "@zespan/sdk";
36
+ import OpenAI from "openai";
37
+
38
+ init({ apiKey: "lqt_...", projectId: "proj_..." });
39
+
40
+ const openai = new OpenAI();
41
+ // This call is automatically traced
42
+ const response = await openai.chat.completions.create({
43
+ model: "gpt-4o",
44
+ messages: [{ role: "user", content: "Hello" }],
45
+ });
46
+ ```
47
+
48
+ To disable autopatch and wrap manually:
49
+
50
+ ```ts
51
+ init({ apiKey: "lqt_...", autopatch: false });
52
+ ```
53
+
54
+ ## Manual wrappers
55
+
56
+ When you need explicit control, or when using providers beyond OpenAI/Anthropic/Google:
57
+
58
+ ```ts
59
+ import { init, wrapOpenAI, wrapAnthropic, wrapGoogle } from "@zespan/sdk";
60
+ import OpenAI from "openai";
61
+ import Anthropic from "@anthropic-ai/sdk";
62
+ import { GoogleGenerativeAI } from "@google/generative-ai";
63
+
64
+ init({ apiKey: "lqt_...", autopatch: false });
65
+
66
+ const openai = wrapOpenAI(new OpenAI());
67
+ const anthropic = wrapAnthropic(new Anthropic());
68
+ const google = wrapGoogle(new GoogleGenerativeAI(process.env.GOOGLE_API_KEY!));
69
+ ```
70
+
71
+ **All available wrappers:**
72
+
73
+ | Function | Provider |
74
+ | ------------------------ | -------------------- |
75
+ | `wrapOpenAI(client)` | OpenAI |
76
+ | `wrapAnthropic(client)` | Anthropic |
77
+ | `wrapGoogle(client)` | Google Generative AI |
78
+ | `wrapOpenRouter(client)` | OpenRouter |
79
+ | `wrapBedrock(client)` | AWS Bedrock |
80
+ | `wrapMistral(client)` | Mistral |
81
+ | `wrapGroq(client)` | Groq |
82
+ | `wrapLiteLLM(client)` | LiteLLM |
83
+
84
+ ## Configuration
85
+
86
+ ```ts
87
+ init({
88
+ apiKey: "lqt_...", // required
89
+ projectId: "proj_...", // required — links traces to a project
90
+ environment: "production", // default: "production"
91
+ storePrompts: false, // store prompt/completion text (default: false)
92
+ redactKeys: ["password", "secret", "token", "api_key"], // keys to redact
93
+ sampleRate: 1.0, // 0.0–1.0, fraction of events to send
94
+ debug: false, // log SDK activity to console
95
+ batchSize: 50, // events per batch flush
96
+ flushInterval: 2000, // ms between batch flushes
97
+ autopatch: true, // auto-instrument OpenAI/Anthropic/Google
98
+ });
99
+ ```
100
+
101
+ ## User and session context
102
+
103
+ Tag traces with user ID, session ID, or custom metadata:
104
+
105
+ ```ts
106
+ import { withZespanContext } from "@zespan/sdk";
107
+
108
+ await withZespanContext(
109
+ { userId: "user_123", sessionId: "sess_abc", tags: { feature: "chat" } },
110
+ async () => {
111
+ // All AI calls inside here are tagged with this context
112
+ await openai.chat.completions.create({ ... });
113
+ }
114
+ );
115
+ ```
116
+
117
+ ## Agent tracing
118
+
119
+ Group multi-step agent workflows into a single trace:
120
+
121
+ ```ts
122
+ import { withAgent } from "@zespan/sdk";
123
+
124
+ await withAgent(
125
+ {
126
+ name: "SupportAgent",
127
+ role: "specialist",
128
+ framework: "custom",
129
+ tools: [{ name: "lookup_order", description: "Look up order by ID" }],
130
+ },
131
+ async (agent) => {
132
+ agent.logPlan(["Look up order", "Check policy", "Draft reply"]);
133
+
134
+ const result = await agent.traceTool(
135
+ "lookup_order",
136
+ { order_id: "123" },
137
+ async () => fetchOrder("123")
138
+ );
139
+
140
+ agent.delegateTo("RefundAgent", "refund requested");
141
+
142
+ // Wrapped LLM calls inside here inherit agent context
143
+ await openai.chat.completions.create({ ... });
144
+ }
145
+ );
146
+ ```
147
+
148
+ ## Manual spans
149
+
150
+ Trace custom operations that aren't LLM calls:
151
+
152
+ ```ts
153
+ import { startSpan } from "@zespan/sdk";
154
+
155
+ const { span, run } = startSpan({
156
+ name: "document-retrieval",
157
+ span_kind: "retrieval",
158
+ });
159
+
160
+ await run(async () => {
161
+ const docs = await vectorStore.search(query);
162
+ await span.end({ status: "success" });
163
+ return docs;
164
+ });
165
+ ```
166
+
167
+ ## Framework integrations
168
+
169
+ ### LangChain
170
+
171
+ ```ts
172
+ import { ZespanCallbackHandler } from "@zespan/sdk";
173
+
174
+ const handler = new ZespanCallbackHandler();
175
+
176
+ const chain = new LLMChain({ llm, prompt, callbacks: [handler] });
177
+ ```
178
+
179
+ ### Vercel AI SDK
180
+
181
+ ```ts
182
+ import { instrumentVercelAI, getLumiqVercelTelemetry } from "@zespan/sdk";
183
+
184
+ instrumentVercelAI();
185
+
186
+ // Or per-call:
187
+ const result = await generateText({
188
+ model: openai("gpt-4o"),
189
+ prompt: "Hello",
190
+ experimental_telemetry: getLumiqVercelTelemetry({ traceId: "my-trace" }),
191
+ });
192
+ ```
193
+
194
+ ### Google ADK
195
+
196
+ ```ts
197
+ import { instrumentADK } from "@zespan/sdk";
198
+
199
+ instrumentADK(); // patches all ADK agents globally
200
+ ```
201
+
202
+ Or wrap a specific agent:
203
+
204
+ ```ts
205
+ import { wrapADKAgent } from "@zespan/sdk";
206
+
207
+ const traced = wrapADKAgent(myAgent, { name: "MyAgent" });
208
+ ```
209
+
210
+ ### LlamaIndex
211
+
212
+ ```ts
213
+ import { LumiqLlamaIndexHandler } from "@zespan/sdk";
214
+
215
+ const handler = new LumiqLlamaIndexHandler();
216
+ Settings.callbackManager.addEventHandler(handler);
217
+ ```
218
+
219
+ ### CrewAI / AutoGen / PydanticAI
220
+
221
+ These frameworks use OTEL-based instrumentation. See exports:
222
+
223
+ ```ts
224
+ import {
225
+ CREWAI_OTEL_ENV,
226
+ getCrewAIInstrumentationGuide,
227
+ } from "@zespan/sdk";
228
+ import { injectAutoGenContext } from "@zespan/sdk";
229
+ import { getPydanticAIConfig } from "@zespan/sdk";
230
+ ```
231
+
232
+ ## Prompt management
233
+
234
+ Fetch versioned prompts from Zespan with 5-minute client-side cache:
235
+
236
+ ```ts
237
+ import { getZespanClient } from "@zespan/sdk";
238
+
239
+ const client = getZespanClient();
240
+
241
+ // Latest version
242
+ const prompt = await client.prompts.get("support-reply");
243
+
244
+ // Specific version or label
245
+ const prompt = await client.prompts.get("support-reply", { version: 3 });
246
+ const prompt = await client.prompts.get("support-reply", {
247
+ label: "production",
248
+ });
249
+
250
+ // Compile variables
251
+ const text = client.prompts.compile(prompt, {
252
+ user_name: "Alice",
253
+ product: "Pro",
254
+ });
255
+ ```
256
+
257
+ ## Guardrails
258
+
259
+ Check content against your configured guardrail rules before or after LLM calls:
260
+
261
+ ```ts
262
+ import { getZespanClient, GuardrailBlockedError } from "@zespan/sdk";
263
+
264
+ const client = getZespanClient();
265
+
266
+ try {
267
+ const check = await client.checkGuardrails({
268
+ text: userMessage,
269
+ phase: "pre",
270
+ });
271
+
272
+ if (!check.allowed) {
273
+ return "Request blocked by content policy.";
274
+ }
275
+
276
+ const response = await openai.chat.completions.create({ ... });
277
+
278
+ const postCheck = await client.checkGuardrails({
279
+ text: response.choices[0].message.content!,
280
+ phase: "post",
281
+ });
282
+
283
+ return postCheck.modifiedText ?? response.choices[0].message.content;
284
+ } catch (err) {
285
+ if (err instanceof GuardrailBlockedError) {
286
+ return "Response blocked by content policy.";
287
+ }
288
+ throw err;
289
+ }
290
+ ```
291
+
292
+ Guardrails can also be applied automatically via wrapper options:
293
+
294
+ ```ts
295
+ const openai = wrapOpenAI(new OpenAI(), { guardrails: true });
296
+ // or fine-grained:
297
+ const openai = wrapOpenAI(new OpenAI(), {
298
+ guardrails: { pre: true, post: true, failClosed: false },
299
+ });
300
+ ```
301
+
302
+ ## Flush on exit
303
+
304
+ The SDK flushes automatically on `process.beforeExit`. For serverless functions or short-lived scripts, flush manually:
305
+
306
+ ```ts
307
+ import { getZespanClient } from "@zespan/sdk";
308
+
309
+ await getZespanClient().flush();
310
+ ```
311
+
312
+ ## OpenTelemetry
313
+
314
+ Enable native OTEL export alongside Zespan:
315
+
316
+ ```ts
317
+ init({
318
+ apiKey: "lqt_...",
319
+ enableOTel: true,
320
+ otelEndpoint: "http://localhost:4318",
321
+ otelServiceName: "my-service",
322
+ });
323
+ ```
324
+
325
+ ## TypeScript
326
+
327
+ The SDK is fully typed. All wrapper functions preserve the original client's type signature.