Implementation
A build prompt for an AI coding agent: exactly what to implement for the Knowledge subsystem, in what order, against which contracts. Hand the block below to an agent; the sections after it are the reference it should follow.
This page is an agent prompt
Every section in these docs gets an Implementation page — a precise, copy-paste task spec the agent executes. Read Overview and LightRAG first; they are the source of truth this prompt points to.
The prompt
ROLE: You are implementing the Knowledge subsystem of Agentfy.ai 2.0 (NestJS + Prisma + CleanSlice).
GOAL: Give each agent its own queryable knowledge base — the store's catalog, docs and policies —
backed by LightRAG (graph-RAG) running as a SEPARATE Python service. The NestJS `agent/knowledge`
slice is a THIN gateway: knowledge-base + document CRUD (metadata in Postgres), document feeding,
and proxied retrieval. Ingestion/graph/query collapse INSIDE LightRAG — they are NOT our sub-slices.
The agent reaches retrieval OVER MCP (a brain tool), not as part of the brain.
DELIVERABLES
1) `agent/knowledge` slice (api, L5) — CleanSlice structure:
- domain/: IKnowledgeGateway (abstract — KB/Document metadata, Prisma-backed),
IRagGateway (abstract — the LightRAG contract: insert/query/dropWorkspace),
knowledge.service.ts (orchestrates both), knowledge.types.ts (IKnowledgeBaseData,
IDocumentData, RetrievalModeTypes = naive|local|global|hybrid, DocumentStatusTypes), errors/.
- data/: knowledge.gateway.ts (Prisma impl of IKnowledgeGateway),
rag.gateway.ts (impl of IRagGateway → delegates to LightRagRepository + RagMapper),
lightRag.repository.ts (HTTP client wrapping the LightRAG service API — a REPOSITORY,
not a Prisma gateway: it wraps an external SDK/API), knowledge.mapper.ts.
- knowledge.prisma (KnowledgeBase, KnowledgeDocument), knowledge.controller.ts
(@Controller('knowledge-bases'); Swagger operationId on every route for SDK gen), dtos/.
2) MCP exposure — `@Tool` retrieval surfaced via `setup/mcp` (e.g. knowledge_search). ALL knowledge
access is over MCP; `agent/knowledge` is the only direct caller of LightRAG. TWO clients query the
same endpoint: the BRAIN (orchestrator, in-process, during the LLM loop) AND the WORKER (mid-task,
dialing the api MCP endpoint with its short-lived session token — no round-trip through the brain).
Both carry the same server-derived workspace, so isolation holds for either client.
3) Ingestion pipeline — feeding a document enqueues a budgeted `ingestion` job on `runtime/task`
(BullMQ); the consumer calls LightRAG insert and advances KnowledgeDocument.status. NEVER index
inline on the request path. Incremental: re-index only changed docs (catalog deltas).
4) LightRAG service deployment — Helm values for the HKUDS `lightrag` image on Postgres
(pgvector + Apache AGE), workspace-keyed instance pool. Borrow the Ranch chart (see reference).
CONTRACTS: implement exactly the rows, enums, repository client and job kind in the reference below.
Follow CleanSlice conventions (gateway vs repository, `I`-prefixed abstract DI tokens, singular slice
folders, `Types`-suffixed enums, camelCase DTO files, `#` aliases, no `any` — use `unknown` + guards).
SECURITY (non-negotiable): the workspace is ALWAYS derived from the authenticated team/kb on the api
side — NEVER accept a client-supplied workspace (empty/spoofed = cross-tenant leak). Workspace must be
non-empty. The `api` is the SOLE caller of the internal LightRAG service (network-isolated, no public
ingress). Deleting a KB tears down its workspace (delete-by-doc + drop the AGE graph).
ACCEPTANCE: see the checklist at the bottom. Start at the v0.x MVP scope.Reference — contracts to implement
Knowledge-base & document rows (Prisma, metadata only)
The corpus itself lives in LightRAG; Postgres holds only metadata + status:
model KnowledgeBase {
id String @id // = the LightRAG `workspace`
teamId String // tenant; workspace derived from this + id
agentId String? // null = team-shared base
name String
createdAt DateTime @default(now())
}
model KnowledgeDocument {
id String @id
baseId String // → KnowledgeBase.id
source String // catalog | upload | url
externalId String? // e.g. OpenCart product id (for incremental delta)
checksum String? // skip re-index when unchanged
status String // pending | indexing | indexed | failed
error String?
updatedAt DateTime @updatedAt
}Retrieval modes
RetrievalModeTypes = naive | local | global | hybrid. The caller (agent) picks per question; default hybrid. Cheap questions take naive (pure vector) — the cost-lean path from Overview → scaling.
MCP clients — brain and worker
Retrieval is reached only over MCP (agent/knowledge exposes the @Tools via setup/mcp; the api hosts the endpoint). Both the brain and the worker are clients:
| Client | Auth | Path |
|---|---|---|
Brain (orchestrator) | in-process | calls the MCP tool directly during the LLM loop |
| Worker (the hands) | short-lived session token | dials the api MCP endpoint mid-task; no round-trip through the brain |
The worker's token scopes it to its (agent, session), and the api derives the workspace from that — the worker never supplies one. So a worker querying knowledge gets the same isolation as the brain. (This supersedes the earlier "retrieval is brain-only" tool-split note — retrieval over MCP is open to both; what stays brain-only is secret/KEK material, never the worker.)
LightRAG repository (the external-service client)
lightRag.repository.ts wraps the LightRAG HTTP API — it has its own types, knows nothing about the domain, and is converted to domain types by RagMapper:
interface ILightRagRepository {
insert(workspace: string, docs: RagDoc[]): Promise<void>; // POST /insert
query(workspace: string, q: string, mode: string): Promise<RagHit[]>; // POST /query
dropWorkspace(workspace: string): Promise<void>; // KB teardown
}IRagGateway (domain) is the abstract contract; rag.gateway.ts (data) catches repository/HTTP errors and converts them to domain errors. workspace is passed in by the service — derived from the authed KB, never the client.
Ingestion job
ingestion (BullMQ, budgeted): { baseId, documentIds[] } → consumer loads docs, calls rag.insert(workspace, ...), advances KnowledgeDocument.status, respects a per-base token budget + rate limit. Lives in runtime/task; the same queue subsystem the Worker uses.
LightRAG service (deploy)
HKUDS ghcr.io/hkuds/lightrag on Postgres pgvector + AGE, LIGHTRAG_{KV,VECTOR,GRAPH,DOC_STATUS}_STORAGE=PG*, pinned version, fixed EMBEDDING_DIM. Instance pool keyed by workspace (lazy-init + idle-evict). Reference: cleanslice/ranch/k8s/platform/lightrag/* is ~working — adapt its Helm chart/values. See LightRAG and GitOps.
Ordered tasks
- v0.x MVP —
agent/knowledgeslice (Prisma KB/Document CRUD) ·LightRagRepository+IRagGateway(insert + query,hybrid) ·knowledge_searchMCP tool · one workspace per KB. Deploy the LightRAG service from the Ranch chart. Proves create base → feed doc → agent queries over MCP → grounded answer. - + Async ingestion — move insert onto the
ingestionBullMQ job with status tracking; never inline. - + Incremental & budget —
checksum/externalIddelta skip; per-base token budget + rate limit. - + Modes & cheap path — expose
naive|local|global|hybrid; default cheap, graph where it earns it. - + Lifecycle — KB delete →
dropWorkspace(delete-by-doc + drop AGE graph); cold-start warm/cache.
Acceptance criteria
- [ ] An agent retrieves grounded facts from its base over MCP (
knowledge_search), never inventing. - [ ] Both the brain (in-process) and a running worker (via its session token) can query the base over MCP, under the same workspace isolation.
- [ ] The
workspaceis derived server-side from the authed team/kb; a client cannot supply one. - [ ] One LightRAG service serves many bases via workspace-keyed instances; no cross-tenant leak.
- [ ] Feeding a document enqueues an ingestion job; the request path never blocks on indexing.
- [ ] Unchanged docs (matching
checksum) are skipped; only catalog deltas re-index. - [ ] LightRAG is wrapped as a Repository (external API);
agent/knowledgestays a thin gateway. - [ ] Deleting a KB tears down its workspace (drops the AGE graph); no orphaned vectors/graph.
See also
- Overview · LightRAG — the source of truth this prompt points to.
- Layered slices — where
agent/knowledge(L5) andruntime/tasksit. - Worker → Implementation — the sibling build prompt; same queue subsystem.
- Conventions — gateway-vs-repository and the CleanSlice rules the agent must follow.
- Infra → resources · GitOps — deploying the LightRAG service + Postgres.