INITE Brain — memory with context

INITE Brain

Open-source memory for AI agents: a bitemporal knowledge graph with provenance, over MCP and REST.

CI Latest release License: AGPL-3.0-or-later Docker pulls Image: arm64 | amd64 Stars PRs welcome MCP native

Install in Claude Code Add to Cursor Add to VS Code MCP Registry

Website · Quick start · Architecture · Domain Packs · Getting started · Docs · Agent guide

## Quick start Needs Docker with Compose v2, `openssl`, and an OpenAI API key (the default model configuration). Runs the released image (`linux/amd64` and `linux/arm64`) with SurrealDB; no clone, no build. ```bash : "${OPENAI_API_KEY:?export OPENAI_API_KEY first}" mkdir inite-brain && cd inite-brain curl -fsSLO https://raw.githubusercontent.com/inite-ai/inite-brain-service/main/docker-compose.quickstart.yml BRAIN_KEY="brain_$(openssl rand -hex 24)" KEY_HASH="$(printf %s "$BRAIN_KEY" | openssl dgst -sha256 -r | cut -d' ' -f1)" cat > .env <conversations · documents · facts"] raw[("Source records
documents · episodes · evidence")] derive["Indexers and scene builders
candidates · entity resolution · conflicts"] memory[("Connected memory on SurrealDB
facts + graph · scenes · beliefs")] retrieve["Retrieval
semantic + lexical · graph · multi-hop"] answer["Synthesis + verification
answer with citations or abstention"] packs["Domain Packs
vocabulary · memoryModel · tools"] media["Evidence registration / upload
scan hook · trusted processors"] input --> raw input --> derive media --> raw raw --> derive derive --> memory memory --> retrieve raw --> retrieve retrieve --> answer packs -. "domain configuration" .-> derive packs -. "capabilities and consent" .-> media ``` | Memory layer | What it preserves | | --- | --- | | **Facts and entities** | Typed claims, canonical entities, relationships, confidence, source attribution and temporal history. | | **Episodes** | Source turns and conversation context that derived memory can point back to or be rebuilt from. | | **Scenes** | Bounded events with gists, entities, state changes and source links. Optional gist embeddings and a scene retrieval lane make them searchable alongside other evidence. | | **Beliefs** | Derived state with revision history and supporting scenes. Pack-projected state deltas can feed belief promotion. | | **Evidence** | Assets, located fragments, processing runs and derived representations, with links to the memories they support. | **Rebuildable memory.** Derived worlds can be rebuilt from retained episodes in a staging version. Readers stay pinned to the previous world until promotion. Scene maintenance can process dirty conversations on a schedule, with budgets, leases and metrics; it can compose scenes and promote supported beliefs. **Configurable retrieval.** Retrieval profiles select mechanisms for the corpus and question. Semantic and lexical search, graph expansion, reranking, raw passages, scene retrieval and belief retrieval are distinct capabilities. A known entity can enter through `graph_retrieve`; a question spanning relationships can use `search_multi_hop`. **Separate serving and background work.** The NestJS service uses a SurrealDB-backed job queue, leases and worker-thread offloads. Run the image as one process or split `PROCESS_ROLE=api|worker`; see the [operations guide](docs/operations.md#splitting-api-and-worker-roles). The code includes capabilities that are **opt-in**, not a promise that every installation runs every layer. Scene construction, scene serving, belief promotion, evidence upload/processing and pack projections have separate gates. Check the [architecture](docs/architecture.md), [operations](docs/operations.md) and flag definitions for [scenes](src/common/scene-flags.ts), [evidence](src/common/evidence-flags.ts) and [pack projections](src/common/pack-projection-flags.ts) when enabling them. ## Domain Packs A pack is a versioned JSON manifest installed per tenant. It tells the engine how to interpret a domain's material. Pack-derived observations remain candidates for the core pipeline to validate and resolve. | A pack can declare | Purpose | | --- | --- | | `predicates` | Typed vocabulary, value constraints, conflict semantics, decay and PII classes. | | `extractionProfile`, `evalFixtures` | Domain instructions, examples and extraction checks. | | `memoryModel` | Scene schemas, state models and transitions, attention hints, verification rules and advisory retention hints. Also declares supported modalities, requested processor capabilities and raw-evidence policy. | | `indexer`, `seedDocuments` | Participation in document indexing and knowledge supplied with the pack. | | `mcpTools` | Additional agent tools, subject to explicit operator consent. | The [industry pack library](packs) includes: | Pack | Example memory models | | --- | --- | | [`real_estate`](packs/real-estate.pack.json) | Listings, tenancies and permits. | | [`fintech`](packs/fintech.pack.json) | Licenses and certifications. | | [`medical`](packs/medical.pack.json) | Drug ontology, prescription and approval lifecycles. | | [`legal`](packs/legal.pack.json) | Agreements, obligations and legal matters. | | [`insurance`](packs/insurance.pack.json) | Policy and claim lifecycles. | | [`hr`](packs/hr.pack.json) | Positions and employee lifecycles. | For example, `real_estate` declares the listing path `listed → under_offer → sold`, as well as withdrawal and return-to-market transitions. It distinguishes viewing and closing scenes, with an ephemeral retention hint for a viewing and a durable hint for a closing. The built-in [`code_memory`](src/ai/domain-packs/code-memory.pack.ts) pack covers engineering decisions, rationale, invariants, gotchas and change lifecycles. Use `record_decision`, `why` and `recall_decisions` to retain the reasons behind the code. The six industry packs are distributable; built-in code memory is part of the core seed. **Author and distribute.** Scaffold with `pnpm pack:init my_pack`, validate, optionally sign, publish to a registry and install per tenant. Registry versions are immutable, installs are checksum-pinned, and signature requirements follow the server's trust policy. Registry and marketplace support discovery, publisher profiles, mirroring and optional billing. **Consent is part of installation.** The current first-party industry packs declare media capabilities, so installing them requires reviewing that section and passing `--accept-modalities`. This authorizes the declared capabilities; it does not supply a missing processor or enable every server feature. Pack MCP tools have a separate consent path. Built-in `code_memory` media declarations also do not, by themselves, activate media processing. Full authoring, signing and installation commands: [Domain Packs standard](docs/domain-packs.md) · [MCP pack tools](docs/mcp-pack-tools.md) · [pack evaluation](test/eval/domain-packs/README.md). ## Getting started ### Use the hosted service Hosted brain is provisioned per company: a tenant (`companyId`) and scoped API keys. Sign in and issue one on the [keys screen](https://brain.inite.ai/en/app/keys) — it shows the key once, alongside ready-to-paste configuration for Claude Code, Claude Desktop, Cursor, VS Code, Codex CLI and Goose. If your workspace has not been provisioned yet, ask at `info@inite.ai`. ```bash export BRAIN_URL="https://brain.inite.ai" export BRAIN_KEY="brain_YOUR_API_KEY" ``` Keys can also be issued over the API by any credential you already hold — `POST /v1/keys` mints one no wider than the caller's own scopes, and `POST /v1/keys/{id}/revoke` takes it back. The same endpoints work on a self-hosted deployment, so the env-var key below is only ever a bootstrap. ### Run from source Prerequisites: **Node.js 22**, **pnpm 10** and **Docker Compose**. The default model configuration needs an OpenAI API key. Local embeddings and alternative model providers are configuration choices; see [operations](docs/operations.md). ```bash git clone https://github.com/inite-ai/inite-brain-service.git cd inite-brain-service pnpm install --frozen-lockfile cp .env.example .env # Set OPENAI_API_KEY in .env for the default model configuration. ``` Create a local read/write key. This appends a generated key and its registration to your development `.env`; Brain authenticates against the SHA-256 hash. ```bash node <<'JS' const { randomBytes, createHash } = require('node:crypto'); const { appendFileSync } = require('node:fs'); const key = 'brain_' + randomBytes(24).toString('hex'); const keys = [{ keyHash: 'sha256:' + createHash('sha256').update(key).digest('hex'), companyId: 'co_demo', scopes: ['brain:read', 'brain:write'], }]; appendFileSync('.env', '\nBRAIN_KEY=' + key + '\nBRAIN_API_KEYS=' + JSON.stringify(keys) + '\n'); JS docker compose up -d surrealdb pnpm start:dev ``` In a second terminal, from the same directory: ```bash export BRAIN_URL="http://localhost:3000" export BRAIN_KEY="$(node --env-file=.env -p 'process.env.BRAIN_KEY')" curl --fail-with-body "$BRAIN_URL/health" ``` For the full container setup, use `docker compose --env-file .env up -d --build` instead of `pnpm start:dev`. The app service publishes no host port — that is what lets `--scale brain=N` run several replicas — so copy `docker-compose.override.yml.example` to `docker-compose.override.yml` first; it maps host **3030**, and `BRAIN_URL=http://localhost:3030` then works for the requests below. The Compose defaults are for local development; production credentials and topology are covered in [deployment](docs/DEPLOY.md). ### Remember something, then ask about it Text in, facts out. Brain captures the turn, extracts entities and claims, and runs each one through bitemporal conflict resolution: ```bash curl --fail-with-body -X POST "$BRAIN_URL/v1/ingest/mention" \ -H "Authorization: Bearer $BRAIN_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Maria moved to Berlin in June and prefers morning appointments.", "userId": "user_42" }' curl --fail-with-body -X POST "$BRAIN_URL/v1/search" \ -H "Authorization: Bearer $BRAIN_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "where does Maria live", "userId": "user_42", "limit": 5 }' ``` Use your application's stable user ID on **both** writes and reads. Omit `userId` on both only for tenant-global memory. The `userId` is also who is speaking: a first-person turn ("I moved to Berlin") lands on the user's own entity, and "where do I live?" on `/v1/synthesize` is answered to them. The memory learns the user's name from them — "I'm Maria" becomes a `name` fact on their own entity — or from your onboarding write: `/v1/ingest/fact` with `entityRef: { "vertical": "user", "id": "user_42" }`, `predicate: "name"`, the same `userId`. (A speaker anchor `{ "vertical": "user", "id": "user_42", "role": "speaker", "name": "Maria" }` on a mention names them too.) To relay someone else's words under the user's scope, anchor that person as the speaker instead. Until a name is learned, `workspace_status` and `/v1/users/:userId/profile` say so — ask once, record it. ### Record a fact you already know When the claim is already structured — a CRM field changed, an event fired — skip the extractor and state it. The response says what the resolver *decided* (`INSERTED`, `SUPERSEDED`, `COMPETING`…), not just that the write happened: ```bash curl --fail-with-body -X POST "$BRAIN_URL/v1/ingest/fact" \ -H "Authorization: Bearer $BRAIN_KEY" \ -H "Content-Type: application/json" \ -d '{ "entityRef": { "vertical": "rent", "id": "cust_42" }, "predicate": "complained_about", "object": "late maintenance", "validFrom": "2026-09-01T10:00:00Z", "userId": "user_42", "source": { "vertical": "rent", "messageId": "msg_1" } }' ``` The local key above has no administrative scope; pack installation and forgetting require an appropriately scoped operator key. More: [getting started](docs/getting-started.md). ## Connect an agent ### Claude Code — one command ```bash /plugin marketplace add inite-ai/inite-brain-service /plugin install inite-brain@inite ``` That installs the MCP server, the six skills, and the lifecycle hooks together: `SessionStart` injects what Brain already knows about the repo you are in, `PreCompact` and `SessionEnd` write the session back. Claude Code prompts for your API key at enable time and keeps it in the OS keychain. Details and switches: [plugin README](plugins/inite-brain/README.md). Prefer to wire it by hand? ```bash claude mcp add --transport http brain https://brain.inite.ai/mcp \ --header "Authorization: Bearer $BRAIN_KEY" ``` ### Gemini CLI — one command ```bash export BRAIN_API_KEY="brain_..." gemini extensions install https://github.com/inite-ai/inite-brain-service ``` MCP server, the six skills, and the [agent memory guide](docs/agents-using-brain.md) loaded as context. The key stays in your environment — the manifest references `${BRAIN_API_KEY}` and Gemini expands it at connect time. ### Cursor and VS Code — one click Those two publish an install URL scheme, so the badges at the top of this file do the work; replace the placeholder key in the client's own MCP settings afterwards. Every other client takes the URL `https://brain.inite.ai/mcp` (or `?tools=chatgpt` for ChatGPT, whose connector contract is exactly `search` + `fetch`). ### Every other harness ```bash curl -fsSL https://brain.inite.ai/install.sh | sh ``` Installs the skills into every agent it finds on the machine — Claude Code, Codex CLI, Gemini CLI, openclaw, opencode — and takes `--target cursor,agents --scope project` for the project-local ones. `SKILL.md` is a cross-agent format, so the same six skills work unchanged everywhere. For clients that launch a stdio MCP server, use the first-party [`@inite/brain-mcp`](clients/brain-mcp/README.md) connector. This configuration fits clients with a `mcpServers` map, including Claude Desktop: ```json { "mcpServers": { "brain": { "command": "npx", "args": ["-y", "@inite/brain-mcp"], "env": { "BRAIN_API_KEY": "brain_YOUR_API_KEY", "BRAIN_COMPANY_ID": "YOUR_COMPANY_ID" } } } } ``` For the local setup, use company ID `co_demo`, the key from `.env`, and add `"BRAIN_BASE_URL": "http://localhost:3000"` to `env` (port `3030` for Compose). Node.js and `npx` must be available to the client. Clients with native remote MCP support can connect directly over **Streamable HTTP**: ```text URL: https://brain.inite.ai/mcp (tenant taken from the credential) https://brain.inite.ai/mcp/ (explicit, must match the key) Authorization: Bearer brain_ ``` Both spellings serve the same endpoint. Use the tenant-less one when the client only knows a URL — that is every OAuth-discovered connector, where the tenant arrives in the token's `org` claim rather than from the person pasting the config. An unauthenticated probe answers at `/mcp/health` (and `/mcp//health`), so a setup script can check reachability before any credential exists. The key's scopes determine available tools; server flags and installed packs can extend the surface. The connector forwards tools and resources, and bridges MCP sampling when the client supports it. See the [per-client setup guide](https://brain.inite.ai/en/docs/mcp/setup). | Agent task | Start with | | --- | --- | | Find relevant memory | `search_knowledge`, `graph_retrieve`, `search_multi_hop` | | Answer with citations | `synthesize` | | Resume after a gap | `memory_diff`, `get_entity_timeline` | | Record information | `record_fact` for one claim; `ingest_document` for longer material | | Inspect disagreement | `detect_contradiction`, `get_competing_facts` | | Remember engineering rationale | `record_decision`, `why`, `recall_decisions` | | Find out what you just connected to | `workspace_status` | Read the [agent memory guide](docs/agents-using-brain.md) for memory semantics and the [skills guide](skills/README.md) for reusable agent workflows. Synthesis keeps fact references in `citations` and other evidence references (episodes, fragments, scenes and beliefs) in `evidenceCitations`; preserve both when presenting an answer. ## Build with the SDK ```bash npm install @inite/brain ``` ```ts import { createBrain, brainTools } from '@inite/brain' const brain = createBrain({ apiKey: process.env.BRAIN_KEY!, userId: 'user_42' }) await brain.remember('Maria moved to Berlin in June.') const { answer, citations } = await brain.answer('where does Maria live') ``` `brainTools(brain)` returns tool definitions the Vercel AI SDK takes directly, and `createBrainStore(brain)` is a LangGraph-shaped store over the same memory. One dependency (zod), no framework required: [`@inite/brain`](clients/brain-sdk/README.md). Using Anthropic's memory tool (`memory_20250818`)? Swap the filesystem backend for a tenant-fenced service without touching your agent loop: [`@inite/brain-memory-tool`](clients/brain-memory-tool/README.md). ## Feed it documents Enable `DOCUMENT_INGEST_ENABLED=1` on the server. Submit normalized text through **Source → Indexer → Candidates → Brain**: ```bash curl --fail-with-body -X POST "$BRAIN_URL/v1/ingest/document" \ -H "Authorization: Bearer $BRAIN_KEY" \ -H "Content-Type: application/json" \ -d '{ "kind": "markdown", "title": "Acme maintenance review", "text": "Customer cust_42 reported late maintenance. The team agreed to review response times next week.", "occurredAt": "2026-09-01T10:00:00Z", "userId": "user_42", "contextRef": { "vertical": "rent" } }' ``` Indexers stage candidates before the core resolves and commits facts. Stored content can be re-indexed after installing a new pack; external indexers can join over a pull work API. `storeContent: false` disables content retention for that document, so later re-indexing cannot reuse its text. [Document pipeline](docs/document-pipeline.md) · [External indexers](docs/indexer-protocol.md). Or let the brain **read** what already exists: a folder, a bucket, a site, an MCP server — install a source pack (`file_memory`, `web_memory`), connect a source in **Admin → Connections**, sync; every fact carries the file's revision. For what lives on a laptop, a CI runner or a box on the LAN, the [`@inite/brain-agent`](clients/brain-agent/README.md) walks it there — folders, a repository's committed docs, a local MCP server — and the brain keeps the books. [Source plane](docs/source-plane.md). ## Files and evidence The evidence plane supports metadata/reference registration through `POST /v1/ingest/evidence-asset` and multipart blob upload through `POST /v1/ingest/evidence-blob`. Uploaded assets pass a scan hook and can be dispatched to trusted processors; outputs are derived representations, with fragment locators where supplied by the processor. Current adapters include local image metadata decoding, PDF text-layer extraction and plain-text extraction. **Image metadata is not visual scene understanding; PDF text extraction is not OCR.** A modality declared by a pack is a capability request, not proof that a corresponding audio, video or vision processor is installed. These paths require their evidence gates, storage configuration and applicable pack consent. Raw serving additionally checks scope and PII policy. [Evidence contracts](src/contracts/evidence) · [Evidence configuration](src/common/evidence-flags.ts) · [Processor adapters](src/evidence/processing/adapters). ## Build on Brain - **Extend the domain:** [author a pack](docs/domain-packs.md), publish to the registry and install a reviewed version per tenant. - **Connect an indexer:** use the [pull protocol](docs/indexer-protocol.md) and [reference client](examples/reference-indexer.ts). - **Extend the agent:** declare [pack MCP tools](docs/mcp-pack-tools.md), with separate consent for the added tool surface. - **Inspect the API:** [OpenAPI 3.1](docs/openapi.json) is generated with `pnpm openapi:build` from the platform contracts. ## Quality and evaluation Retrieval, answer accuracy and state-transition correctness measure different things. Published scores belong to a particular dataset, reader model, retrieval profile, token budget and code revision; they are not a general accuracy guarantee for the running service. | Evaluation | What it probes | | --- | --- | | LoCoMo | Representation quality when the source conversation fits in context. | | LongMemEval | Recall and reasoning over longer conversation histories. | | BEAM | How quality changes as history scales. | | Memory fitness and state transitions | Mechanical, judge-free checks of memory behavior and lifecycle changes. | | Domain-pack and code-memory batteries | Domain extraction, entity identity, state and engineering-memory scenarios. | Conversational-memory results use a **strict binary judge, our own full-context baseline, paired statistics and a held-out split**. Read the [evaluation protocol](docs/eval-protocol.md) and [methodology](docs/eval-methodology.md) alongside any reported number; scores published under different protocols are not directly comparable. **CI:** PRs run lint, formatting, type checking, builds, unit tests with coverage, socket and integration tests, plus frontend checks and supply-chain checks. The real-LLM quality eval runs **nightly or by manual dispatch**, not on every PR. The workflow is the source of truth: [`.github/workflows/ci.yml`](.github/workflows/ci.yml). Battery guides: [memory fitness](test/eval/memory-fitness/README.md) · [state transitions](test/eval/state-transitions/README.md) · [domain packs](test/eval/domain-packs/README.md) · [code memory](test/eval/code-memory/README.md). ## Stack Node.js 22 · NestJS · TypeScript · SurrealDB 3.x · configurable embedding and LLM providers · local BGE-M3 option · configurable reranking · SurrealDB-backed jobs and leases · worker threads · OpenTelemetry. The web app and docs use Next.js, React and Tailwind CSS. ## Documentation [Documentation hub](docs/README.md) · [Web docs, EN/RU](https://brain.inite.ai/en/docs) | Task | Read | | --- | --- | | Integrate | [Getting started](docs/getting-started.md), [API](docs/api.md), [MCP agent guide](docs/agents-using-brain.md) | | Understand memory | [Architecture](docs/architecture.md), [Data model](docs/data-model.md), [Bitemporal semantics](docs/bitemporal-semantics.md), [Retrieval profiles](docs/architecture-manifest.md) | | Inspect provenance and access | [Fact provenance](docs/fact-provenance-api.md), [User profiles](docs/user-profile-api.md), [Source trust](docs/source-reputation.md), [ABAC](docs/abac.md) | | Extend | [Domain Packs](docs/domain-packs.md), [Document pipeline](docs/document-pipeline.md), [MCP pack tools](docs/mcp-pack-tools.md) | | Operate | [Operations](docs/operations.md), [Operator playbook](docs/operator-playbook.md), [Deployment](docs/DEPLOY.md) | | Evaluate | [Protocol](docs/eval-protocol.md), [Methodology](docs/eval-methodology.md), [Harness](docs/eval.md) | ## Contributing ### Contribute with an AI agent [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/inite-ai/inite-brain-service) You don't need to be an engineer. Open the repo (Codespaces above gives a ready environment with SurrealDB running), start your coding agent and describe the idea in plain words: - **Claude Code:** `/contribute` — it restates the idea, writes a short spec, builds it with tests, runs the gates and opens a PR. `/spec-idea` only files the idea as an issue. - **Any other agent** (Cursor, Codex, Copilot, Gemini CLI, Windsurf…): "Read AGENTS.md and help me add …". [AGENTS.md](AGENTS.md) is the source of truth for agents: commands, zones (what is safe to change and what needs a maintainer first) and the idea → PR loop. Prefer to just propose? Use the [Product idea](https://github.com/inite-ai/inite-brain-service/issues/new?template=product-idea.yml) form. ### The workflow See [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community guidelines. ```bash pnpm lint:ci pnpm format:check pnpm typecheck pnpm build pnpm test pnpm test:socket # Integration suites require Docker: pnpm test:e2e pnpm test:e2e:jobs ``` Choose additional evals for the behavior you change; real-model runs require provider credentials. Database changes belong in new numbered migrations in `src/db/migrations/`. For vulnerability reports, follow [SECURITY.md](SECURITY.md). ## Roadmap Follow [issues](https://github.com/inite-ai/inite-brain-service/issues) and [releases](https://github.com/inite-ai/inite-brain-service/releases) for current work. Design notes and earlier experiments remain in [docs/roadmap](docs/roadmap); read their dates and status before treating an item as shipped or pending. ## License [AGPL-3.0-or-later](LICENSE).