Every team has documents that only certain people should see. Sales contracts that aren’t finalized. HR policies under review. Engineering runbooks that reference internal infrastructure. Finance reports with sensitive projections.
The Orchestrator’s Knowledge module solves this with scoped, searchable documents – powered by vector embeddings and full-text search, filtered by your existing role-based permissions.
How It Works
Documents in the knowledge base are tagged with a scope and a visibility setting.
Scopes control which department can access a document:
- General – anyone with knowledge base access
- Sales – sales team only
- HR – human resources only
- Engineering – engineering team only
- Finance – finance team only
- Executive – leadership only
Scopes map directly to permission keys. A sales rep sees sales and general documents. A manager with both sales and HR permissions sees both. An executive with all scope keys sees everything.
Visibility adds a second layer:
- Shared (default) – visible to anyone with the matching scope permission
- Private – visible only to the person who created it
This is the contract scenario. A sales rep drafts a proposal, marks it private, iterates on it, then flips it to shared when it’s ready for the team.
Adding Documents
From the Web UI
Navigate to /knowledge in your browser. Click the + Add button to open the form.
Fill in:
- Title – a descriptive name for the document
- Scope – which department this belongs to
- Visibility – shared with the scope group, or private to you
- Content – the document text (plain text or markdown)
Click Save Document. The system automatically chunks the content, generates vector embeddings for semantic search, and indexes it for full-text keyword search.
From an AI Agent (MCP)
Any MCP-connected agent with the knowledge permission can add documents:
knowledge_add(
title: "Q2 Sales Playbook",
content: "...",
scope: "sales",
visibility: "shared"
)
The agent needs both the base knowledge permission and the scope-specific permission (e.g., knowledge_sales) to add documents to that scope.
From the REST API
POST /api/knowledge
Content-Type: application/json
{
"title": "Engineering Runbook v3",
"content": "Step 1: Check the dashboard...",
"scope": "engineering",
"visibility": "shared"
}
Returns the document ID on success.
From IEx
Knowledge.add("HR Policy Update", content, "hr", created_by: user_id, visibility: "private")
Importing Markdown Files
Already have documentation in markdown files? Import them directly instead of copy-pasting content.
From the Web UI
Open the + Add form, select the scope and visibility, then click Import .md. Pick a markdown file from your computer. The title is automatically extracted from the first # heading in the file. If there’s no heading, the filename is used as the title.
From an AI Agent (MCP)
knowledge_import(
filename: "onboarding-guide.md",
content: "# New Hire Onboarding\n\nWelcome to the team...",
scope: "hr",
visibility: "shared"
)
This is useful when an agent reads a file and imports it on your behalf.
From the REST API
JSON body (for scripts and programmatic access):
POST /api/knowledge/import
Content-Type: application/json
{
"filename": "runbook-v3.md",
"content": "# Deployment Runbook\n\nStep 1: ...",
"scope": "engineering"
}
Multipart file upload (for tools like curl):
curl -X POST https://yourserver/api/knowledge/import \
-H "Authorization: Bearer $TOKEN" \
-F "[email protected]" \
-F "scope=engineering" \
-F "visibility=shared"
Both approaches extract the title from the markdown heading automatically.
From IEx
content = File.read!("path/to/document.md")
Knowledge.import_markdown("document.md", content, "sales", created_by: user_id)
Bulk Import
For importing an entire directory of markdown files from IEx:
Path.wildcard("docs/sales/*.md")
|> Enum.each(fn path ->
content = File.read!(path)
filename = Path.basename(path)
Knowledge.import_markdown(filename, content, "sales", created_by: user_id)
end)
Searching
The knowledge base supports two search modes.
Semantic Search
Finds documents by meaning, not just keywords. Useful when you know what you’re looking for but don’t remember the exact words.
Web UI: Type your query in the search bar, select “Semantic” from the dropdown, and press Enter or click Search.
MCP: knowledge_search(query: "what are our pricing tiers")
REST: GET /api/knowledge/search?q=pricing+tiers&k=5
Results include a similarity score. The system over-fetches candidates from the vector index, then filters by your scope permissions and visibility – so you never see documents you shouldn’t.
Full-Text Search
Instant keyword matching using SQLite FTS5. No embedding needed – results come back immediately.
Web UI: Type your query, select “Text”, and search.
MCP: knowledge_search_text(query: "annual discount")
REST: GET /api/knowledge/search-text?q=annual+discount&k=10
Both search modes respect the same permission and visibility rules.
The Private Document Workflow
Here’s a concrete scenario.
Sarah is a sales rep working on a large deal. She adds the draft contract to the knowledge base:
knowledge_add(
title: "Acme Corp Master Agreement - DRAFT",
content: "...",
scope: "sales",
visibility: "private"
)
Only Sarah can see this document. Her colleagues on the sales team – who share the knowledge_sales permission – cannot find it through search or listing.
Sarah iterates on the contract over several days. Her AI agent can search her private documents to help refine terms, compare against previous deals, and flag inconsistencies.
When the contract is finalized and approved, the document visibility can be changed to shared, making it available to the entire sales team as a reference.
Permission Model
The knowledge base uses six permission keys, one per scope:
| Scope | Key | Who Gets It |
|---|---|---|
| General |
knowledge (120001) |
Everyone with knowledge access |
| Sales |
knowledge_sales (120002) |
Sales team |
| HR |
knowledge_hr (120003) |
HR team |
| Engineering |
knowledge_engineering (120004) |
Engineering team |
| Finance |
knowledge_finance (120005) |
Finance team |
| Executive |
knowledge_executive (120006) |
Leadership |
A user’s visible documents are the intersection of:
- Scopes they have permission keys for
-
Documents that are either
sharedor created by them (ifprivate) -
Documents that are
active(not deleted)
Admins can grant scope keys individually. A cross-functional manager might get knowledge_sales and knowledge_engineering but not knowledge_hr or knowledge_finance.
What Gets Indexed
When you add a document, the system:
- Chunks the content into ~2000-character segments with sentence overlap for context continuity
- Embeds each chunk using Voyager AI (1024-dimensional vectors) for semantic search
- Indexes each chunk in FTS5 with the document title for keyword search
Chunking happens synchronously. Embedding runs asynchronously – your document is searchable via full-text immediately, and via semantic search within a few seconds.
Viewing and Managing Documents
The /knowledge web page shows all documents you have access to, sorted by most recent. Each card displays:
- Document title
- Scope badge (color-coded by department)
- Private badge (if applicable)
- Chunk count and creation date
- Expandable content preview
Click a card to expand it. Click Delete to soft-delete (the document is marked inactive but retained for audit purposes).
AI Chat Integration
When you use the /chat feature, the LLM automatically searches the knowledge base before answering questions that could be answered by internal documents. You don’t need special syntax – just ask naturally.
The system prompt tells the LLM to:
- Search the knowledge base first for any domain-specific question
- Ground its response in the actual documents it finds
- Cite the document title when referencing results
-
Retrieve full documents with
knowledge_getif a chunk looks relevant but incomplete
For example, asking “what’s our vacation policy?” in chat will trigger a knowledge search, find the HR policy document (if you have knowledge_hr permission), and answer using the actual policy text rather than generic information.
Access Points
| Method | List | Search | Add | Import | Delete |
|---|---|---|---|---|---|
| Web UI |
/knowledge |
Search bar | + Add button | Import .md button | Delete button |
| MCP |
knowledge_list |
knowledge_search, knowledge_search_text |
knowledge_add |
knowledge_import |
knowledge_delete |
| REST |
GET /api/knowledge |
GET /api/knowledge/search, /search-text |
POST /api/knowledge |
POST /api/knowledge/import |
DELETE /api/knowledge/:id |
| IEx |
Knowledge.list_permitted/2 |
Knowledge.search/3, Knowledge.search_text/3 |
Knowledge.add/4 |
Knowledge.import_markdown/4 |
Knowledge.delete/1 |
Every access point enforces the same permission and visibility rules. There is no backdoor.