dashboard
@innernet/sdk — the typed client for the REST API.
2 pages

TypeScript SDK

@innernet/sdk is a zero-dependency typed client for the REST API. Node 18+, Bun, Deno, edge runtimes — anywhere fetch exists.

bash
npm install @innernet/sdk

quickstart#

ts
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#

ts
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#

ts
// 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#

ts
// 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.

ts
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:

ts
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
}