SDK Reference
API reference for @argosvix/sdk. Wrap your AI client once with wrap() and every call is recorded automatically.
Install
npm install @argosvix/sdk@alpha <provider-sdk>
Use openai, @anthropic-ai/sdk, @google/genai, or @mistralai/mistralai as <provider-sdk> (you can mix multiple providers).
wrap(client, options)
Returns a wrapped instance of your AI client. For typical usage (calling create, consuming streams with for-await) you can drop it in without touching the rest of your code.
OpenAI's advanced APIs mostly work as-is after wrapping: .withResponse(), and streaming .tee() / .toReadableStream() / .controller (abort) all keep working. To use them on streams, set stream_options explicitly (without it, a compatibility wrapper is returned for usage recording, and these methods are absent). Two caveats: .asResponse() (reading the raw Response directly) is not supported because it cannot coexist with recording — use the unwrapped client for those specific calls. And since the full stream is read for recording, slow consumption of a received stream temporarily holds the whole response in memory.
import { wrap } from "@argosvix/sdk";
import OpenAI from "openai";
const openai = wrap(new OpenAI(), {
apiKey: process.env.ARGOSVIX_API_KEY,
tags: { service: "my-app", env: "prod" },
});
options.apiKey (required)
The argk_... token issued on the API keys page. Pass it from an environment variable.
options.tags (optional)
Arbitrary key/value pairs you can use as filter and aggregation axes on the dashboard. Common examples:
tags: {
service: "my-app", // split multiple services in one dashboard
env: "prod", // separate staging vs prod counts
feature: "summarize", // compare cost / latency per feature
userId: "u_xxx", // per-user usage measurement (PII caution — hash recommended)
}
⚠️ Do not put end-user PII (email, name, etc.) into
tags(see Terms § 4, paragraph 2).
options.sessionId (optional)
An ID that groups calls belonging to the same session (conversation). When set, it is stored on each record as sessionId and can be used to filter by session in the query API. In the Python SDK, pass session_id="...".
const openai = wrap(new OpenAI(), {
apiKey: process.env.ARGOSVIX_API_KEY,
sessionId: "sess_2026_07_08_abc",
});
options.captureContent (optional, default false)
When true, prompt and completion bodies are included in the records. Non-streaming calls are supported across all 4 providers; streaming calls also capture bodies on all observed paths (OpenAI Chat / OpenAI Responses / Anthropic / Gemini / Mistral, in both TypeScript and Python), accumulating up to 256KB per call — anything beyond is dropped and a truncated marker is appended, and if a stream is interrupted the body captured so far is still recorded.
When a response contains tool calls (function calling), the tool names and arguments are also recorded as toolCalls (PII inside arguments is masked under the same rules as bodies).
const openai = wrap(new OpenAI(), {
apiKey: process.env.ARGOSVIX_API_KEY,
captureContent: true,
});
In the Python SDK, pass capture_content=True.
client = wrap(OpenAI(), api_key=os.environ["ARGOSVIX_API_KEY"], capture_content=True)
How it works and how it stays safe:
- PII masking always runs before sending (emails, card numbers, phone numbers, national IDs, and IP addresses are replaced with
[REDACTED_*]). - On the server, bodies are stored (AES-256-GCM encrypted) only when the account is on Pro or above and has explicitly opted in to plaintext storage in the dashboard. Without that consent, submitted bodies are discarded, not stored.
- Viewing, deleting, and access logs for stored bodies are managed under Privacy & Data in the dashboard settings. See Terms Article 4-2 for details.
Deployed prompts and version tagging (resolvePrompt / withPrompt)
Fetch the currently deployed version of a managed prompt from the SDK, and automatically
tag calls made with it as prompt ({name}@v{version}) — the foundation for per-version
quality and cost comparison.
import { resolvePrompt, withPrompt } from "@argosvix/sdk";
const p = await resolvePrompt("support-bot", {
apiKey: process.env.ARGOSVIX_API_KEY!,
// label: "production" (default)
});
await withPrompt(p, async () => {
// Calls inside get tags.prompt = "support-bot@v3" automatically
await openai.chat.completions.create({
model: "gpt-5.5",
messages: [{ role: "system", content: p.template }],
});
});
resolvePromptkeeps a 60-second TTL cache and falls back to a stale entry on network or server failures, so your hot path never blocks on prompt resolution (a 404 for a missing deployment still throws).- An explicit
tags.prompton a call takes precedence over the ambient tag. - The Python SDK mirrors this with
resolve_prompt(name, api_key=...)and thewith_prompt(p):context manager.
flushClient(client)
In short-lived runtimes (Cloudflare Workers, AWS Lambda, Vercel Edge, and similar) you must await flushClient() inside the handler's finally block. Without it, records will not reach the dashboard because the runtime terminates before the SDK finishes sending.
import { wrap, flushClient } from "@argosvix/sdk";
const client = wrap(new OpenAI(), {
apiKey: process.env.ARGOSVIX_API_KEY,
});
export default {
async fetch(req, env) {
try {
return await handler(client, req, env);
} finally {
await flushClient(client);
}
},
};
Long-lived processes (Node.js server, Bun, Deno deploy) don't need it. The TypeScript SDK sends automatically once its buffer reaches 100 records (call flushClient() any time to send earlier); the Python SDK flushes in the background roughly every 5 seconds. wrap() is best-effort by design: a failed send to Argosvix never breaks your application's LLM call.
Framework integrations
If you call models through a framework instead of a provider client directly, use the matching integration. Both record the same fields as wrap() (provider, model, tokens, cost, latency, TTFT, cache/reasoning tokens), support the same four providers (OpenAI / Anthropic / Google Gemini / Mistral), and honour budget/policy gates and withTrace grouping. Recording is best-effort — it never breaks your model call.
Vercel AI SDK (ai package)
argosvixMiddleware() returns a wrapLanguageModel-compatible middleware (LanguageModelV2 / V4). Every call through generateText / streamText / generateObject — including calls the AI SDK issues internally for tool loops and multi-step agents — is recorded.
import { openai } from "@ai-sdk/openai";
import { wrapLanguageModel, generateText } from "ai";
import { argosvixMiddleware, flushClient } from "@argosvix/sdk";
const observed = argosvixMiddleware({ apiKey: process.env.ARGOSVIX_API_KEY });
const model = wrapLanguageModel({ model: openai("gpt-5.5"), middleware: observed });
try {
await generateText({ model, prompt: "hi" });
} finally {
await flushClient(observed); // or: await observed.flush()
}
Other providers run normally but are not recorded — pass provider in the config to force a mapping.
LangChain.js
argosvixLangChainHandler() returns a callback handler. Pass it in callbacks (per call or at model construction) and every LLM call through LangChain — including chains and agents — is recorded.
import { ChatOpenAI } from "@langchain/openai";
import { argosvixLangChainHandler, flushClient } from "@argosvix/sdk";
const handler = argosvixLangChainHandler({ apiKey: process.env.ARGOSVIX_API_KEY });
const model = new ChatOpenAI({ model: "gpt-5.5" });
try {
await model.invoke("hi", { callbacks: [handler] });
} finally {
await flushClient(handler); // or: await handler.flush()
}
Covered methods per provider
| Provider | Covered methods |
|---|---|
| OpenAI | chat.completions.create, responses.create (both with streaming) |
| Anthropic | messages.create (with streaming) |
| Gemini | models.generateContent, models.generateContentStream |
| Mistral | chat.complete, chat.stream |
A note on interrupting streams early in the Python SDK: breaking out of a synchronous iteration records immediately, but breaking out of
async fordoes not guarantee immediate cleanup due to Python language semantics. To record reliably, consume the stream withasync with, or callawait stream.aclose()after breaking.
Any other method passes through (not recorded, but errors are not swallowed either). If you want a method outside this list to be recorded, email hello@argosvix.com.
Types
import type { ArgosvixConfig } from "@argosvix/sdk";
interface ArgosvixConfig {
/** argk_... token issued on the dashboard */
apiKey: string;
/** Arbitrary key/value pairs (filter / aggregation axes) */
tags?: Record<string, string | number | boolean>;
/** Custom base URL (e.g. proxy or testing; usually not needed) */
endpoint?: string;
}
Troubleshooting
- No records appear on the dashboard — check that you didn't forget
flushClient(in short-lived runtimes), verify network reachability, and double-check theapiKeyfor typos. - Records take a while to appear — sends are batched (TypeScript: at 100 records or on
flushClient(); Python: roughly every 5 seconds). For low-traffic processes, callflushClient()/flush()to see records immediately. - Cost shows as zero — the pricing table for that provider or model may not be registered yet. Email hello@argosvix.com and we can add it.
Support
Last updated: 2026-07-09