Your first trace

Wrap an LLM call in a trace and generation, send token usage, and flush before your process exits.

This is the whole quickstart: create a trace, record a generation inside it, end the generation with token usage, and flush. The SDK batches events in the background and ships them to Currai.

TypeScript

import { Currai } from "currai";

const currai = new Currai({
  publicKey: process.env.CURRAI_PUBLIC_KEY!,
  secretKey: process.env.CURRAI_SECRET_KEY!,
});

const trace = currai.trace({
  name: "chat-turn",
  sessionId: "sess-1",
  userId: "user-1",
  input: { messages },
  environment: "production",
  tags: ["chatbot"],
});

const generation = trace.generation({
  name: "openai.chat.completions",
  model: "gpt-4o-mini",
  input: messages,
  modelParameters: { temperature: 0.7 },
});

const completion = await openai.chat.completions.create({ /* … */ });

generation.end({
  output: completion.choices[0].message,
  usage: {
    input: completion.usage.prompt_tokens,
    output: completion.usage.completion_tokens,
    total: completion.usage.total_tokens,
    unit: "TOKENS",
  },
});

trace.update({ output: completion.choices[0].message.content });

await currai.flushAsync(); // required on serverless (Vercel, AWS Lambda, etc.)

Python

import os
from currai import Currai

currai = Currai(
    public_key=os.environ["CURRAI_PUBLIC_KEY"],
    secret_key=os.environ["CURRAI_SECRET_KEY"],
)

trace = currai.trace(
    name="chat-turn",
    session_id="sess-1",
    user_id="user-1",
    input={"messages": messages},
    environment="production",
    tags=["chatbot"],
)

generation = trace.generation(
    name="openai.chat.completions",
    model="gpt-4o-mini",
    input=messages,
    model_parameters={"temperature": 0.7},
)

completion = openai_client.chat.completions.create(...)

generation.end(
    output=completion.choices[0].message.content,
    usage={
        "input": completion.usage.prompt_tokens,
        "output": completion.usage.completion_tokens,
        "total": completion.usage.total_tokens,
        "unit": "TOKENS",
    },
)

trace.update(output=completion.choices[0].message.content)

await currai.flush_async()  # required before short-lived processes exit

Flush hygiene

The SDK buffers events and flushes them in the background, so instrumentation never blocks a request. But a short-lived process — a serverless function, a CLI, a worker that exits — can die before the buffer is sent.

Always flush before the process can exit. Call flushAsync() (TypeScript) or flush_async() (Python) at the end of a request handler or before shutdown. On a long-running server you can rely on the background flush interval and only flush on shutdown.

Provider support

The SDK is provider-agnostic — trace().generation().end({ model, output, usage }) works for any LLM. For OpenAI-compatible providers (OpenAI, Groq, xAI Grok, DeepSeek, Together), point the openai client at their baseURL and instrument the same way. For Anthropic, Gemini, or Bedrock, wrap the call manually — it's the same ~10 lines.

Next, go deeper on generations.