Client SDK
The @tarski/client TypeScript SDK — append observations, run queries, subscribe to live results, and drive typed sessions against local serve or Tarski Cloud.
@tarski/client is the publishable TypeScript SDK for the Tarski API: append
observations, run declared and ad-hoc worldview queries, subscribe to typed event
streams, and drive typed agent sessions — against local tarski serve or Tarski Cloud —
without hand-rolling HTTP. ESM with bundled types, Node 18+ or browser bundlers, zero
runtime dependencies.
The SDK is a client of existing contracts only: it never derives facts, ordering, or authorization locally. Its request/response types and validators are generated from the platform’s own contract inventory, and every build embeds its contract identity — a changed contract cannot ship without a version bump.
Getting started
import { createTarskiClient } from '@tarski/client';
const client = createTarskiClient({
baseUrl: 'http://127.0.0.1:7411', // local tarski serve, or your cloud runtime
token: () => readTokenSomewhere(), // in-memory bearer; string or provider fn
});
const caps = await client.discoverCapabilities();
Capability discovery reports typed unavailable states, so unsupported operations against older runtimes fail understandably instead of mysteriously.
Three auth options, mutually exclusive where it matters:
token— an in-memory bearer (string or function). The SDK has no persistence.endUserToken— a per-request supplier of your app’s rotating IdP tokens, re-read on every request; verified at ingress and minted into actor context server-side. See Identity & tenancy.localDevActorContext— local-serve-only fixture headers; fails closed with a typed error against any other authority.
Appending observations
await client.appendObservation({
lineage: 'main',
kind: 'booking.request',
payload: { slot: '2026-07-23T10:00Z', customer: 'c_42' },
idempotencyKey: 'booking.request:c_42:2026-07-23T10:00Z',
});
Single append supports idempotent retry — conflicting reuse of an idempotency key is a typed failure. Write-policy denials come back as typed diagnostics.
Queries
const page = await client.executeDeclaredQuery('booking-status', {
bindings: { date: '2026-07-23' },
});
page.rows; // canonical rows, stable order
page.resultDigest; // byte-stable for this query at this head
page.cursor; // deterministic continuation at a pinned head
Responses mirror the canonical envelope — query, binding, and result digests, snapshot
and projection identity — so a result is checkable evidence, not just data.
executeAdhocQuery covers scope-gated ad-hoc reads.
Live subscriptions
subscribeQuery keeps a declared query current (see
Reactive queries). subscribeLineageEvents and
subscribeSessionEvents are typed async-iterable SSE streams with cursor persistence and
reconnect. When a resume window is exceeded, the iterator yields an explicit typed
rehydrate item carrying the recovery head — the SDK never fabricates missed events; you
rebuild visible state from queries.
Sessions
Typed agent-session lifecycle: create-or-start (idempotent, with typed
session_start.idempotency_conflict), preview, message, and reads for catalog, auth
state, lifecycle, transcript, timeline, and provenance.
Error handling
One failure surface: TarskiApiError, keyed on stable codes with contracted
retryability:
try {
await client.appendObservation(/* … */);
} catch (e) {
if (e instanceof TarskiApiError) {
e.code; // e.g. 'observation.write_policy_denied'
e.retryability; // 'retryable' | 'non_retryable' | 'rehydrate_required'
e.retryAfterMs; // pacing, when the server supplies it
}
}
Unknown future codes pass through marked uncontracted; SDK-minted configuration errors
use a distinct sdk.* code space.
Quality you can rely on
The published package build is driven against a real spawned tarski serve by a
conformance suite — idempotent retries, policy denials, cursor and digest assertions, SSE
reconnect ordering, forced rehydrates, session lifecycle — plus a cloud variant asserting
local/hosted parity on typed codes and result digests. The Team Tasks reference app
consumes the SDK as a real dependency, full React frontend included. See
Examples.