TypeScript SDK
@innernet/sdk is a zero-dependency typed client for the REST API. Node 18+, Bun, Deno, edge runtimes — anywhere fetch exists.
npm install @innernet/sdkquickstart#
import { Innernet } from '@innernet/sdk'
const innernet = new Innernet({ apiKey: process.env.INNERNET_API_KEY! })
// remember something about one of your users
await innernet.memories.add({
content: 'Prefers concise answers; works in TypeScript.',
userId: 'user_42',
tags: ['preference'],
})
// recall before responding
const { memories } = await innernet.memories.list({ userId: 'user_42', limit: 20 })
// search the whole graph — context maps AND memories
const { results } = await innernet.search('pricing decision')context maps#
const { projects } = await innernet.projects.list()
const map = await innernet.projects.get('my-product')
const dim = await innernet.dimensions.get('my-product', 'roadmap')
await innernet.dimensions.put('my-product', 'roadmap', {
content: '# Roadmap\n\n- ship v1',
commitMessage: 'trim roadmap',
})
await innernet.captures.create('my-product', {
content: 'Decided: usage-based pricing.',
tags: ['decision'],
})versioning — branches and commits#
// fork, work, diff, merge — git for thinking, typed
await innernet.branches.create('my-product', {
name: 'pricing-experiment',
summary: 'what if usage-based?',
})
await innernet.branches.putDimension('my-product', 'pricing-experiment', 'pricing', {
content: '# Pricing\n\nUsage-based, $0.005/1k ops.',
})
const { diff } = await innernet.branches.diff('my-product', 'pricing-experiment')
// { dimensions: { added: [], modified: ['pricing'], … }, nodes: { … } }
await innernet.branches.merge('my-product', 'pricing-experiment') // branch wins
// …or shelve it instead: await innernet.branches.park('my-product', 'pricing-experiment')
const { commits } = await innernet.commits.list('my-product')personal memory#
// disclosure-gated — private never crosses the API
const { facts } = await innernet.self.facts({ maxDisclosure: 'work' })
await innernet.self.capture({
content: 'Prefers dark mode everywhere.',
dimensionHint: 'preferences',
})
// load a project WITH the owner's context attached
const map = await innernet.projects.get('my-product', { includeSelf: true })errors#
Every non-2xx throws InnernetApiError with .status, .code, and .message; 429s carry .retryAfter (seconds). Idempotent GETs retry once automatically on 429/5xx.
import { InnernetApiError } from '@innernet/sdk'
try {
await innernet.projects.get('nope')
} catch (err) {
if (err instanceof InnernetApiError && err.status === 404) {
// create it, or move on
}
}in an agent loop#
The pattern that makes agents feel continuous — recall → act → remember:
async function answer(userId: string, question: string) {
const { memories } = await innernet.memories.list({ userId, limit: 20 })
const reply = await llm.complete({
system: `What you know about this user:\n${memories.map(m => '- ' + m.content).join('\n')}`,
user: question,
})
await innernet.memories.add({ content: `Asked about: ${question}`, userId, runId: crypto.randomUUID() })
return reply
}