AgentwatchConsole
Integrations

OpenAI-compatible providers

Model, token counts, and tool names extracted automatically — no extra wiring.

If the value your wrapped function returns has the shape of an OpenAI chat completion, the SDK reads the fields it recognises straight off it. That covers OpenAI itself and every provider that speaks the same protocol:

  • OpenAI
  • Groq
  • Cerebras
  • Together
  • vLLM, and anything else exposing an OpenAI-compatible route

Wrapping a completion call

Wrap the call itself and the trace fills in on its own — no model, no token counts to thread through by hand.

chat.ts
import OpenAI from 'openai'
import { watch } from '@agentwatch-beta/sdk'

const client = new OpenAI({
  baseURL: 'https://api.groq.com/openai/v1',
  apiKey: process.env.GROQ_API_KEY,
})

const chat = watch(
  (messages) => client.chat.completions.create({
    model: 'llama-3.3-70b-versatile',
    messages,
  }),
  { apiKey: 'aw_live_...', agentId: '<agent-uuid>' },
)
model, tokens, and tool names read off the response

What is read off the response

  • Model — the model the provider reports having served, which is not always the one you asked for. Baselines are held per model, so a silent version bump surfaces as a change point instead of unexplained drift.
  • Token counts — prompt, completion, and total, from the usage block.
  • Tool names — the tools the completion called. A shift in which tools fire is a behavioural change even when the prose still reads fine.

Non-matching returns still trace

Nothing breaks if your function returns something else. The trace is captured with input, output, latency, and status as usual — the model and token fields are simply absent, and you can fill them in yourself with aw.trace().

Wrapping the agent, not the call

Wrapping the completion traces one model call. Wrapping your agent function traces the whole run — retrieval, tool calls, retries, and all — which is the unit AgentWatch scores. Prefer the outer one when your agent does more than a single completion.

ts
// traces one model call
const chat = watch((messages) => client.chat.completions.create({ ... }), opts)

// traces the whole run — usually what you want
const runAgent = watch(async (query: string) => {
  const docs = await retrieve(query)
  const answer = await client.chat.completions.create({ ... })
  return answer.choices[0].message.content
}, opts)

In the second form the return value is a string rather than a completion, so the model and token fields are not extracted. Return the completion object instead, or send them explicitly with aw.trace().