{"id":50586804,"url":"https://github.com/dnotitia/akb","last_synced_at":"2026-06-05T07:00:39.007Z","repository":{"id":356273558,"uuid":"1231704393","full_name":"dnotitia/akb","owner":"dnotitia","description":"AKB — Agent Knowledgebase. Organizational memory for AI agents: vault-scoped docs / tables / files unified by URI graph, served over MCP.","archived":false,"fork":false,"pushed_at":"2026-05-29T04:35:15.000Z","size":2894,"stargazers_count":43,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-29T06:20:53.016Z","etag":null,"topics":["agent","claude","claude-code","fastapi","knowledge-base","knowledge-graph","mcp","model-context-protocol","multi-tenant","pgvector","postgres","rag","react","vector-search"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dnotitia.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-07T07:54:22.000Z","updated_at":"2026-05-29T05:34:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dnotitia/akb","commit_stats":null,"previous_names":["dnotitia/akb"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/dnotitia/akb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnotitia%2Fakb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnotitia%2Fakb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnotitia%2Fakb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnotitia%2Fakb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dnotitia","download_url":"https://codeload.github.com/dnotitia/akb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnotitia%2Fakb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33932048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","claude","claude-code","fastapi","knowledge-base","knowledge-graph","mcp","model-context-protocol","multi-tenant","pgvector","postgres","rag","react","vector-search"],"created_at":"2026-06-05T07:00:30.180Z","updated_at":"2026-06-05T07:00:38.991Z","avatar_url":"https://github.com/dnotitia.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/akb-hero.png\" alt=\"AKB — agents reading and writing into a permissioned knowledge vault of docs, tables, and files, linked by a URI graph\" width=\"100%\"\u003e\n\u003c/p\u003e\n\n# AKB — Agent Knowledge Base\n\n\u003e **Organizational memory for AI agents.** Git-backed knowledge base served\n\u003e over the **Model Context Protocol (MCP)** — agents read and write directly\n\u003e with hybrid semantic + keyword search, structured tables, files, and a URI\n\u003e graph. Drop-in alternative to Confluence / Notion for Claude Code, Cursor,\n\u003e Windsurf, and any MCP-aware agent.\n\n[![License: BSL 1.1](https://img.shields.io/badge/license-BUSL--1.1-blue.svg)](./LICENSE)\n[![npm: akb-mcp](https://img.shields.io/npm/v/akb-mcp.svg?label=npm%3A%20akb-mcp)](https://www.npmjs.com/package/akb-mcp)\n[![MCP](https://img.shields.io/badge/MCP-Streamable%20HTTP-orange.svg)](https://modelcontextprotocol.io)\n\n## Works with\n\nAny agent client that speaks **MCP (Streamable HTTP or stdio)**:\n\n- **Claude Code** — CLI / VS Code / JetBrains\n- **Claude Desktop** — macOS / Windows\n- **Cursor**, **Windsurf**, **Cline**, **Continue** — via the\n  [`akb-mcp`](https://www.npmjs.com/package/akb-mcp) stdio proxy\n- Custom agents — direct HTTP `POST /mcp/` with a Bearer token\n\n## Why AKB\n\nMost knowledge tools are built for humans clicking through a UI. Agents need a\ndifferent shape: structured documents, semantic + keyword search in one call,\nexplicit relations, and full version history. AKB gives agents a single set of\ntools (`akb_put`, `akb_search`, `akb_browse`, `akb_relations`, …) over a\nbacking store of Git bare repos and a PostgreSQL hybrid index.\n\n## Retrieval quality\n\nMemory is only useful if the right note comes back. AKB's hybrid retrieval\n(dense + BM25, source-level dedup) was benchmarked on\n[LongMemEval](https://github.com/xiaowu0162/LongMemEval)-S — 500 long-context\nquestions, ~50 chat sessions per question. **Recall@5 = 98.4%**, with no\nreranker in the loop.\n\n| System | R@5 | n | Reranker | Source |\n|---|---:|:---:|:---:|---|\n| **AKB hybrid** | **98.4%** | 500 | no | this repo |\n| MemPalace hybrid + rerank | 98.4% | 450 | yes | [MemPalace](https://github.com/mempalace/mempalace) |\n| gbrain hybrid | 97.6% | 500 | no | [gbrain-evals](https://github.com/garrytan/gbrain-evals) |\n| gbrain vector | 97.4% | 500 | no | gbrain-evals |\n\nMethodology, per-category breakdown, and a one-command reproducible harness\nlive in [`eval/longmemeval/`](eval/longmemeval/). The embedding model differs\nacross systems (AKB: `bge-m3@1024`), so read this as a stack-level comparison.\n\n## Design philosophy\n\n**Core stays small; flexibility comes from extension, not built-in\nautomation.** AKB does not ship its own consolidator, summariser, or\n\"knowledge gardener\" — instead every write emits a structured event to a\nRedis Stream (`akb:events`). Operators wire any external consumer\n(periodic synthesis bot, doc-rot reaper, weekly-digest agent, audit\ntrail, …) on top, with no patches to the core. The base contract is a\nread/write store; opinions about *what to do with* the knowledge live\noutside.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                  Access Layer                            │\n│   MCP Server  │  REST API  │  Web UI                     │\n├──────────────────────────────────────────────────────────┤\n│                  Core Services                           │\n│   Document (Put/Get)  │  Search (Hybrid: dense+BM25)     │\n│   Relations (graph)   │  Session  │  Publications        │\n├──────────────────────────────────────────────────────────┤\n│                  Storage Layer                           │\n│   Git bare repos       │  PostgreSQL 16 (text + meta SoT)│\n│                        │  Vector store (driver):         │\n│                        │    pgvector  (default, same PG) │\n│                        │    qdrant    (optional)         │\n│                        │    seahorse  (managed, optional)│\n└──────────────────────────────────────────────────────────┘\n```\n\nPostgreSQL is the source of truth — chunk text + metadata + BM25 vocab.\nThe vector store is a driver-pluggable derived index holding dense\nembeddings and corpus-side sparse vectors. Full vector-store loss is\nrecoverable from PG by setting `chunks.vector_indexed_at = NULL` and\nletting the indexing worker re-populate.\n\n## Key Concepts\n\n- **Vault** — A Git bare repo. The unit of access control and physical isolation.\n- **Collection** — A directory inside a vault. Topical grouping of documents.\n- **Document** — Markdown + YAML frontmatter, optimised for agent read/write.\n- **Hybrid Search** — Dense (semantic) + BM25 (lexical) fused via RRF in one call.\n- **Relations** — `depends_on`, `related_to`, `implements` in frontmatter form an explicit knowledge graph.\n- **Vault isolation in `akb_sql`** — Enforced by PostgreSQL ACL. Each\n  AKB user has a corresponding PG role (`akb_user_\u003cuid\u003e`) and each\n  vault has three group roles (`akb_vault_\u003cvid\u003e_{reader,writer,admin}`).\n  `akb_sql` runs the user's SQL inside a transaction with\n  `SET LOCAL ROLE`; cross-vault references return PG `42501`\n  directly. No application-side regex inspects user SQL for forbidden\n  identifiers. See `docs/designs/pg-native-rbac/`.\n\n## MCP Tools (selection)\n\n| Tool | Description |\n|------|-------------|\n| `akb_list_vaults` / `akb_create_vault` | Vault management |\n| `akb_put` / `akb_get` / `akb_update` / `akb_delete` | Document CRUD (Git commit + indexing) |\n| `akb_put_file` / `akb_get_file` / `akb_delete_file` | File attachments — proxy-side (requires local filesystem) |\n| `akb_create_table` / `akb_alter_table` / `akb_drop_table` / `akb_sql` | Tabular content — per-doc tables + SQL |\n| `akb_browse` | Tree traversal (collection → docs) |\n| `akb_search` / `akb_grep` | Hybrid search (dense + BM25) / literal grep |\n| `akb_drill_down` | Section-level retrieval |\n| `akb_relations` / `akb_link` / `akb_unlink` / `akb_graph` | Knowledge graph |\n| `akb_edit` / `akb_diff` / `akb_history` | In-place edit, diff, Git history |\n| `akb_grant` / `akb_revoke` / `akb_set_public` | Permission boundaries — per-user, per-org, public |\n| `akb_publish` / `akb_unpublish` | Public publication |\n\nAgent memory and session lifecycle are not MCP tools — they live on\nthe dedicated `/api/v1/agent-sessions` REST surface, driven by AKB\nlifecycle plugins (`akb-claude-code`, `akb-cursor`, …) that hook into\nthe agent's own SessionStart / PreCompact / SessionEnd events. As an\nagent, your own memory vault (`agent-memory-{username}`) is browsable\nthrough the standard `akb_search` / `akb_browse` / `akb_get` tools\nexactly like any other vault.\n\nThe full tool catalogue is exposed via `akb_help()` from any MCP client.\n\n## Document Format\n\nEvery vault resource has a location-aware AKB URI — the canonical handle\nused by every tool and stored in relations. As of 0.3.0:\n\n```\nakb://{vault}                                          vault root (browse target)\nakb://{vault}/coll/{coll_path}                         collection (browse target)\nakb://{vault}[/coll/{coll_path}]/doc/{filename}        document\nakb://{vault}[/coll/{coll_path}]/table/{name}          table\nakb://{vault}[/coll/{coll_path}]/file/{uuid}           file\n```\n\nThe `/coll/{coll_path}` segment is omitted for resources at the vault\nroot. Walking up a URI to its parent collection is a pure string\noperation — paste the parent into `akb_browse(uri=...)` to list\nsiblings without an extra lookup.\n\n```yaml\n---\ntitle: \"Payment API v2 migration plan\"\ntype: plan              # note | report | decision | spec | plan | session | task | reference\nstatus: active          # draft | active | archived | superseded\ntags: [payments, api]\ndomain: engineering\nsummary: \"REST → gRPC transition plan.\"\ndepends_on: [\"akb://eng/coll/specs/doc/payment-api-v2.md\"]\nrelated_to: [\"akb://eng/coll/meetings/doc/2026-05-01-payments.md\"]\n---\n\n# Payment API v2 migration plan\n...\n```\n\n## Quick Start\n\nAKB ships as a **3-container stack** (PostgreSQL with pgvector + backend +\nfrontend). You bring an OpenAI-compatible embedding endpoint (OpenAI,\nOpenRouter, self-hosted vLLM/TEI, etc.) — that's the only required external\ndependency for core CRUD and search. Prefer running a separate Qdrant\ncluster, or pointing at a managed Seahorse Cloud table? See *Vector store*\nbelow.\n\n```bash\n# 1. Configure\ncp config/app.yaml.example   config/app.yaml\ncp config/secret.yaml.example config/secret.yaml\n$EDITOR config/secret.yaml   # set embed_api_key (and jwt_secret for any non-local deploy)\n\n# 2. Run\ndocker compose up -d\n\n# 3. Open\nopen http://localhost:3000\n```\n\n`config/app.yaml` and `config/secret.yaml` are the **single source of runtime\nconfiguration** — no environment variables are read by the backend. Mount the\n`config/` directory at `/etc/akb/` in any deployment.\n\n### Vector store (driver-pluggable)\n\nHybrid search (dense + BM25 sparse, RRF-fused) runs through a driver\ninterface. Three drivers ship; pick at config time:\n\n- **`pgvector`** (default) — uses the same Postgres container that holds\n  application data. The pgvector/pgvector image pre-installs the\n  extension; the driver creates a separate `vector_index` schema, so the\n  main `chunks` table stays plain PostgreSQL. RRF fusion runs\n  application-side. No external service to operate.\n- **`qdrant`** — runs a separate Qdrant container; native RRF via the\n  Query API. Useful when you already operate Qdrant or want to scale\n  the vector store independently of Postgres.\n- **`seahorse`** — points at a managed [Seahorse Cloud][shc] table over\n  its TABLE_V2 + BFF API (Bearer auth, per-table host). No\n  infrastructure to run on your side; you provision a table in the\n  Seahorse console (or let the driver auto-create one) and AKB stores\n  its chunks there. Native RRF, server-side BM25. See\n  [`docs/vector-store-seahorse.md`](./docs/vector-store-seahorse.md)\n  for the end-to-end setup walkthrough (sign-up → token → schema →\n  config).\n\n[shc]: https://console.seahorse.dnotitia.ai\n\nSwitching drivers is a config edit (no schema migration on the main DB):\n\n```bash\n# Default flow targets pgvector.\ndocker compose up\n\n# Qdrant:\ndocker compose -f docker-compose.yaml -f docker-compose.qdrant.yaml up\n$EDITOR config/app.yaml     # vector_store_driver: qdrant\n                            # vector_url: http://qdrant:6333\n\n# Seahorse Cloud (managed; full guide in docs/vector-store-seahorse.md):\ndocker compose up           # no extra container needed\n$EDITOR config/app.yaml     # vector_store_driver: seahorse\n                            # seahorse_tenant_uuid: \u003cyour tenant\u003e\n                            # seahorse_table_name: \u003cyour table\u003e\n$EDITOR config/secret.yaml  # seahorse_token: shsk_\u003c...\u003e\n```\n\nEmbedding model + dimensions are also fully pluggable via\n`embed_base_url` / `embed_model` / `embed_dimensions` — the codebase has\nno hard-coded model. For pgvector with HNSW, keep `embed_dimensions ≤ 2000`\n(or 4000 with `halfvec`); larger models fall back to exact scan.\nQdrant/Seahorse have no such limit (Qdrant up to 65536, Seahorse up to\nits table-defined dim).\n\n### LLM features (optional)\n\nLLM is only used by the `metadata_worker` to auto-tag documents imported via\nexternal git mirroring. Core CRUD/search works without it. To enable, set\n`llm_base_url` / `llm_model` in `app.yaml` and `llm_api_key` in `secret.yaml`.\n\n### Event fanout (optional)\n\nThe PG `events` outbox is always written. Set `redis_url` in `app.yaml` to\nhave the `events_publisher` worker drain the outbox to a Redis Stream\n(`akb:events`) so external services can subscribe via `XREAD` / consumer\ngroups. Leave blank to disable; events still accumulate in PG and you can\nbuild an SSE endpoint on top of the LISTEN/NOTIFY trigger without Redis.\n\n### Production deployment\n\nFor Kubernetes, see [`deploy/k8s/README.md`](./deploy/k8s/README.md). The\n`deploy/k8s/` directory contains a generic kustomize base; provide your\nown registry, hostname, and TLS issuer via the documented env vars or an\noperator-private overlay under `deploy/k8s/internal/`.\n\n## Project Structure\n\n```\nakb/\n├── backend/                  # Python 3.11 / FastAPI / asyncpg / GitPython\n│   ├── app/\n│   │   ├── api/routes/       # REST endpoints\n│   │   ├── services/         # Business logic + workers\n│   │   └── db/               # PostgreSQL schema + migrations\n│   ├── mcp_server/           # Streamable HTTP MCP server\n│   └── tests/                # E2E shell tests\n├── frontend/                 # React 19 + TypeScript + Vite + Tailwind\n├── packages/\n│   └── akb-mcp-client/       # stdio ↔ HTTP MCP proxy (npm: akb-mcp)\n├── agents/                   # Reference Python agent runtime (think/act loop over MCP)\n├── templates/                # Doc templates (ADR, PRD, runbook, …) and vault profiles\n├── design-system/            # Frontend design system docs\n├── config/\n│   ├── app.yaml.example      # Non-secret runtime settings\n│   └── secret.yaml.example   # API keys, passwords (gitignored when not .example)\n├── deploy/\n│   └── k8s/                  # Generic kustomize base for Kubernetes\n└── docker-compose.yaml       # 3-container local stack (postgres + backend + frontend)\n```\n\n## Tech Stack\n\n- **Backend**: Python 3.11, FastAPI, Uvicorn, asyncpg, GitPython, MCP SDK\n- **Database**: PostgreSQL 16 (main DB needs no extension; the same\n  pgvector/pgvector image hosts the optional vector_index schema)\n- **Vector store**: driver-pluggable (pgvector default; Qdrant or\n  Seahorse Cloud optional — hybrid dense + BM25 sparse, RRF fusion)\n- **Event stream** (optional): PG `events` outbox + Redis Streams fanout\n- **Frontend**: React 19, TypeScript, Vite, Tailwind CSS v4, Radix UI\n- **Auth**: JWT + Personal Access Tokens (PATs)\n- **MCP**: Streamable HTTP (backend) + stdio proxy (`akb-mcp` on npm)\n\n## Versioning\n\nAKB follows [SemVer](https://semver.org/). The product version lives in\n`backend/pyproject.toml` (`[project].version`) and is mirrored to\n`frontend/package.json` via `scripts/bump-version.sh \u003cx.y.z\u003e`. Each\n`deploy/k8s/deploy.sh` run tags the Docker images with both the explicit\nversion (`:${VERSION}`) and `:latest`, so historical builds remain\npullable for rollback.\n\n`packages/akb-mcp-client` (the `akb-mcp` npm proxy) follows its own npm\nsemver lifecycle and is **not** tied to the product version.\n\n## License\n\nThe AKB backend, frontend, and deployment manifests are licensed under\nthe [Business Source License 1.1](./LICENSE) — source-available, with\nan Additional Use Grant that permits production use (commercial or\nnon-commercial) up to a seat-count threshold, automatically converting\nto **Apache License 2.0** four years after each version's first public\nrelease.\n\nThe npm `akb-mcp` proxy (`packages/akb-mcp-client/`) is separately\nlicensed under the **MIT License** so it can be freely embedded in any\nagent client without restriction.\n\n**Free production use of the backend** — you may deploy AKB in\nproduction, commercial or not, provided your aggregate deployment\nserves **fewer than 100 Named Seats** (distinct human user accounts in\nthe `users` table, per deployment; service accounts and\n90-day-inactive accounts excluded — see [LICENSE](./LICENSE) for the\nprecise definition).\n\n**Commercial license required** for any of:\n\n- Production use of the backend at or above 100 Named Seats.\n- Offering AKB (modified or not) as a hosted service, on-premises\n  product, embedded component, or rebranded distribution to third\n  parties — regardless of seat count.\n\n**Trademarks** — \"AKB\", \"Dnotitia\", and \"Seahorse\" are trademarks of\nDnotitia, Inc. The software license does not grant trademark rights.\nForks and derivative works must be distributed under a different name.\nSee [TRADEMARKS.md](./TRADEMARKS.md).\n\nFor commercial licensing, the rationale behind the BSL transition, or\ntrademark permission requests, see\n[LICENSE-CHANGE.md](./LICENSE-CHANGE.md) or contact\n**support@dnotitia.com**.\n\n## Security\n\nFound a vulnerability? See [SECURITY.md](./SECURITY.md) — please report\nprivately, not via public issues.\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnotitia%2Fakb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdnotitia%2Fakb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnotitia%2Fakb/lists"}