{"id":47369917,"url":"https://github.com/ekailabs/contexto","last_synced_at":"2026-04-07T06:02:32.029Z","repository":{"id":314190090,"uuid":"1044757264","full_name":"ekailabs/contexto","owner":"ekailabs","description":"Context Engine for your AI agents.","archived":false,"fork":false,"pushed_at":"2026-04-03T11:29:27.000Z","size":102301,"stargazers_count":348,"open_issues_count":14,"forks_count":12,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-04-03T15:15:51.281Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.getcontexto.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekailabs.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":null,"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":"2025-08-26T06:58:12.000Z","updated_at":"2026-04-03T04:13:58.000Z","dependencies_parsed_at":"2026-01-16T22:05:23.159Z","dependency_job_id":null,"html_url":"https://github.com/ekailabs/contexto","commit_stats":null,"previous_names":["ekailabs/ekai-gateway","ekailabs/contexto"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ekailabs/contexto","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekailabs%2Fcontexto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekailabs%2Fcontexto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekailabs%2Fcontexto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekailabs%2Fcontexto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekailabs","download_url":"https://codeload.github.com/ekailabs/contexto/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekailabs%2Fcontexto/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31501903,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-03-19T04:00:31.530Z","updated_at":"2026-04-07T06:02:32.016Z","avatar_url":"https://github.com/ekailabs.png","language":"TypeScript","funding_links":[],"categories":["LLMOps","TypeScript"],"sub_categories":["Observability"],"readme":"\u003cp align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003eContexto\u003c/h1\u003e\n  \u003cp align=\"center\"\u003e\u003cstrong\u003eThe Local-First Context Engine for AI Agents\u003c/strong\u003e\u003c/p\u003e\n  \u003cp align=\"center\"\u003eNeuroscience-inspired · Open source\u003c/p\u003e\n\u003c/p\u003e\n\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![GitHub stars](https://img.shields.io/github/stars/ekailabs/contexto.svg?style=social)](https://github.com/ekailabs/contexto)\n[![Discord](https://img.shields.io/badge/Discord-Join%20Server-7289da?logo=discord\u0026logoColor=white)](https://discord.com/invite/5VsUUEfbJk)\n\n\nAI agents face a fundamental problem: **context windows are finite, but conversations are not.** Most runtimes handle this by summarizing older messages to free space. This works for short conversations, but over time summaries compound into summaries-of-summaries, blending unrelated topics and losing specific details.\n\nContexto takes a different approach: instead of compressing history, it **organizes** it.\n\n- Uses **semantic clustering** to group related messages and concepts\n- Maps relationships between messages, concepts, and session states\n- Provides structured context retrieval to combat context rot\n- Enables the agent to understand conversation topology\n\n## OpenClaw Setup\n\n### 1. Install the plugin in OpenClaw\n\n```bash\nopenclaw plugins install @ekai/contexto\nopenclaw plugins enable contexto\n```\n\n### 2. Set Contexto as the context engine\n\n```bash\nopenclaw config set plugins.slots.contextEngine contexto\n```\n\n### 3. Configure your API key\n\nSet your API key via CLI:\n\n```bash\nopenclaw config set plugins.entries.contexto.config.apiKey your-api-key-here\n```\n\n### 4. Restart OpenClaw\n\n```bash\nopenclaw gateway restart\n```\n\n## Configuration\n\n| Property | Type | Required | Description |\n| --- | --- | --- | --- |\n| `apiKey` | string | Yes | Your Contexto API key |\n\n## See the Difference\n\n**Without Contexto:**\n```\nUser: I prefer concise answers. I'm building a RAG pipeline with LangChain.\n\n[new session]\n\nUser: How should I chunk my documents?\nAssistant: Great question! There are many approaches to document chunking. First, let me explain\n         what chunking is...\n```\n\n**With Contexto:**\n```\nRetrieved context:\n  → user prefers concise answers\n  → user is building a RAG pipeline with LangChain\n\nUser: How should I chunk my documents?\nAssistant: For your LangChain RAG pipeline: use RecursiveCharacterTextSplitter, 512 tokens,\n         50-token overlap. It handles nested markdown and code blocks well.\n```\n\n## Quick Start\n\n### OpenClaw Plugin\n\n```json\n{\n  \"plugins\": {\n    \"slots\": {\n      \"contextEngine\": \"@ekai/contexto\"\n    },\n    \"allow\": [\"@ekai/contexto\"],\n    \"entries\": {\n      \"@ekai/contexto\": {\n        \"enabled\": true,\n        \"config\": {\n          \"apiKey\": \"your-api-key\"\n        }\n      }\n    }\n  }\n}\n```\n\nOr via CLI:\n\n```bash\nopenclaw plugins install @ekai/contexto\nopenclaw plugins enable contexto\nopenclaw config set plugins.slots.contextEngine contexto\nopenclaw config set plugins.entries.contexto.config.apiKey your-api-key\nopenclaw gateway restart\n```\n\n## How It Works\n\n### Episodes and the Sliding Window\n\nThe unit of storage is an **episode**: a full conversation turn containing the user message, assistant response, and any tool outputs. The sliding-window engine buffers episodes in memory. When token usage hits the compact threshold (default 50% of the token budget), the oldest episodes are ingested to the backend and evicted from the context window.\n\n### Hierarchical Clustering (AGNES)\n\nContexto organizes episodes using [AGNES (Agglomerative Nesting)](https://onlinelibrary.wiley.com/doi/book/10.1002/9780470316801), a bottom-up hierarchical clustering algorithm paired with [average linkage (UPGMA)](https://www.semanticscholar.org/paper/A-statistical-method-for-evaluating-systematic-Sokal-Michener/0db093335bc3b9445fa5a1a5526d634921d7b59a) via [`ml-hclust`](https://github.com/mljs/hclust).\n\n```\nEpisode turns (with embeddings)\n  -\u003e Pairwise cosine distance matrix\n  -\u003e AGNES with average linkage\n  -\u003e Dendrogram\n  -\u003e Cut at similarity threshold (0.65)\n  -\u003e ClusterNode tree (max depth 4)\n```\n\nUnlike summary-based compaction, the hierarchy preserves full episodes and gives you:\n\n- **Semantic organization**: related episodes land in the same branch, even if they happened weeks apart\n- **Multi-resolution retrieval**: match a top-level branch (all travel episodes) or drill into a sub-cluster (visa documents only)\n- **No pre-defined categories**: topics emerge from embeddings, no taxonomy required\n- **No information loss**: full episodes are stored and retrievable, never compressed\n\nFor the full technical deep dive, see [Why We Chose Hierarchical Clustering](docs/why-agnes.md).\n\n### Multi-Branch Beam Search\n\nRetrieval uses beam search (width 3) to explore multiple promising branches simultaneously. Instead of returning the top-k most similar items, beam search descends into the most relevant topic branches and greedily fills the token budget. When a query spans multiple topics, it surfaces episodes from several branches in a single pass with full path tracing for explainability (e.g., `travel -\u003e Japan trip -\u003e visa documents`).\n\n### Hybrid Rebuild Strategy\n\nFull AGNES is O(n^2) and only runs periodically: when items are below 100 or after 50 incremental inserts. Between rebuilds, new episodes insert in O(log N) by walking the tree and slotting into the best-matching branch.\n\n## Why Not Just Summarize?\n\n| | Summary-Based Compaction | Contexto (Hierarchical Clustering) |\n|---|---|---|\n| **What happens at compaction** | Oldest messages summarized into a shorter block | Episodes ingested into a semantic tree, originals evicted |\n| **Information loss** | Compounds over time (summaries of summaries) | None. Full episodes stored and retrievable |\n| **Cross-topic handling** | Unrelated episodes blended into one summary | Related episodes cluster together, unrelated stay separate |\n| **Retrieval** | Whatever the summary retained | Beam search across relevant topic branches |\n| **Token budget** | Summary must fit alongside new messages | Retrieval fills budget with the most relevant episodes |\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────┐\n│                   Your Agent                    │\n│  (OpenClaw, Claude Code, LangChain, custom, ...)│\n└──────────────────────┬──────────────────────────┘\n                       │\n                       v\n┌─────────────────────────────────────────────────┐\n│              @ekai/contexto                     │\n│         Sliding Window + Compaction             │\n│                                                 │\n│   Episodes buffered -\u003e compact at threshold     │\n│   -\u003e evict oldest -\u003e ingest to backend          │\n└──────────────────────┬──────────────────────────┘\n                       │  ContextoBackend interface\n                       v\n┌─────────────────────────────────────────────────┐\n│         Remote API  or  Custom Backend          │\n│         (api.getcontexto.com)                   │\n└──────────────────────┬──────────────────────────┘\n                       │\n                       v\n┌─────────────────────────────────────────────────┐\n│              @ekai/mindmap                      │\n│   AGNES Clustering + Beam Search Retrieval      │\n│                                                 │\n│   Episodes -\u003e semantic tree -\u003e query via beam   │\n│   search -\u003e token-budget-aware results          │\n└─────────────────────────────────────────────────┘\n```\n\n## Pluggable Backend\n\nThe context engine communicates with backends through the `ContextoBackend` interface:\n\n```ts\ninterface ContextoBackend {\n  /** Store one or more conversation events. */\n  ingest(payload: WebhookPayload | WebhookPayload[]): Promise\u003cvoid\u003e;\n  /** Search the mindmap for context relevant to the query. */\n  search(query: string, maxResults: number, filter?: Record\u003cstring, unknown\u003e, minScore?: number): Promise\u003cSearchResult | null\u003e;\n}\n```\n\nThe default `RemoteBackend` calls the hosted API at `api.getcontexto.com`. Implement the `ContextoBackend` interface to plug in your own storage and retrieval backend.\n\n## Packages\n\n```\ncontexto/\n├── packages/\n│   ├── contexto/         # @ekai/contexto — OpenClaw plugin, context engine\n│   ├── mindmap/          # @ekai/mindmap — AGNES clustering + beam search\n│   ├── memory/           # @ekai/memory — SQLite-backed memory kernel\n│   ├── openrouter/       # @ekai/openrouter — OpenAI-compatible proxy\n│   └── ui/dashboard/     # @ekai/ui-dashboard — Next.js monitoring dashboard\n├── docs/                 # Technical documentation\n├── CONTRIBUTING.md\n└── package.json\n```\n\n## Configuration\n\n| Property | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `apiKey` | string | Yes | | Your Contexto API key |\n| `compactionStrategy` | `'sliding-window'` \\| `'default'` | No | `'sliding-window'` | Compaction strategy |\n| `compactThreshold` | number (0-1) | No | `0.50` | Ingest + evict at this % of token budget |\n| `contextEnabled` | boolean | No | `true` | Enable/disable context injection |\n| `maxContextChars` | number | No | | Max characters for injected context |\n| `minScore` | number | No | | Minimum similarity score for retrieved results |\n\n## Roadmap\n\n- [x] OpenClaw plugin (`@ekai/contexto`)\n- [x] Hierarchical clustering with AGNES (`@ekai/mindmap`)\n- [x] Multi-branch beam search retrieval\n- [ ] RLM Plugin\n- [ ] **Document knowledge** — ingestion, chunking, retrieval\n- [ ] **Claude Code integration**\n- [ ] Benchmarks\n\n## Enterprise\n\nBuilding AI agents for your team or product? We work with companies deploying agents at scale to ensure they always have the right context.\n\n**[Talk to us](mailto:s@ekailabs.xyz)**\n\n## Contributing\n\nContributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Community\n\n- 💬 [Discord](https://discord.com/invite/5VsUUEfbJk) — Chat with the team\n- 📖 [Docs](https://docs.ekailabs.xyz/) — Documentation\n- 🐛 [Issues](https://github.com/ekailabs/contexto/issues) — Bugs \u0026 feature requests\n\n## License\n\nApache 2.0 — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekailabs%2Fcontexto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekailabs%2Fcontexto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekailabs%2Fcontexto/lists"}