Create a Knowledge Base Agent
This guide walks you through creating a Knowledge Base agent — an agent that searches an indexed set of your documents and answers with numbered citations back to the source document and page, instead of guessing.
Prerequisites
Section titled “Prerequisites”- Pinchy is running (see Quick Start)
- You have mounted at least one data directory (see Mount Data Directories)
- Local Ollama is connected under Settings → AI Provider → Ollama (Local) (see Set Up Local Ollama) — the knowledge base embeds your documents with a fixed local model served by that endpoint
- You are logged in as an admin
Your agents can chat on any provider you like — the knowledge base always embeds locally. But the local Ollama endpoint itself has to carry two models: the embedding model the knowledge base uses, and one tool-capable chat model. Connecting Ollama (Local) validates that a chat model is there, and refuses an endpoint that only has the embedding model with No models found. Pull a compatible model first. So pull both before you connect, even if none of your agents will ever chat on this endpoint.
1. Mount your data directories
Section titled “1. Mount your data directories”Before creating a Knowledge Base agent, make sure the documents you want the agent to access are mounted under /data/ in the Pinchy container. See the Mount Data Directories guide for detailed instructions.
2. Pull the models
Section titled “2. Pull the models”The knowledge base turns your documents into searchable passages using a fixed embedding model, bge-m3, served by the same local Ollama endpoint you configured above. Pull it once — together with a tool-capable chat model, which the Ollama (Local) connection requires:
ollama pull bge-m3ollama pull qwen2.5:7bAny tool-capable chat model satisfies the connection check; qwen2.5:7b is the one Pinchy suggests. Pull both before you connect the endpoint: with only bge-m3 present, saving the Ollama URL is refused and the knowledge base has no embedder to reach.
If bge-m3 isn't available when you trigger indexing (see below), the reindex request fails until it's pulled.
3. Navigate to "New Agent"
Section titled “3. Navigate to "New Agent"”In the Pinchy sidebar, click the + button next to "Agents" to open the agent creation form.
4. Select the "Knowledge Base" template
Section titled “4. Select the "Knowledge Base" template”Choose Knowledge Base from the template options. This template gives the agent the knowledge_search tool — a search over your indexed documents that returns citable passages, not raw file access.
5. Enter a name and create
Section titled “5. Enter a name and create”Give your agent a descriptive name, for example "HR Policy Assistant" or "Engineering Docs". You can also add an optional tagline like "Answers questions about company HR policies". Then click Create.
The agent is created with an auto-generated avatar and you are taken to its chat page. The Knowledge Base template pre-fills operating instructions (AGENTS.md) with cite-then-answer guidelines, but the agent doesn't know which documents to search yet — you scope that in the Permissions tab, then index those documents.
6. Configure directory access
Section titled “6. Configure directory access”Open the agent's settings by clicking the gear icon, then select the Permissions tab.

Under Knowledge Base, the Allowed Directories picker shows all directories found under /data/. Select the directories that contain the documents this agent should be able to search. This is the same folder scope that governs everything the agent can retrieve and cite — an agent can never search or cite a document outside its granted directories.
Click Save to apply the permissions.
7. Index the documents
Section titled “7. Index the documents”Granting a directory doesn't index it automatically — an admin has to trigger indexing. Call the reindex endpoint for the agent:
curl -X POST -b session_cookie "https://pinchy.example.com/api/agents/<agentId>/knowledge/reindex"This reads the agent's granted folders, extracts text from each PDF, splits it into overlapping chunks, embeds every chunk with bge-m3, and stores the result in Pinchy's own Postgres database (using pgvector) so it can be searched later.
Indexing is idempotent — unchanged files are skipped on the next run, changed files are re-indexed, and files removed from disk are dropped from the index. Re-run reindex whenever documents change — new files, edits, or deletions. There's no automatic file-watcher yet; a scheduled sweep is planned for a later phase.
The request comes back immediately with a job to watch:
{ "jobId": "6f1c2b64-6c3e-4a2f-9c19-5c1d3a1f2e77", "status": "pending", "pathCount": 2}Indexing itself runs in the background. It has to: every page has to be read, split, and turned into a vector, and on a few thousand documents that's hours of work on a CPU. Nothing about that fits inside an HTTP request, so the request queues the run and hands you its id.
One index run happens at a time, across your whole Pinchy — the index is shared, and embedding is CPU-hungry enough that two runs would only slow each other down. Trigger a second while one is going and you get a 409 naming the run that's in your way, including which agent it belongs to. That may not be the agent you asked about; watch that one instead of retrying.
8. Watch the run
Section titled “8. Watch the run”Ask the same endpoint how it's going:
curl -b session_cookie "https://pinchy.example.com/api/agents/<agentId>/knowledge/reindex"{ "job": { "status": "running", "processed": 340, "total": 1893, "counts": null }}total is every document we found across the granted folders, counted before the first one is read — so it doesn't move once the run starts. counts fills in as the run goes, so you don't have to wait until the end to see how it's going:
processed counts whole documents, so a long one holds the number still while we work through it — a 300-page PDF can sit there for minutes. That's the run being slow, not stuck.
| Field | What it means |
|---|---|
indexed | Added or updated, and searchable afterwards. |
skipped | Unchanged since the last run, left alone. |
removed | Gone from disk, dropped from the index. |
unsearchable | Read without error, but the file holds no text to search — nearly always a scanned PDF (see Scope in this release). |
failed | Couldn't be read or parsed at all. The run continues; if an earlier version of the file was indexed, that version stays searchable. |
indexed counts documents the agent can actually reach, not documents we processed — that's why a scanned PDF lands under unsearchable instead. If either of the last two numbers is above zero, part of your corpus can't answer questions yet, and it's worth knowing which part before someone asks it something.
A status of failed is a different thing from a failed file: it means something systemic stopped the whole run — the embedding endpoint went away, or the database did — and error says what. A broken file never gets that far; it's counted and stepped over.
If Pinchy restarts mid-run, the run resumes on the next start. Nothing is lost and nothing is done twice: everything already indexed is skipped on the way back through.
9. Chat with the agent
Section titled “9. Chat with the agent”Go back to the agent's chat and start asking questions. The agent calls knowledge_search behind the scenes, which runs a hybrid search — semantic (vector) and full-text — over the passages you indexed, then answers using only what it found.
Cite-then-answer
Section titled “Cite-then-answer”Every grounded answer cites its sources inline, like [1] and [2], and ends with a Sources list mapping each number to its document path and page:
**Sources:**
- [1] /data/handbook/policies/Employee Handbook.pdf — p. 12- [2] /data/handbook/policies/Employee Handbook.pdf — p. 14That makes every claim in the answer traceable back to a specific document and page, even though the underlying search results aren't shown in the chat.
Sources are named by their full path, not just the filename. In a real document tree a bare filename is often impossible to act on — you can't tell which of several folders it lives in, and two folders may hold files with the same name. The path is what lets you open the document and check the claim for yourself.
The list resolves exactly the numbers the answer cites — no more and no fewer. A number with no entry would be a dead end, and an entry the answer never cited would make a single source look like several.
Regression-protected
Section titled “Regression-protected”Citation accuracy isn't just a goal here — it's tested. Every change to the knowledge base runs against an automated test suite that checks retrieval quality (the right passages come back for a query) and citation integrity (every [N] in an answer resolves to a real, correctly-formatted source, and vice versa). A change that broke either would fail before it ships. We also track groundedness — whether an answer's claims are actually backed by what it cites — against a reference set of questions, so accuracy is measured over time, not just assumed.
Honest when it doesn't know
Section titled “Honest when it doesn't know”If the indexed documents don't contain the answer, the agent says so instead of guessing. If only part of a question is answered by the sources, it answers what's supported and flags what's missing rather than padding the rest.
Cross-language
Section titled “Cross-language”The agent answers in the language you asked in, even if the source documents are written in a different language.
Scope in this release
Section titled “Scope in this release”Phase 1 of the knowledge base is deliberately narrow:
- Only text-based PDFs are indexed and searchable via
knowledge_search. Scanned/image-only PDFs and Office documents (.docx, etc.) are on the roadmap, not indexed today. - There's no clickable link from a citation into the PDF viewer yet — citations are text (document path + page), not a jump-to-passage link.
- Indexing is a manual admin action (step 7). It runs in the background and reports progress, but you still have to ask for it — a scheduled sweep and a progress UI in the app are planned for a later phase.
Every retrieval and every reindex is recorded in the audit trail — each knowledge_search call as retrieval.query with the documents it drew on, and every reindex as two knowledge.reindex entries sharing a jobId: who asked for it, and how it turned out. Both are needed, because the run finishes long after the request that started it. The search query text itself is never stored in plaintext, only a one-way hash.
Customizing the agent
Section titled “Customizing the agent”Beyond permissions, you can customize your Knowledge Base agent through its settings tabs:
- General — Change the name, tagline, avatar, or model
- Personality — Choose a personality preset (e.g. The Professor for a formal tone) or write custom personality instructions
- Instructions — Edit the operating instructions that tell the agent how to cite documents and when to abstain
To add organization-specific context like team structure or terminology, go to Settings → Context. This context is applied to all shared agents, not configured per-agent.
Changing permissions later
Section titled “Changing permissions later”You can update an agent's permissions at any time by returning to the Permissions tab. Add or remove directories, then re-run the reindex step so the index matches the new folder set. Changes take effect after clicking Save.
How it works
Section titled “How it works”Under the hood, Pinchy uses an allow-list approach. The agent starts with no capabilities and only gets the tools an admin explicitly enables — here, knowledge_search, scoped by the same folder allowlist as everything else. For a full explanation, see Agent Permissions.