agent-rag
What it is
agent-rag is a deterministic, per-client source of truth for documents such as user stories, contracts, specifications, and manuals, logically organized by project. Original bytes live in a content-addressed object store; SQLite is a rebuildable index, not the source of truth.
What it is not
Engram is for memory points; agent-rag retrieves answers from documents. agent-rag is not a chatbot: it offers deterministic catalog and document-reading operations rather than autonomous conversation. In v1, it is not an LLM or an embedding index.
Install
Install globally so an MCP adapter can resolve agent-rag-mcp from its PATH:
npm install --global agent-rag-mcp
The rag commands available today are:
rag init— Initializes the namespace database and object store.rag add <path>— Ingests a file and copies its bytes to the object store at the same time, so OneDrive/Files-On-Demand eviction cannot lose the ingested document.rag import <dir>— Ingests files from a directory.rag ls— Lists active documents in the selected namespace.rag rm <document-id>— Logically retires a document and preserves its history.rag relabel <document-id> --label <text>— Replaces one document's stored label.rag entity rename <from> <to>— Corrects an entity key within the project.rag review list— Lists version pairs awaiting a human decision.rag review link <from> <to> --type <conflicts_with|same_entity>— Records a human link between versions with a note.rag status— Shows counts for the namespace.rag doctor— Verifies registered-object integrity and reports missing objects, orphan blobs, or temporary files.rag backup --to <dir>— Backs up the manifest and object store.rag restore --from <dir>— Restores a backup under this root.rag reindex— Rebuilds the database from the manifest and objects.rag rehash— Previews recomputed hashes for stored versions;rag rehash --applywrites the changed hash facts in one transaction. Preview first, and back up withrag backup --to <backup-dir>before applying.rag rehash --applywritesmanifest.jsonbefore committing the database transaction. An interruption in that window can leave the manifest ahead of the database; rerunningrag rehash --applyor runningrag reindexconverges to the requested facts.
CLI output
Interactive terminals render document lists as aligned columns and other supported results as concise summaries. When output is piped, commands keep the single-line JSON envelope. Set RAG_FORMAT=json or RAG_FORMAT=pretty to override terminal detection; an invalid value falls back to automatic detection. rag --help defaults to raw usage text on a terminal, while RAG_FORMAT=json restores its JSON envelope for scripts that parse the legacy help output. Set NO_COLOR (any value, including empty) to disable ANSI styling without changing the output layout.
rag ls includes each document's documentId. Copy that value to relabel the same document:
rag ls
rag relabel <document-id> --label "replacement label"
Structured files can use .yaml, .yml, .json, or .jsonl; each structured file yields sections from its parsed data tree. YAML uses the YAML 1.2 core schema, so words such as yes and on remain strings and unquoted timestamps remain strings.
Content identity
Structured JSON, JSONL, and YAML are hashed from compact canonical JSON for their parsed data tree, without a format prefix. Their doc_version rows use content_kind='structured' and hash_version=2; equivalent trees therefore share a content hash across formats and key order. Other formats retain the existing normalized extracted-text hash and use content_kind=NULL with hash_version=1. Existing version rows stay at version 1 with a null content kind until repaired with rag rehash; the repair never rewrites stored object bytes and skips structured documents that cannot be canonically hashed.
The default knowledge-base root is %USERPROFILE%\.rag\. Each client has its own rag.db under .rag\clients\<client>\; projects are logical within that client and are identified by project_id. The namespace is the pair (client, project). By default, failClosed is true; without a namespace, reads are allowed, and when failClosed is set to false, writes go to the reserved default/default namespace. The Tier 3 human review queue is available through rag review list.
rag add is idempotent by sha256: adding the same bytes again returns the {namespace, result} envelope with result.status set to "unchanged" and creates no new version. A different hash creates a new doc_version without deleting the previous one. Deletion is a logical tombstone; version history is preserved. label is what re-ingestion matches on, so relabeling detaches the document from future imports of that same source path, which will then appear as a new document.
MCP
Register two separate server processes in the adapter configuration (this example uses the common mcpServers format). Replace /path/to/rag-data with an absolute storage path:
{
"mcpServers": {
"agent-rag-orchestrator": {
"command": "agent-rag-mcp",
"args": [],
"env": {
"RAG_ROOT": "/path/to/rag-data",
"RAG_CAPABILITIES": "find"
}
},
"agent-rag-explorer": {
"command": "agent-rag-mcp",
"args": [],
"env": {
"RAG_ROOT": "/path/to/rag-data",
"RAG_CAPABILITIES": "find,read"
}
}
}
}
The orchestrator receives only rag_find, which returns citations and bounded excerpts. The explorer also receives rag_read, which reads bounded text from a citation. Keeping them separate applies least privilege. The server reads RAG_ROOT to locate the knowledge base and RAG_CAPABILITIES to decide which tools to announce.
The extension adds a rag section to the agent system prompt describing the namespace and delegation rules; the section contains no client, project, or path value. Set RAG_PROMPT=off (exactly that value) to suppress it; any other value, including unset, keeps it.
The namespace travels in every rag_find or rag_read call; it does not come from the environment. For example, include "namespace": {"client":"acme","project":"research"} in each tool call's arguments. Do not configure RAG_CLIENT or RAG_PROJECT as a substitute for the per-call namespace.
Requirements
- Node.js >= 22.13.
- The
.mtssource files run with--experimental-strip-types --experimental-sqlite. npm run buildbuilds each source file with esbuild (per-file).npm testruns the tests with Node'snode:test.npm run typecheckruns the TypeScript typecheck without emitting files.
Known limits
Version 0.1.0 has no embeddings or Tier 2; scanned PDFs go through OCR. Document parsing runs in a child process with a 512 MB V8 heap cap.
Design documents
License
MIT.