The SDK and agents
@thinkingroot/sdk is how developers consume ThinkingRoot in code. It is pure
@thinkingroot/sdk is how developers consume ThinkingRoot in code. It is pure
fetch — it runs in Node, Bun, Deno, edge runtimes, and the browser — with
429-retry, SSE streaming, and secure-by-default behavior.
Getting started
import { thinkingroot } from "@thinkingroot/sdk";
const tr = thinkingroot({ gatewayUrl: "https://api.thinkingroot.com", projectKey: "tr_sk_..." });
// A shared project brain, or a per-end-user isolated namespace:
const brain = tr.brain("main"); // shared workspace
const userBrain = tr.scope("user_123"); // per-user, fail-closed isolationThe projectKey must be a tr_sk_… key. .scope(userId) routes to a per-user
workspace that is isolated at the engine boundary — cross-user access is unreachable.
Layer 1 — primitives (1:1 with the engine)
memory—recall,store,capsulebranch—fork,merge,diff,rollback,checkout,lineagefn—deploy,invoke,runsroute— capability routerprompt—put,versions,assembleask/compile— streamingsources
const { answer, citations } = await brain.ask("what changed in the pricing model?");
await brain.memory.store("Pricing v2 launches 2026-07-01.");Layer 2 — agent ergonomics
brain.agent(name, { recall, persona })— an agent backed by the brain's memory.brain.crew([...])— multiple agents that share one brain.brain.flow([...])— a sequential or dynamically-routed pipeline; each run gets its own branch.brain.operator().solve(task)— a self-extending operator that reuses or forges a capability to solve a task.
const agent = brain.agent("researcher", {
recall: true,
persona: "You answer with citations and never guess.",
});
const out = await agent.run("Summarize what we know about the billing service.");The spine — self-extension
brain.forge({ name, description, tests, draftBody })— author (via LLM) → deploy a versioned function → verify by invoking against tests → keep or roll back. Every verify-invoke seeds the capability router.brain.acquire(task)— just-in-time: route to an existing capability, or forge a new one if none fits.
await brain.forge({
name: "slugify",
description: "Convert a title to a URL slug",
tests: [{ input: "Hello World", expect: "hello-world" }],
});
const slug = await brain.fn.invoke("slugify", "My New Post");This is the self-compounding loop: capabilities are self-authored, verified before they're kept, and the router learns which capability serves which input — so the backend gets more capable the more it's used.
Engine-native counterpart
Everything above has an in-engine equivalent: inside a Root Function, ctx.acquire,
ctx.memory, ctx.branch, ctx.prompt, and ctx.mcp.call give you the same powers
without the SDK round-trip — co-located with the graph.