Skip to main content

SDK

@toda/sdk is the TypeScript client for the core HTTP API.

bun add @toda/sdk @toda/llm

Client

import { Toda } from "@toda/sdk";
import { ClaudeMemoryProvider } from "@toda/llm";

const toda = new Toda({
apiUrl: process.env.TODA_API_URL!,
apiKey: process.env.TODA_API_KEY!,
memoryProvider: new ClaudeMemoryProvider(),
});
OptionRequiredPurpose
apiUrlYesCore API URL
apiKeyYestoda_ API key
memoryProviderNoEnables ingest()
fetchNoCustom transport

The client is stateless and holds no key other than the API key.

Memory loop

const context = await toda.recallForPrompt(userTurn);
const reply = await model.generate({ context, userTurn });
await toda.ingest(`User: ${userTurn}\nAssistant: ${reply}`);

Writing

remember(content, metadata?)

Stores one memory and returns before anchoring completes.

const receipt = await toda.remember(
"Deployments run on Fridays.",
{ kind: "preference" },
);

Metadata is not encrypted.

ingest(conversation)

Uses the configured memory provider to extract and store durable facts.

const receipts = await toda.ingest(
"User: Deployments run on Fridays.\nAssistant: Noted.",
);

Existing memories are provided to the extractor for deduplication. The method returns [] when no memory is extracted.

Reading

recall(query)

Returns memories containing a case-insensitive substring match. An empty query returns the full log.

const hits = await toda.recall("deployment");

recallForPrompt(query, limit = 10)

Formats up to limit matching memories as prompt context. Returns an empty string when no memory matches.

Proofs

getProof(id)

const bundle = await toda.getProof(id);
// { proof, batchRoot, txSignature, onchainRoot }

verify(id)

const valid = await toda.verify(id);

verify() checks the inclusion proof and compares the batch root with the root returned by the API.

For independent verification, fetch the commitment account from a separate Solana RPC:

const bundle = await toda.getProof(id);
const tip = await readUserCommit(connection, ownerPubkey);

const sound = verifyProof(bundle.proof, hexToBytes(bundle.batchRoot));
const landed = bytesToHex(tip.merkleRoot) === bundle.batchRoot;

A batch root older than the current tip requires reconstruction of the current rolling root. See Verifying a memory.

Staking

getStakeStatus()

const status = await toda.getStakeStatus();

The method returns live: false while staking is not configured.

Memory providers

interface MemoryProvider {
extract(input: {
conversation: string;
existing?: string[];
}): Promise<ExtractedMemory[]>;
}

@toda/llm includes ClaudeMemoryProvider. A provider should return atomic, self-contained facts and omit transient or duplicate information.

Custom providers implement the same interface.

Errors

Methods throw on non-2xx responses. The SDK does not include retries or backoff.

new Toda({ apiUrl, apiKey, fetch: fetchWithRetry });

Types

Request and response schemas are defined in @toda/types. The SDK re-exports the public types.