Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.coval.dev/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Coval ships typed SDKs for TypeScript and Python. Both are generated from the public OpenAPI specs that power this API reference, so the surface area stays in sync with what the API accepts.

TypeScript

@coval/sdk on npm.

Python

coval-sdk on PyPI.
Both SDKs are MIT-licensed and live in coval-ai/coval-examples.

Install

npm install @coval/sdk
To install directly from the source repo:
# npm has no native "install from a git subdirectory" syntax, so clone and install:
git clone https://github.com/coval-ai/coval-examples.git
cd coval-examples/typescript-sdk
npm install
npm run build
npm link        # or: npm pack && npm install ../coval-examples/typescript-sdk/coval-sdk-*.tgz

Quick start

import { CovalClient } from '@coval/sdk';

const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
});

const page = await coval.agents.listAgents({ pageSize: 50 });
for (const agent of page.agents ?? []) {
  console.log(agent.id, agent.display_name);
}
The TypeScript client exposes every v1 API resource as a property on CovalClient: coval.agents, coval.conversations, coval.simulations, coval.traces, coval.metrics, and so on (22 resources total). The Python client is split into one *Api class per resource (AgentsApi, ConversationsApi, SimulationsApi, etc.) constructed against a shared ApiClient.

Auth

The Coval API gateway requires the header x-api-key in lowercase. Uppercase X-API-Key is rejected with Missing API Key.
// Handled automatically. The CovalClient middleware sets the header for you.
const coval = new CovalClient({ apiKey: process.env.COVAL_API_KEY! });
If you see {"message": "Missing API Key"} from the gateway, check that the header name is lowercase. The TypeScript SDK takes care of this for you; the Python SDK leaves it to your set_default_header call.

Errors

import { CovalApiError, CovalNetworkError, CovalClient } from '@coval/sdk';

const coval = new CovalClient({ apiKey: process.env.COVAL_API_KEY! });

try {
  await coval.agents.getAgent({ agentId: 'ag_does_not_exist' });
} catch (err) {
  if (err instanceof CovalApiError) {
    console.error(`HTTP ${err.status} ${err.code ?? ''}: ${err.message}`);
    console.error(`  request_id: ${err.requestId ?? '-'}`);
    console.error(`  body: ${JSON.stringify(err.body)}`);
  } else if (err instanceof CovalNetworkError) {
    console.error(`Network failure after ${err.attempts} attempt(s): ${err.message}`);
  } else {
    throw err;
  }
}
CovalApiError shape: status, code, message, requestId, body, url, method. The requestId is sourced from x-request-id, x-amzn-requestid, or the response body in that order. Include it when you file a support ticket.

Python: --raw fallback for legacy data

The Python client uses strict pydantic v2 models for every response, including regex patterns on IDs (e.g., agent_id must match ^[A-Za-z0-9]{22}$). If your org has historical data that predates the current spec, for example an agent created when IDs had a different shape, pydantic will raise a ValidationError mid-stream and you will lose the rest of the page. The fix is to call the *_without_preload_content variant of any method and parse the response yourself:
import json

resp = AgentsApi(client).list_agents_without_preload_content(page_size=50)
body = json.loads(resp.data.decode("utf-8"))
for a in body["agents"]:
    print(a.get("id"), a.get("display_name"))
Every generated method has a _without_preload_content sibling. The TypeScript SDK does not have this issue: its types are emitted as interface declarations with no runtime validation, so unknown fields pass through.

Retries

The TypeScript SDK retries with exponential backoff and jitter on transient failures. Defaults:
SettingDefaultNotes
Max attempts3Includes the first attempt.
Base delay200msEffective delay = base * 2^(attempt-1) plus jitter.
Max delay5000msCap on any single backoff.
Retryable statuses408, 429, 500, 502, 503, 504Plus network and transport errors.
Retry-AfterHonoredNumeric seconds or HTTP-date both accepted.
// Override
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  retry: { maxAttempts: 5, baseDelayMs: 100, maxDelayMs: 10_000 },
});

// Disable entirely
const noRetry = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  retry: false,
});
When all attempts are exhausted on a transport error, the client throws CovalNetworkError. When a non-retryable status (e.g., 400, 404) comes back, it falls through to the normal error path and raises CovalApiError immediately. For Python, wrap your own calls with tenacity or a similar library.

Pagination

The Coval v1 API uses next_page_token-style pagination. The TypeScript SDK ships an async iterator that handles the loop for you:
import { CovalClient, paginate, collectAll } from '@coval/sdk';

const coval = new CovalClient({ apiKey: process.env.COVAL_API_KEY! });

// Iterate lazily across pages
for await (const agent of paginate({
  fetchPage: (pageToken) => coval.agents.listAgents({ pageToken, pageSize: 50 }),
  items: (page) => page.agents,
  nextToken: (page) => page.next_page_token,
})) {
  console.log(agent.id, agent.display_name);
}

// Or buffer everything into an array
const allAgents = await collectAll({
  fetchPage: (pageToken) => coval.agents.listAgents({ pageToken, pageSize: 50 }),
  items: (page) => page.agents,
  nextToken: (page) => page.next_page_token,
});
paginate and collectAll work with any list endpoint. Provide fetchPage, items, and nextToken callbacks for the method you are calling.
Pass maxPages to cap iteration. Useful when you want a quick preview of a large list without hitting the full backlog.
For Python, use a while loop on next_page_token. See the list_agents.py example for the shape.

Customization

Base URL

Point the client at staging, a self-hosted gateway, or a regional endpoint:
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  baseUrl: 'https://staging.api.coval.dev',
});

Middleware (TypeScript)

Inject request and response middleware after the auth and error layers. Useful for logging, OpenTelemetry spans, or attaching request IDs you control:
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  middleware: [
    {
      async pre(ctx) {
        console.log(`-> ${ctx.init.method} ${ctx.url}`);
      },
      async post(ctx) {
        console.log(`<- ${ctx.response.status} ${ctx.url}`);
      },
    },
  ],
});

Custom fetch

Swap the underlying fetch implementation. For example, to use undici with keepalive in a long-running Node process, or to stub network calls in tests:
import { fetch as undiciFetch, Agent } from 'undici';

const dispatcher = new Agent({ keepAliveTimeout: 60_000 });
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  fetch: ((url, init) => undiciFetch(url, { ...init, dispatcher })) as typeof fetch,
});

Versioning

Both SDKs are generated from the same OpenAPI specs that power this API reference.
  • Minor version bumps (0.2.x0.3.0) reflect spec evolution: new endpoints, new optional fields, additional response shapes. Generally safe to upgrade.
  • Major version bumps (0.x1.0) signal breaking changes in the client surface (CovalClient options, error class shapes, pagination helper signatures).
To regenerate locally:
git clone https://github.com/coval-ai/coval-examples.git
cd coval-examples
node scripts/bundle-spec.mjs       # pull and bundle the latest specs
bash scripts/generate-sdks.sh      # regenerate both clients

Going deeper

Source repo

Full SDK source, examples folder, and the generation scripts. Open issues here.

TypeScript examples

list-agents.ts, submit-conversation.ts. Runnable end-to-end samples.

Python examples

list_agents.py with --raw fallback pattern for legacy data.

OpenAPI specs

The specs that power both SDKs are published at https://api.coval.dev/v1/openapi.

API keys

How to mint and rotate API keys from the dashboard.

CLI

Prefer the shell? coval-cli covers the same surface area.