Unit 11 of 22 · Intermediate

Build kestrel into your app (SDK)

The short version

This is a builder practicum: it wires the TypeScript SDK into your own agent or app, end to end. You install the kestrel.markets package, create one typed client over the managed API, and drive the same seven operations the HTTP face exposes — browse the catalog, validate a document, open and run a session, read the sealed Blotter, grade it, land on a certified proof URL, and resume the same durable Operation later. The SDK mirrors the wire one-to-one: the same operation IDs, events, and receipts, with no SDK-only shortcuts, so nothing you learn here is a convenience that the protocol lacks. The reference docs remain the API truth; this unit is the walkthrough that connects them into a working flow. By the end you have a client that runs a free simulation from inside your app and hands your user a re-verifiable proof URL, with no signup in the loop.

What you are building

A small piece of your own app that runs a kestrel simulation over the managed API and lands on a certified proof URL — the same object the CLI and MCP faces produce, reached from TypeScript. The SDK is a thin projection of the canonical HTTP surface: one typed client, the same operations, the same receipts.

This is a practicum. Read the four faces for the contract and evidence for what a proof URL contains; those pages are the API truth. Here we wire them together.

Install and create one client

The package ships a light, HTTP-only SDK entry. Install it, then build one client over the managed API:

npm i kestrel.markets
import { createSdk, remoteTransport } from 'kestrel.markets/sdk/remote';

// One typed client over the canonical HTTP face. No key needed for the free path.
const kestrel = createSdk(
  remoteTransport({ baseUrl: 'https://api.kestrel.markets' }),
);

remoteTransport binds the managed API; createSdk returns the one typed client. The same client object shape works over the local runtime too — only the transport changes — which is exactly the "equal projections" invariant made concrete.

Run a session and land on a proof URL

The flow mirrors the wire one-to-one. Browse the catalog for a free scenario, validate your document, open a session, drive it to settlement, seal it, and grade the sealed Blotter:

// browse → pick a free catalog scenario
const catalog = await kestrel.catalog();
const scenario = catalog.find((c) => c.free);

// check → validate the Kestrel document (fail-closed; costs nothing)
await kestrel.validate(source);

// run → open a session over that scenario and drive it to settlement
const session = await kestrel.openSession({ kind: 'catalog', id: scenario.id }, source);
let turn = await session.start();
while (turn.next) {
  // your agent authors a decision here, or stands down; see the reference for
  // the AuthoredResponse shape and the streamed events on each turn.
  turn = await session.advance(standDown);
}

// seal → the deterministic Blotter + conformance root + artifacts
const sealed = await session.finalize();

// score → grade the sealed Blotter (a Blotter's sessionId is its artifact id)
const grade = await kestrel.grade({ blotters: [sealed.blotter.session.sessionId] });

The grade carries the certified artifact your user re-verifies. Its proof URL is https://kestrel.markets/proof/<grade-artifact-id> — the same public, anonymous, read-only receipt every other face produces. Hand that link to your user and they can re-verify the signature in a browser without any account.

Resume the same Operation later

A run is a durable Operation. Resume it by ID — from a later request, a different process, or another face entirely — and re-derive its tail from a cursor:

const resumed = await kestrel.resumeOperation({ operationId });

That is the portability guarantee in code: your app and an agent over MCP can hold the same Operation.

The free path, and the paid boundary

The SDK covers the free anonymous path end to end: catalog, validate, session, grade, artifact, and Operation resume. When a call reaches a paid boundary it returns a gated result carrying a signed Offer rather than silently proceeding — the same 402 continuation the other faces surface. Settling that Offer needs a signer; the free simulation-and-proof path above needs none.

See it in kestrel

Before you wire it, watch the exact same run happen from the CLI face over a generic index scenario — free, anonymous, no card:

npx kestrel.markets sim fomc-rate-decision-whipsaw

The proof URL it prints is the identical object your SDK code produces. Recompute one byte for byte to see the receipt is real, not the server's word:

npx kestrel.markets certify https://kestrel.markets/proof/art_d29415f0cf502f4a218a9cba

Keep the capability one command away: drop the kestrel.markets MCP server into your client so the next session opens where your app left off, no account in between.

Recompute it

Every claim in this unit recomputes from a certified proof — no account, no card.

/proof/art_d29415f0cf502f4a218a9cba
Keep readingWhat happened vs how good it was