Overview

Grounded SDK

The Grounded SDK is a server-side TypeScript interface to the existing Grounded /api surface.

It is not a monolithic browser analytics package. It is two packages with one brand:

PackagePurposeAuthMain Routes
@grounded/clientControl-plane automation for agents, connectors, sessions, snapshots, jobs, evals, and datasetsSecret key grd_sk_.../api/agents, /api/connectors, /api/sessions, /api/snapshots, /api/jobs, /api/job-loops, /api/evals
@grounded/tracingDirect trace, span, score, and identity ingestion from your app runtimePublishable key grd_pk_.../api/traces/batch, /api/traces/:id, /api/traces/:id/spans, /api/traces/:id/scores

What The SDK Actually Does

Grounded has two different kinds of work:

  1. Control plane work. You create or inspect Grounded resources such as connectors, snapshots, jobs, evals, and datasets.
  2. Data plane work. You send your application's traces into Grounded so they can be inspected directly and, when tied to an agent, normalized into sessions that power insights and optimization workflows.

That split is why the SDK is two packages instead of one.

@grounded/client

Use the client package when you want to automate Grounded itself:

  • create and inspect agents
  • create, update, connect, disconnect, and sync connectors
  • list sessions and session stats
  • read insights
  • fork snapshots, update drafts, run analysis, activate or reject snapshots
  • create and poll jobs
  • manage job loops
  • create evals, run evals, and inspect eval runs
  • create datasets and list dataset rows

The client intentionally smooths over the current backend response differences. Some existing routes return raw arrays, some return { data: [...] }, and some return paginated objects. The SDK normalizes those into consistent return shapes.

@grounded/tracing

Use the tracing package when your app already has the data and you want to send it straight to Grounded:

  • start a trace for a request, conversation, or background task
  • create spans for LLM calls, tools, retrieval, or app logic
  • record trace- or span-level events
  • attach scores such as resolved=true or groundedness=0.91
  • tag traces with environment, release, agentId, and snapshotId
  • optionally wrap OpenAI calls so spans are created automatically
  • batch and flush completed traces efficiently

This package sends completed traces, not partial streaming span updates. Each completed trace is posted to /api/traces/batch.

How It Fits Into Grounded

If you send traces with a valid resource.agentId, Grounded stores the raw trace and then tries to normalize it into the same session model used by connector-ingested data.

That means a directly ingested trace can become:

  • a session in the session explorer
  • input for insight mining
  • input for snapshot analysis and optimization
  • input for eval workflows

To make that work in practice:

  • resource.agentId is required for trace ingestion
  • resource.snapshotId is optional, but if provided it must belong to that agent
  • if resource.snapshotId is omitted, Grounded uses the latest snapshot for that agent
  • if the agent has no snapshot yet, the trace is stored but will not normalize into a session

Auth Model

The SDK reuses the current Grounded /api and adds API-key auth alongside dashboard session auth.

  • secret keys: grd_sk_...
    • used by @grounded/client
    • can be tenant-scoped or agent-scoped
    • carry explicit scopes such as connectors:write, jobs:read, or snapshots:write
  • publishable keys: grd_pk_...
    • used by @grounded/tracing
    • must be agent-scoped
    • can only carry trace scopes such as traces:write

Key issuance currently happens through internal, session-authenticated routes:

  • GET /api/api-keys
  • POST /api/api-keys
  • POST /api/api-keys/:keyId/revoke

Current Distribution

The SDK is implemented in the Grounded monorepo today:

  • @grounded/client
  • @grounded/tracing

The public npm publish is not live yet, so the docs below show the final package names and the current monorepo-first workflow.

First Example

import { Grounded } from '@grounded/client';
import { GroundedTracing } from '@grounded/tracing';
 
const grounded = new Grounded({
  apiKey: process.env.GROUNDED_SECRET_KEY!,
  baseUrl: process.env.GROUNDED_BASE_URL ?? 'http://localhost:3001',
});
 
const tracing = new GroundedTracing({
  publishableKey: process.env.GROUNDED_PUBLISHABLE_KEY!,
  baseUrl: process.env.GROUNDED_BASE_URL ?? 'http://localhost:3001',
  environment: 'production',
  release: 'api-2026-03-06',
});
 
const connector = await grounded.connectors.create({
  agentId: 'agt_123',
  name: 'LangSmith prod',
  category: 'llm-tracing',
  config: {
    apiKey: process.env.LANGSMITH_API_KEY!,
    projectName: 'support-prod',
  },
});
 
await grounded.connectors.connect(connector.id);
const syncJob = await grounded.connectors.sync(connector.id);
await grounded.jobs.wait(syncJob.id);
 
const trace = tracing.startTrace({
  traceId: 'chat_123',
  sessionId: 'chat_123',
  userId: 'user_123',
  name: 'support.reply',
  resource: { agentId: 'agt_123' },
  input: { message: 'where is my refund?' },
});
 
const span = trace.startSpan({
  name: 'policy.lookup',
  kind: 'retrieval',
  input: { source: 'faq' },
});
 
span.end({
  status: 'ok',
  output: { articleId: 'refund-policy-v3' },
});
 
trace.score({
  name: 'resolved',
  value: true,
  dataType: 'boolean',
});
 
await trace.end({
  status: 'ok',
  output: { text: 'your refund is processing' },
});
 
await tracing.flush();

Where To Go Next