Permissions in every search
Each search returns only what the caller may see. A person sees what their access allows; a project key reads its own project and nothing outside it.
Context Engine · ingestion and retrieval
Put your documents in, then ask. The promptev Context Engine finds the right passages, keeps only what the person or key asking may see, and cites the source of each one. Use it from the Python or JavaScript SDK, over HTTP, or through your project’s MCP server. We run it for you.
Why it matters
A search that does not know who is asking returns the nearest rows in the whole corpus, and the permission filter runs on what came back. When a team's documents sit together in the embedding space, that limit goes almost entirely on rows the caller may not read. Fetching more helps less than it should, for the same reason. Below: one query, how far the search reached, and who is inside it.
2 of 20 permitted rows returned · 18 withheld Measured recall 0.084.
Search first, filter afterwards. The search does not know who is asking, so it spends its limit on the nearest rows in the whole corpus. Those belong overwhelmingly to other groups, and the filter removes them. Measured: recall 0.084, and 63.5% of searches came back with nothing at all. No error is raised.
The usual workaround. Fetch ten times more, then filter. Watch the ring grow. It helps, by an amount that depends on where the caller’s documents sit: with team-shaped permissions the measured recall was 0.419, with 13.0% of searches still empty. The same fetch under randomly assigned permissions recovered 0.730, which is why a benchmark with random permissions makes this look safer than it is.
The fix. The permission is part of the search itself, so only what this caller may read is ever ranked. Measured: the same top ten as a corpus holding only the caller’s documents, on every one of 200 searches. That is agreement with such a corpus, not relevance.
Measured on 100,000 documents from BEIR HotpotQA (100,646 chunks) with hybrid search at its default settings, 200 searches, and synthetic team-shaped permissions under which the caller sees 10% of the corpus. Recall is agreement with a corpus that holds only the caller’s documents, not relevance. Drop visibility to 1% and filtering after the search returns nothing at all for 99.0% of searches: not a degraded answer, an empty one. The plot illustrates a single query on a toy corpus. The recall readout is the measured figure, and the result slots are that same figure drawn on 20 slots.
Use it from your code
Make a project API key in the promptev console. The key reads and writes only its own project. Upload a document, then search it with the same knowledge tool your agents and your MCP clients use.
from promptev import PromptevClient
client = PromptevClient(api_key="fk_...")
# Ingestion: put a document into the project's knowledge
doc = client.upload_document("handbook.pdf")
print(doc.status, doc.chunks)
# Retrieval: search it (only what this key may see)
found = client.search_knowledge_base("search", query="how many days do customers have to ask for a refund", top_k=5)
for hit in found["hits"]:
print(hit["document_name"], hit["score"])import { readFile } from "node:fs/promises";
import { PromptevClient } from "@promptev/client";
const client = new PromptevClient({ apiKey: "fk_..." });
// Ingestion: put a document into the project's knowledge
const { results } = await client.uploadDocument([
{ name: "handbook.pdf", content: await readFile("handbook.pdf") },
]);
// Retrieval: search it (only what this key may see)
const found = await client.searchKnowledgeBase("search", { query: "how many days do customers have to ask for a refund", top_k: 5 });
for (const hit of found.hits) console.log(hit.document_name, hit.score);Over plain HTTP the same two steps are POST /api/v1/documents (multipart files) and POST /api/v1/knowledge (a JSON body such as {"action": "search", "query": "how many days do customers have to ask for a refund", "top_k": 5}) on https://api.promptev.ai, with the key as a Bearer token. Every project is also an MCP server: its search_knowledge_base tool is the same tool with the same actions, and upload_document adds a file. Beyond search there are actions to discover what the knowledge holds, read a whole document, list, count and sum, and follow the Context Graph from one person, product or contract to the next.
What it is
The same engine sits under every promptev agent. Connectors keep sources such as Google Drive, SharePoint, OneDrive, Slack, Dropbox and Atlassian in sync, and your own uploads join them. There is no permissive default: every search says who is asking.
Each search returns only what the caller may see. A person sees what their access allows; a project key reads its own project and nothing outside it.
Every hit names its document, so answers cite their sources. Upload with graph mode and the engine also maps people, products and their relationships.
Keep the knowledge in your own database, and use your own embedding model, your own OCR model and your own extraction model for the Context Graph, on your own keys.
Python, JavaScript, HTTP and MCP reach the same knowledge tool, with the same actions. What you build on one works on the others.
Cost is in credits at $0.005 each. Ingestion is 1 credit per page, slide or MB (at least 1). A knowledge call is 1 credit, plus 1 for a search, or 5 when the search uses the Context Graph. Through the SDKs and the API a knowledge call carries no extra API charge. The rates are the same for a workspace on its own database or models.
Start here
Start with 1,000 free credits for a 30-day trial and no card. Upload your documents in the app, or make a project key and use the SDKs, the API or MCP.