Skip to main content
ff.wrap(client) returns a transparent proxy of your LLM client. You call it exactly as before; behind each messages.create (Anthropic), chat.completions.create (OpenAI), or embeddings.create it captures tokens, cost, latency, HTTP status, and (opt-in) prompt/completion content, then records them to your Supabase.
Provider is detected by the client’s shape, so there is no hard dependency on either SDK. You build the client and supply its API key the provider SDK’s default variable (ANTHROPIC_API_KEY / OPENAI_API_KEY), your own env name passed explicitly, or createAIClient({ apiKey }). FirstFlow reads no credentials; it only observes the calls.

The firstflow call metadata

Add a firstflow field to any wrapped call. It is read and stripped before the request reaches the provider.
userId
string
The end user the call belongs to. Stored on firstflow_llm_calls.
conversationId
string
Groups the call into a conversation. When set with userId, the wrap also records the prompting user message and the assistant reply to firstflow_conversation_messages.
sessionId
string
Alias for conversationId pass whichever name your code already uses (the browser SDK calls this shared id sessionId). When both are set, conversationId wins.
metadata
Record<string, unknown>
Arbitrary tags merged into the recorded row’s metadata.

Scope: user vs. conversation

What you pass decides the scope of what’s recorded:

Bring your own OpenAI-compatible endpoint

@firstflow/runtime-server/aiclient is a pre-wrapped client for any OpenAI-compatible server (Ollama, vLLM, LM Studio, LocalAI, a gateway):
openai is an optional peer dependency loaded only by this subpath. Install it (pnpm add openai) when you use createAIClient; Anthropic-only apps never pull it in. Equivalent to new Firstflow({ persistence }).wrap(new OpenAI({ baseURL, apiKey })).

Content capture

captureContent: true on new Firstflow({...}) stores prompt and completion text in firstflow_conversation_messages. Leave it off (the default) to record only metadata tokens, cost, latency, status.

Next

Group multiple calls with traces, see exactly what gets recorded, or classify the conversation in Intent & sentiment.