Local-first knowledge graph Prerelease 0.3.0 · Linux

Okto Neuron. Knowledge graph memory for your agents, built from your Markdown notes.

Okto Neuron is a local-first knowledge graph memory for AI agents, made by Okto Labs. It reads a folder of Markdown notes, extracts claims with an LLM you configure, and serves them over MCP. Ask with sources and each cited source comes back with its file path, byte range and content hash.

For developers who want Claude Code to answer from their own notes and show where the answer came from.

$ curl -fsSL https://raw.githubusercontent.com/OktoLabsAI/okto-neuron/main/install.sh | bash
Linux · macOS not yet verified on 0.3.0

Free to run locally · No account required · Source-available (ELv2) · Works with Claude Code

See how an answer is grounded
ELv2
source on GitHub
127.0.0.1
binds loopback, no account
5
MCP tools
JSON
benchmark data published

Your agent answered. Which line of which file did that come from?

Most agent memory tools hand back prose. The paragraph sounds settled, the source is gone, and a confident wrong number reads exactly like a right one. You cannot check what you cannot locate.

Worse, retrieval can fail quietly. The model was unreachable, the context was cut short, the answer was assembled from nothing, and the paragraph still arrives looking finished.

01

The answer has no source.

The answer names a value, a date, a decision. Nothing in it says which file, let alone which bytes of that file.

02

Fluent text reads the same either way.

A fluent sentence carries the same weight whether it was read from your notes or extrapolated to fill a gap.

03

A failed call returns normal-looking text.

When the model behind the tool is down or truncates, most tools return the same shape of text. You find out later, if at all.

A knowledge graph derived from your notes.

Okto Neuron is a standalone, local-first knowledge graph usable as a Python library, CLI, and authenticated MCP server. Your Markdown files stay the source of record; the graph is derived from them and can be regenerated from the same files.

CLI

okto-neuron / kg

Init a vault, ingest files, ask and explore from the terminal. The same code path the server uses.

Library

Python

Import it. Every surface below is a thin wrapper over the same library calls.

MCP

Port 8201

Five bearer-authenticated tools. Claude Code is the wired client; the protocol is open to any MCP client.

REST

Port 7777

GET /api/v1/nodes/{id} returns a node, its in and out edges, its provenance record, and the block it came from.

UI

Seven views

Query, Add, Logs, Browse, Graph, Curation, Config. The Query view exposes 13 retrieval controls.

Runs on Okto Grafx, the Okto Labs embedded graph database. Ladybug and Neo4j are selectable backends; Neo4j needs the neo4j extra, which the installer does not add.

5 + 6
primitives + support types
5
MCP tools
7
UI views
1
process, two ports

Every claim carries its byte range home.

Each claim is anchored by PROV-O edges to the block it was read from, the extractor activity that produced it, and the agent responsible. Ask with include_sources=true and the pointer comes back with the answer.

// the excerpt line the model sees, so it can say the sources do not cover a period
[EXCERPT source=decisions/0012-queue-backend.md bytes=0-388,880-1364 of 2210]

// what comes back (abridged)
{
  "text": "On 2026-03-04 the team chose Redis Streams for the job queue, citing a smaller operational footprint than Kafka for the current team size.",
  "citations": ["..."],
  "subgraph_evidence_ids": [],
  "retrieval": {
    "synthesis_status": "ok",
    "finish_reason": "stop",
    "vault": "platform-notes"
  },
  "sources": [
    {
      "block_id": "blk_4e11c0",
      "path": "decisions/0012-queue-backend.md",
      "byte_start": 880,
      "byte_end": 1364,
      "content_hash": "sha256:7c0e...91af"
    }
  ]
}
Paths are vault-relative. Absolute paths are never returned. explore returns block_id on claims and relationships too, so you can walk the graph without an LLM in the loop. Values are illustrative. Walk through a full example.
“Every source block declares which bytes of which file it is.” ADR 0043, D7

A degraded answer never looks like a successful one.

synthesis_status comes back in retrieval on every ask. finish_reason joins it whenever a provider was called and reported one, and vault_override_ignored appears whenever a vault override is discarded. Read them before trusting the text. They are how the tool reports a failed model call.

synthesis_status

Always present. Six values.

ok empty provider_error truncated abnormal_stop no_llm

Empty text plus provider_error means the model was unreachable, not that the graph lacks the answer. no_llm means no model is configured, so none was called; the citations are still the retrieval hits.

“A degraded answer must never look like a successful one.” ADR 0043, D6
finish_reason

Present when a provider reported one.

The value is normalized, and the provider's raw value comes back as native_finish_reason when the two differ. Anything other than stop sets synthesis_status to truncated or abnormal_stop. The field is absent when no provider reported a reason, as with no_llm, where no model was called.

vault_override_ignored

Shown when it happens.

When a per-call vault override is discarded, the response says so. You never answer from a different vault than you think you did.

How a note becomes committed claims.

Files or raw text go in. Blocks, claims, and entities come out the other side, but only after deduplication, reconciliation, and a confidence gate. Extraction only proposes candidates; the gate is the only thing that commits.

  1. 01

    Intake

    A file path or raw text is chunked into byte-anchored blocks: path, byte_start, byte_end, content_hash.

  2. 02

    Propose

    An LLM extracts atomic claims and entities from each block. These are candidates, not facts.

  3. 03

    Stage

    Candidates are held with their provenance edges: which block, which extractor run, which agent.

  4. 04

    Resolve

    Duplicates are collapsed and entities reconciled against what the graph already holds.

  5. 05

    Gate auto-commit or hold for review

    Entity candidates at or above confidence 0.75 auto-commit; below that they are held for review in Curation. Relationships, and the claims minted from them, pass a separate gate that checks endpoint types, the predicate and grounding in the source block, then commits, queues or rejects each one. The 0.75 threshold is configurable.

  6. 06

    Commit

    Committed to the graph store (Okto Grafx by default) and embedded locally with fastembed, in-process.

Closed schema

Five primitives: Agent, Activity, InformationObject, Concept, Place. Six support types: Document, Identifier, Annotation, Claim, Block, Finding. Vocabulary follows PROV-O, SKOS, Dublin Core, BIBFRAME, and CiTO.

Supersession

When an edit replaces the text an old claim was read from, and an LLM correction judge confirms the new claim corrects it, the old claim is dated and dropped from recall, with a supersedes edge from the new one. This happens at ingest, within the same document or resolved subject.

Derived, rebuildable

The graph is derived from the vault. Delete the graph and rebuild it from the same files. A rebuild re-runs LLM extraction, so the new graph can differ from the old one, and the history of superseded claims is not recreated.

The MCP tools, behind one bearer token.

The MCP server listens on 127.0.0.1:8201 and authenticates every call. Each tool's first docstring line is reproduced below unchanged.

ask one-shot · k = 20 · 17 parameters

Answer a question grounded in the knowledge graph, with citations.

Seeds wide, synthesizes once, and returns synthesis_status, finish_reason when the provider reported one, and optional byte-exact sources.

explore structured · k = 12 · no LLM call

Drill into the graph around a topic, then walk outward by node id.

Returns graph structure, not prose, and makes no LLM call at all.

remember file path or raw text · loopback-only

Ingest a source and autonomously curate it into the graph.

sensitivity="local_only" refuses any hosted LLM for that ingest.

list_vaults names only

List the vault NAMES this server can reach, so you can pick one.

Returns names, deliberately not paths.

init_vault loopback-only

Create one application-managed named vault without selecting it.

Accepts loopback callers only. Direct remote serving is disabled in 0.3.0.

What leaves the machine, exactly.

LLM calls to the endpoint you set, an optional remote Neo4j you explicitly allow, the installer's downloads, the embedding model download when fastembed does not already have the model cached, and LLM call traces if you opt in to MLflow tracing. There is no analytics in the shipped package, and tracing is off until you set OKTO_NEURON_MLFLOW_TRACKING_URI to a tracking server you choose.

  • LLM calls, to the endpoint you configure
  • A remote Neo4j, only if you explicitly allow one
  • The installer's downloads
  • The embedding model download, when it is not already cached
  • LLM call traces, only to an MLflow server you name

Loopback by default

Binds 127.0.0.1. Direct remote serving is disabled in 0.3.0; use an SSH tunnel to reach it from another machine.

Bearer-authenticated MCP

Every tool call carries a token. remember and init_vault accept loopback callers only.

Local model by default

The default LLM endpoint is http://127.0.0.1:8123/v1, a server you run. Non-loopback endpoints require explicit remote-egress confirmation.

Embeddings in-process

The default embedder is fastembed, running inside the daemon. Nothing about your text is sent anywhere to be embedded. The model itself is downloaded when fastembed does not find it in its cache.

Secrets at rest

API keys are never written into vault YAML. Stored with POSIX owner-only permissions, or Windows DPAPI. New installs keep vault data in ~/.okto-neuron/vaults/<name>; installs upgraded from Marginalia keep ~/.marginalia/vaults.

Questions about Okto Neuron.

What is Okto Neuron?

A local-first knowledge graph memory for AI agents. It reads Markdown notes, extracts claims with an LLM you configure, and serves them over MCP, a CLI, a Python library and a Web UI. Every claim points back to the file, byte range and content hash it came from.

Is it open source?

It is source-available. From 0.3.0 the license is the Elastic License 2.0 with an addendum covering SaaS, competing services, internal use and branding. Releases up to 0.2.0 stay under Apache 2.0. The source is on GitHub.

How do I install it?

Run the one-line installer. It sets up the daemon, the UI and the Claude Code registration. Okto Neuron is not on PyPI yet; the PyPI packages named neuron and marginalia are unrelated projects.

Which platforms does it run on?

The upgrade from 0.2.0 to 0.3.0 has been rehearsed on Linux, with a locally built 0.3.0 wheel. macOS and Windows have not yet been verified on 0.3.0.

Does my data leave my machine?

Only these: LLM calls to the endpoint you configure, the installer's downloads, and the embedding model download when fastembed does not already have it cached. Two more are optional and happen only when you set them up: a remote Neo4j you explicitly allow, and LLM call traces if you opt in to MLflow. Your text is embedded locally. If your LLM endpoint is hosted, the text sent to it leaves the machine. There is no analytics in the shipped package.

Do I need an LLM?

For ingest and for written answers, yes. The default endpoint is http://127.0.0.1:8123/v1, a server you run. If no model is configured, ask returns synthesis_status: no_llm with the retrieval hits as citations. If a model is configured but unreachable, it returns provider_error. explore makes no LLM call.

Which agents can use it?

The installer registers Claude Code (setup guide). The server speaks MCP over HTTP with a bearer token on 127.0.0.1:8201.

How is this different from searching my notes with RAG?

Plain retrieval returns chunks of text. Okto Neuron extracts atomic claims into a graph through a confidence gate, keeps a byte-range pointer on each one, can retire a claim when an edit replaces the fact in the same note and a correction judge confirms it, and reports on every answer whether the model call finished cleanly.

What happens when I edit a note?

On the next ingest, if the edit replaced the old text and an LLM correction judge confirms the change, the new claim supersedes the old one within the same document or resolved subject. The old claim is dated and linked to the new one. Corrections across documents are flagged for you to review instead of being applied.

Is there a benchmark?

Yes, on LoCoMo categories 1-4, from our own harness, with the data published. See Benchmarks.

What was it called before?

Marginalia, up to 0.2.0.

Install with one command.

Prerelease 0.3.0. The upgrade from 0.2.0 to 0.3.0 has been rehearsed on Linux, with a locally built 0.3.0 wheel. macOS and Windows have not yet been verified on 0.3.0. The installer sets up everything listed here.

$ curl -fsSL https://raw.githubusercontent.com/OktoLabsAI/okto-neuron/main/install.sh | bash
Linux · macOS not yet verified on 0.3.0

Up to 0.2.0 this project was called Marginalia. Okto Neuron is not on PyPI yet; the PyPI packages named neuron and marginalia are unrelated projects.

Using Claude Code? The installer registers it for you. How to check or register it by hand.

  1. Installs uv and pins Python 3.12. Your system Python is untouched.
  2. Installs the Okto Neuron wheel.
  3. Starts one daemon: UI and REST on 7777, MCP on 8201.
  4. Opens the UI.
  5. Lets you create, select, configure, and delete managed vaults inside the application.
  6. Registers Claude Code with claude mcp add --scope user.

Pass --no-onboard to skip the first-run prompt.

Free to run locally. No account required.