Surfaces
The projects in the repository, the three ways a caller reaches the HTTP surface, groups mapped from your own directory, agents over MCP, and your own words on the tools.
| Project | What it is |
|---|---|
Premagentic.Core |
Connectors, chunker, embedding providers, migrations, gates, hybrid retrieval, the in-memory vector index |
Premagentic.Cli |
migrate (alias init-db), setup, remove, rebuild-index, ingest, search, section, eval, and administration: users, groups, agents, tokens, rules, settings, sources, extensions, profile, audit |
Premagentic.Api |
Sign-in through one seam (a password and a session, or a trusted header), search and section as the caller (POST /api/search, /api/section), and MCP over HTTP at /mcp for agent tokens |
Premagentic.McpServer |
A stdio bridge to /mcp for an agent that only speaks stdio, with an agent token read from a file; it holds no database credentials |
Premagentic.Tests |
Unit tests, plus the gates, identity, the datastore, the vector index and setup end to end on stock PostgreSQL |
Premagentic.Conformance |
xunit fixtures an extension author inherits to prove a reader, a chunker, a connector or an embedding provider keeps its contract |
samples/extensions/sentence-chunker |
A whole extension: a chunker, a .csv reader and a sign-in adapter that claims nothing, loaded by the tests from a folder by hash |
01Who is calling
Every request to the HTTP surface runs as a caller PremAgentic resolved itself, with that caller's groups and rules as they are at that moment. A request with no caller is refused with a 401. There are three ways to be one.
- A person signs in with a sign-in name and a password (
POST /api/session) and gets a session cookie: HttpOnly, Secure, SameSite=Strict. A session ends after 30 minutes idle or 8 hours at most, at sign-out, or the moment the account is disabled or given a new password. Password sign-in is refused over plain HTTP. Five wrong passwords lock an account for 15 minutes, failures are throttled by address, and every failure gets the same answer, so a caller cannot tell which names exist. A request that changes something under the cookie carries the anti-forgery token that sign-in returned, inX-Prem-Antiforgery. - An agent presents its token in
Authorization: Bearer prem_agt_.... It reaches what its registration gives it, is held to its requests per minute (counted by each API process separately), and sees machine-written content by the agents' trust setting or its own minimum tier. A revoked or expired token reaches nothing. - A trusted header, for a customer whose proxy already signs people in:
set
PREM_SIGN_IN_HEADERto the header the proxy writes the person's PremAgentic sign-in name into. PremAgentic resolves that user's groups from its own tables; an unknown or disabled name reaches nothing. With the mode on, only the proxy may reach the port, because a client that can set the header can name any user.
PremAgentic signs people in two ways out of the box: a password, which issues a session, and a trusted header, for a deployment where a proxy in front has already signed the person in. Both go through one seam, so a third way can be added as an extension without touching the core.
Whatever the way, it resolves a person to an account you already made. It never creates an account and never grants a role. A name PremAgentic does not know reaches nothing.
Groups from your own directory. If people sign in through a directory,
tell PremAgentic what its groups mean here: prem groups map "<the directory's
group>" <a PremAgentic group>. A group you have not mapped means nothing and
is ignored, so nobody gets access you did not write down. The same mapping
decides what a connector's permissions come to: a file readable by a group you
have mapped is readable by that PremAgentic group, and a file readable only by
groups you have not mapped is readable by nobody. An ingest run says how many
principals it met that mean nothing here, so a share whose groups were never
mapped does not look like an empty folder.
Behind a reverse proxy the API sees the proxy's address, so the address
throttle covers everyone behind it at once, and where TLS ends at the proxy
password sign-in is refused. Name the proxies in PREM_TRUSTED_PROXIES (see
Behind a reverse proxy) and the API believes their forwarding headers instead.
Agents connect over MCP at /mcp in the same process, with their token:
Streamable HTTP, MCP revision 2026-07-28, stateless. They get two read-only
tools, search_knowledge and get_document_section, and no tool that writes,
stores or remembers anything. For an agent that only speaks stdio,
Premagentic.McpServer is a bridge: it reads a token from the file named by
PREM_AGENT_TOKEN_FILE, forwards to PREM_API_URL, and holds no database
credentials.
Your own words on the tools. An assistant reads a tool's description to
decide whether to call it. Set mcp.tool_descriptions to name your own corpus
and the tools get called when they should be:
prem settings set mcp.tool_descriptions '{"search_knowledge": "Search the
Contoso handbook and client files."}'. It is read when the server starts.
Every result says what it is: trust tier, authorship, stale flag and concept id, on the HTTP surface, over MCP and in the CLI.