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(),
});
| Option | Required | Purpose |
|---|---|---|
apiUrl | Yes | Core API URL |
apiKey | Yes | toda_ API key |
memoryProvider | No | Enables ingest() |
fetch | No | Custom 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.