Getting started

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.

After this code runs, open your Currai workspace and check the traces table for chat-turn. If the trace does not appear within a few seconds, start with Troubleshooting: most missing traces come from missing environment variables, invalid keys, or returning from a serverless handler before flushAsync() / flush_async() finishes.

TypeScript

code
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

code
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. In Python, a synchronous currai.flush() is also available for non-async call sites. 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.

What to check in the dashboard

The first trace should show:

  • chat-turn as the trace name.
  • production as the environment.
  • user-1 and sess-1 on the trace metadata.
  • One openai.chat.completions generation nested inside the trace.
  • Prompt, completion, token usage, latency, and cost on the generation.

If you see the trace but not the generation, make sure generation.end() runs after the provider call. If you see the generation but cost is empty, make sure you send usage.input, usage.output, and the model name.

Next, go deeper on generations, or see full runnable apps in the examples repo.