Knowledge & RAG
The Knowledge Protocol — permission-aware RAG for agents via pluggable adapter plugins (memory, RAGFlow, custom)
Knowledge & RAG
Part of the AI module — how agents retrieve knowledge through the Knowledge Protocol and its adapter plugins.
ObjectStack ships a Knowledge Protocol that lets you retrieve from pluggable backends (RAGFlow, LlamaIndex, Dify, custom pgvector, …) with one call: KnowledgeService.search(query, { sourceIds?, topK? }). The framework defines the contract and runs permission-aware filtering; the adapter plugin does the actual retrieval. See the protocol design for the rationale.
This whole stack is open. The @objectstack/service-knowledge service, the adapter plugins (@objectstack/knowledge-memory, @objectstack/knowledge-ragflow), the @objectstack/embedder-openai embedder, and the permission-aware retrieval + event sync below all ship in the open-source framework. The workflow is: declare your knowledge sources, pick an adapter, and call search — retrieval respects the same row-level security as any ObjectQL query. Only the in-product chat runtime that consumes retrieval ships in ObjectOS; see the callout under Retrieving knowledge.
Wiring
import { ObjectKernel } from '@objectstack/core';
import { KnowledgeServicePlugin } from '@objectstack/service-knowledge';
import { KnowledgeMemoryPlugin } from '@objectstack/knowledge-memory';
// or, for prod:
// import { KnowledgeRagflowPlugin } from '@objectstack/knowledge-ragflow';
const kernel = new ObjectKernel();
kernel.use(new KnowledgeServicePlugin({
sources: [
{
id: 'task_notes',
label: 'Task notes',
adapter: 'memory',
source: { kind: 'object', object: 'task', contentFields: ['title', 'notes'] },
},
{
id: 'product_docs',
label: 'Product docs',
adapter: 'ragflow',
source: { kind: 'http', urls: ['https://docs.example.com/sitemap.xml'] },
options: { datasetId: 'rgf_doc_dataset' },
},
],
}));
kernel.use(new KnowledgeMemoryPlugin());
// kernel.use(new KnowledgeRagflowPlugin({ endpoint, apiKey }));Retrieving knowledge
Retrieval is a plain service call — no AI runtime required. Resolve the knowledge
service and call search. Hits are re-checked against the caller's
ExecutionContext (RLS), sorted by score, and capped at topK before they come
back.
const knowledge = ctx.getService('knowledge');
const hits = await knowledge.search('proposals about ACME', {
sourceIds: ['task_notes', 'product_docs'], // optional — defaults to every source the caller may see
topK: 5,
executionContext, // the caller's context — retrieval drops any hit RLS would hide
});
// hits: KnowledgeHit[] — each { chunkId, documentId, sourceId, sourceRecordId?, score, snippet, title? }In-product chat ships in ObjectOS. Exposing this retrieval to a chat UI as
the search_knowledge tool — the ask / build personas, the /api/v1/ai/*
endpoints, and aiService.chatWithTools — is provided by the ObjectOS
in-product runtime. The
open-source framework has no built-in in-product chat, but everything else here — the Knowledge
Protocol, adapters, embedder, and KnowledgeService.search — is open, so you can call
search directly from your own code, agent, or MCP tool.
What you get for free
- Permission-aware retrieval. Every hit with a
sourceRecordIdis re-checked against the caller'sExecutionContextviaIDataEngine— the same RLS that gates plain ObjectQL queries. A salesperson asking "find proposals about ACME" only sees the proposals they could already read directly. File / HTTP hits pass through (ACL is the adapter's problem). - Inline event sync. When records on indexed objects change, the kernel's
IRealtimeServiceevents driveKnowledgeService.handleRecordUpsert/Deleteautomatically. No cron, no queue (yet — Phase 2). - Adapter swap, zero caller changes. Move from
memorytoragflowto a custom adapter without touching yoursearchcalls, thesearch_knowledgetool, or any agent prompt.
Why we did not build a vector DB
Mature OSS (RAGFlow, LlamaIndex, Dify) already nail chunking, embedding, hybrid retrieval, rerank, and OCR. ObjectStack's value is the metadata-native source declaration + the permission-aware filter on top of those engines — not yet-another-RAG-stack. Customers pick the retrieval engine that matches their data; we make sure it talks to ObjectStack the same way every time.