Quickstart
This quickstart covers the full Grounded loop:
- browser telemetry with
@grounded/analytics - backend traces with
@grounded/tracing - control-plane reads and jobs with
@grounded/client
Prerequisites
- Node.js 22+
- a running Grounded API, for example
http://localhost:3001 - an existing tenant
- an agent with at least one snapshot if you want direct traces to normalize into sessions
- API keys
1. Install The Packages
The SDK is implemented in the Grounded monorepo today. Public npm publishing is prepared but may not be live yet in your environment.
Inside the monorepo:
pnpm --filter @grounded/client build
pnpm --filter @grounded/tracing build
pnpm --filter @grounded/analytics buildThe intended public install shape is:
npm install @grounded/client @grounded/tracing @grounded/analytics2. Create Keys
- use a secret key for
@grounded/client - use a publishable key for
@grounded/tracing - use a publishable key for
@grounded/analytics
Example secret key scopes:
agents:readconnectors:writesessions:readinsights:readsnapshots:writejobs:readjobs:writeevals:readevals:write
Example publishable key scopes:
traces:write- optionally
traces:read
3. Initialize The SDKs
import { Grounded } from '@grounded/client';
import { GroundedTracing } from '@grounded/tracing';
import { init as initAnalytics } from '@grounded/analytics';
const grounded = new Grounded({
apiKey: process.env.GROUNDED_SECRET_KEY!,
baseUrl: process.env.GROUNDED_BASE_URL ?? 'http://localhost:3001',
});
const tracing = new GroundedTracing({
apiKey: process.env.GROUNDED_PUBLISHABLE_KEY!,
agentId: 'agt_support',
baseUrl: process.env.GROUNDED_BASE_URL ?? 'http://localhost:3001',
environment: 'production',
release: 'api-2026-03-09',
});
const analytics = initAnalytics({
apiKey: process.env.NEXT_PUBLIC_GROUNDED_PUBLISHABLE_KEY!,
agentId: 'agt_support',
baseUrl: process.env.NEXT_PUBLIC_GROUNDED_BASE_URL ?? 'http://localhost:3001',
mirror: { fullstory: window.FS },
});baseUrl can be either the Grounded origin or the origin plus /api.
4. Send Browser Telemetry
analytics.identify('user_123', { plan: 'pro' });
analytics.page();
analytics.track('checkout_started', { sku: 'pro-monthly' });
const ctx = analytics.getContext();getContext() is the primary handoff contract between browser telemetry and backend traces.
5. Send A Backend Trace
const trace = tracing.startTrace({
name: 'support.reply',
sessionId: ctx.sessionId,
anonymousId: ctx.anonymousId,
userId: ctx.userId,
resource: { snapshotId: 'snap_live' },
input: { message: 'where is my refund?' },
});
const retrieval = trace.startSpan({
name: 'policy.lookup',
kind: 'retrieval',
input: { source: 'faq' },
});
retrieval.recordEvent('cache_hit', { index: 'policy-cache' });
retrieval.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();
await analytics.flush();The tracing SDK now fails fast if it cannot link a trace into Grounded's session model. Every trace must resolve:
- an
agentId - and at least one stitch key
sessionId, oranonymousId, oruserIdplus non-emptycorrelationKeys
6. Read The Data Back
const traces = await grounded.traces.list({
agentId: 'agt_support',
sessionId: ctx.sessionId,
});
const sessions = await grounded.sessions.list({
agentId: 'agt_support',
q: 'refund',
});
const stats = await grounded.sessions.stats('agt_support');7. Sync A Connector
const connector = await grounded.connectors.create({
agentId: 'agt_support',
name: 'LangSmith prod',
category: 'llm-tracing',
provider: 'langsmith',
config: {
apiKey: process.env.LANGSMITH_API_KEY!,
projectName: 'support-prod',
},
});
await grounded.connectors.connect(connector.id);
const syncJob = await grounded.connectors.sync(connector.id, {
from: '2026-03-01T00:00:00.000Z',
to: '2026-03-06T00:00:00.000Z',
});
await grounded.jobs.wait(syncJob.id, {
timeoutMs: 10 * 60_000,
});8. Draft And Analyze A Snapshot
const draft = await grounded.snapshots.createDraft('agt_support', {
parentSnapshotId: 'snap_live',
systemPrompt: 'Be more explicit about refund timelines.',
});
await grounded.snapshots.commitDraft(
draft.id,
'Tighten refund messaging',
{
systemPrompt: 'Be more explicit about refund timelines and cite policy names.',
},
);
const analysisJob = await grounded.snapshots.runAnalysis(draft.id);
await grounded.jobs.wait(analysisJob.id);9. Run An Optimization Job
const optimizeJob = await grounded.jobs.create({
agentId: 'agt_support',
type: 'optimize-snapshot',
snapshotId: draft.id,
effort: 'medium',
topK: 3,
});
await grounded.jobs.wait(optimizeJob.id, {
timeoutMs: 20 * 60_000,
});
const summary = await grounded.jobs.summary(optimizeJob.id);