DoAIRight
Integrations · Direct SDK

Any app, two lines

When you call a provider SDK directly — or you’re not on LangChain — put one observe() right where you already have the prompt and the reply. That’s the whole integration.

Python

from doairight_evals import create_client

client = create_client(api_key="dar_...")            # key: /app/developer

# right where you already have the prompt and the model's reply:
resp = model.generate(prompt)                        # your existing call
client.observe(
    prompt=prompt,
    response=resp.text,
    kind="generative",
    model="gemini-2.5-flash",                        # optional, but useful
    provider="vertex",                               # optional
    latency_ms=1234,                                 # optional
    prompt_tokens=42, completion_tokens=17,          # optional
    metadata={"app": "my-app"},                      # optional
)

Only prompt and response are required — everything else is optional metadata that makes the run richer to score and filter. observe() enqueues and returns immediately: no network I/O on your thread, and it never raises into your caller.

TypeScript / JavaScript

import { createClient } from "@doairight/evals";

const client = createClient({ apiKey: "dar_..." });  // key: /app/developer

const reply = await model.generate(prompt);          // your existing call
client.observe({
  prompt,
  response: reply.text,
  kind: "generative",
  model: "gpt-4o",
  metadata: { app: "my-app" },
});

Install with npm install @doairight/evals. Same shape as Python, camelCase fields.

Any language — raw HTTP

curl -X POST https://doairight.com/api/evals/observe \
  -H "authorization: Bearer dar_..." \
  -H "content-type: application/json" \
  -d '{
    "prompt": "...",
    "response": "...",
    "kind": "generative",
    "model": "gpt-4o",
    "metadata": { "app": "my-app" }
  }'

No SDK for your stack? POST the same JSON to /api/evals/observe with your dar_ key as a bearer token. Full request/response shape: /docs/api.

Streaming responses

Assemble the streamed chunks into the final string as you already do, then call observe() once with the complete response. There’s no need to send partial tokens — DoAIRight scores the finished reply.

Shutdown (optional)

# On process shutdown, drain anything still queued:
client.close()

The client sends on a background worker. In short-lived scripts or workers, call close() (Python) / flush() (TS) before exit so queued runs aren’t lost. Long-running servers don’t need this.

On LangChain?

Skip the per-call-site work entirely — attach one callback handler instead: LangChain & LangGraph.