@q1k-oss/context-engine
v0.3.2
Published
AI-powered knowledge graph engine that extracts and structures domain knowledge from conversations
Readme
Overview
Most agents keep their context in a transcript. That works until the transcript is longer than the window, and then you are summarising, and the details that mattered are the ones that get summarised away.
Context Engine keeps the context as a graph instead. As a conversation runs, it extracts entities, processes and business rules and writes them as nodes and edges. Upload a PDF or a spreadsheet and the same thing happens to its contents. Every change is versioned, so you can ask what the model believed at turn nine, and diff it against turn fourteen.
Reading back out, you ask for prioritised context rather than the last n messages — the
part of the graph that matters for the question at hand, serialised compactly with
@q1k-oss/mint-format. With Apache AGE enabled you can
also run Cypher over it: shortest paths, all paths, neighbours.
It is designed to be used as a library first: a Temporal worker imports it and calls its pure, side-effect-free functions in-process inside activities, keeping durability, retry, concurrency and persistence with the host. A standalone Express server is still provided for chat and graph use, but document ingestion is the host's job — the upload route and its async orchestration were removed in ADR-037.
Highlights
- Versioned knowledge graph — every mutation is a version, with deltas you can replay.
- Extraction from conversation and files — entities, processes and rules, plus PDFs, images and documents.
- Prioritised context retrieval — fetch the relevant subgraph by priority, not by recency.
- Cypher over Postgres — optional Apache AGE for path finding and neighbour queries.
- Pre-built LLM tools — 18 tool definitions with Zod schemas, ready to register with any tool-use loop.
- Pure extraction entrypoint —
@q1k-oss/context-engine/extractionexposes Docling extraction, MINT mapping and deterministic chunking with no DB or filesystem coupling. - Library or server — import the services directly, or run the Express app with SSE streaming for chat and graph.
Install
npm install @q1k-oss/context-engineRequires Node.js 18+ and a PostgreSQL database. Apache AGE is optional but enabled by default.
Quick start
import { initContextEngine, createApp } from '@q1k-oss/context-engine';
initContextEngine({
databaseUrl: process.env.DATABASE_URL!,
anthropicApiKey: process.env.ANTHROPIC_API_KEY,
googleAiApiKey: process.env.GOOGLE_AI_API_KEY,
});
const app = createApp({ corsOrigin: 'http://localhost:3000' });
app.listen(3001, () => console.log('Context Engine running on :3001'));Push the schema before the first run:
npx drizzle-kit pushUsage
Configuration
initContextEngine takes the whole configuration:
| Option | Required | Default | Description |
| --- | --- | --- | --- |
| databaseUrl | Yes | — | PostgreSQL connection string |
| anthropicApiKey | No | — | Anthropic API key for Claude, the reasoning engine |
| googleAiApiKey | No | — | Google AI API key for Gemini, used for file extraction |
| ageEnabled | No | true | Enable Apache AGE graph extensions for Cypher queries |
| uploadDir | No | './uploads' | Directory for file uploads |
Running the built-in standalone server (node dist/server.js) reads the same settings from
the environment instead:
| Variable | Description |
| --- | --- |
| DATABASE_URL | PostgreSQL connection string |
| ANTHROPIC_API_KEY | Anthropic API key for Claude |
| GOOGLE_AI_API_KEY | Google AI API key for Gemini |
| AGE_ENABLED | Set to 'false' to disable Apache AGE (default: enabled) |
| UPLOAD_DIR | File upload directory (default: './uploads') |
| CORS_ORIGIN | CORS origin (default: 'http://localhost:3000') |
| API_PORT | Server port (default: 3001) |
Using the services directly
You do not need the Express layer. Import the services and drive them yourself:
import {
initContextEngine,
chatOrchestratorService,
graphBuilderService,
entityExtractorService,
} from '@q1k-oss/context-engine';
initContextEngine({ databaseUrl: process.env.DATABASE_URL! });
const session = await chatOrchestratorService.createSession('My Agent');
for await (const event of chatOrchestratorService.processMessage(session.id, 'Build me a support agent')) {
if (event.type === 'text_delta') process.stdout.write(event.data.delta);
}
const graph = await graphBuilderService.getGraph(session.id);Registering the graph as LLM tools
The package ships tool definitions that plug into any tool-use system — Claude, OpenAI, or
your own loop. Each carries a Zod schema for validation and an execute function.
import { initContextEngine, contextEngineTools } from '@q1k-oss/context-engine';
initContextEngine({ databaseUrl: process.env.DATABASE_URL! });
for (const tool of contextEngineTools) {
register({
name: tool.name,
description: tool.description,
parameters: tool.parameters, // Zod schema
run: tool.execute,
});
}Import the groups individually if you want a narrower surface:
import { nodeTools, edgeTools, graphTools, aliasTools } from '@q1k-oss/context-engine/tools';Database setup
PostgreSQL is required. Set DATABASE_URL, then push the Drizzle schema:
npx drizzle-kit pushdocker-compose.yml in this repository brings up a plain PostgreSQL 16 for local work.
For Cypher queries you also need the Apache AGE extension on
that instance — either swap the image for apache/age, or set ageEnabled: false and skip
the Cypher endpoints.
API reference
Subpath imports
| Import | Contents |
| --- | --- |
| @q1k-oss/context-engine | Services, initContextEngine, contextEngineTools |
| @q1k-oss/context-engine/app | createApp — the Express application |
| @q1k-oss/context-engine/config | Configuration helpers |
| @q1k-oss/context-engine/db | getDb and the Drizzle client |
| @q1k-oss/context-engine/db/schema | Tables: sessions, knowledgeNodes, … |
| @q1k-oss/context-engine/extraction | doclingClientService, structureToMint, toMintDocument, chunkDocument |
| @q1k-oss/context-engine/tools | nodeTools, edgeTools, graphTools, aliasTools |
| @q1k-oss/context-engine/types | Session, KnowledgeNode and friends |
LLM tools
| Group | Tools |
| --- | --- |
| Node | create_node, get_node, update_node, delete_node, list_nodes, search_nodes |
| Edge | create_edge, get_edge, delete_edge, list_edges |
| Graph | get_graph, get_prioritized_context, get_graph_version, list_graph_versions, get_context_deltas, repair_orphans |
| Alias | add_alias, list_aliases |
HTTP endpoints
Available once you mount createApp().
Chat
| Method | Endpoint | Description |
| --- | --- | --- |
| POST | /api/chat/sessions | Create a session |
| GET | /api/chat/sessions | List sessions |
| GET | /api/chat/sessions/:id | Get session with messages |
| DELETE | /api/chat/sessions/:id | Delete session |
| POST | /api/chat/sessions/:id/messages | Send message (SSE stream) |
Knowledge graph
| Method | Endpoint | Description |
| --- | --- | --- |
| GET | /api/graph/:sessionId | Get full knowledge graph |
| GET | /api/graph/:sessionId/versions | List graph versions |
| GET | /api/graph/:sessionId/versions/:version | Get a specific graph version |
| GET | /api/graph/:sessionId/deltas | Get the context evolution timeline |
| GET | /api/graph/:sessionId/deltas/:deltaId | Get a specific delta |
| GET | /api/graph/:sessionId/context | Get prioritised context (?minPriority=0.3) |
| POST | /api/graph/:sessionId/repair-orphans | Repair orphan nodes via LLM semantic matching |
Apache AGE / Cypher — requires ageEnabled: true (the default).
| Method | Endpoint | Description |
| --- | --- | --- |
| GET | /api/graph/:sessionId/age | Get the graph from Apache AGE |
| GET | /api/graph/:sessionId/path | Find the shortest path (?from=&to=) |
| GET | /api/graph/:sessionId/paths | Find all paths (?from=&to=&maxHops=5) |
| GET | /api/graph/:sessionId/neighbors/:nodeId | Get node neighbours (?direction=both) |
| POST | /api/graph/:sessionId/cypher | Execute a read-only Cypher query |
Domain extraction
| Method | Endpoint | Description |
| --- | --- | --- |
| POST | /api/graph/domain/extract | Extract a complete domain graph from documentation |
| POST | /api/graph/domain/entities | Extract entities from documentation |
| POST | /api/graph/domain/processes | Extract processes and workflows |
| POST | /api/graph/domain/rules | Extract business rules |
Development
Architecture in one table:
| Piece | Role | | --- | --- | | Claude | Primary reasoning engine; receives conversation history plus graph context | | Gemini | File extraction only — PDFs, images, documents | | mint-format | Token-efficient serialisation of graph context into prompts | | Drizzle ORM | PostgreSQL schema and queries | | Apache AGE | Optional Cypher graph queries | | Express | HTTP API with SSE streaming | | Zod | Request validation and tool parameter schemas |
npm install
npm run dev # tsx watch src/server.ts
npm run build # tsc into dist/
npm run start # node dist/server.js
npm run db:generate # generate a migration from the schema
npm run db:migrate # apply migrations
npm run db:push # push the schema straight to the database
npm run db:studio # open Drizzle Studiodocker-compose.yml brings up PostgreSQL with Apache AGE for local work. Python helpers
used by the file-extraction path live in python/, configured through pyproject.toml.
Contributing
Contributions are welcome.
- Fork the repository and clone your fork.
- Create a branch:
git checkout -b feat/my-change. npm install, thennpm run buildto confirm the project still compiles.- Update this README for anything that changes the public surface.
- Commit using Conventional Commits and open a pull request.
Related projects
Context Engine is part of the q1k-oss family — see q1k.ai/oss.
| Package | What it does |
| --- | --- |
| @q1k-oss/mint-format | Token-efficient data format for LLM prompts |
| @q1k-oss/context-engine | Turns conversations and files into a versioned knowledge graph |
| @q1k-oss/behaviour-tree-workflows | Declarative behaviour trees in YAML, durable via Temporal |
| @q1k-oss/kiban | React components on Radix primitives and Tailwind |
