How It Works
Onprest separates two questions. The gateway answers “who may call what”. The agent answers “what does this capability do, and what may it return”. Keeping these apart is what lets the public side stay useful without holding anything sensitive.
[API client / AI agent]
|
| REST / MCP / OpenAPI
v
[onprest-gateway]
^
| WebSocket, opened outbound by the agent
|
[onprest-agent + capability.yaml]
|
v
[database / folder / internal API / Wasm module]Components
| Component | Runs | Does |
|---|---|---|
onprest-gateway | Where callers and the agent can reach it | Authenticates API keys, authorizes capabilities, serves REST, MCP, OpenAPI, and /healthz, and accepts the agent’s connection |
onprest-agent | Inside the on-prem network, next to the systems it uses | Loads capability.yaml, prepares the sources it references, runs capabilities, and keeps detailed errors in a local log |
capability.yaml | With the agent | Defines every operation that can exist, its sources, input, limits, and output |
Both are single static binaries. Neither needs the other’s configuration, and neither stores application data in a database.
A request, step by step
- A client calls
POST /api/v1/capabilities/get_customeror the MCP toolget_customerwith an API key. - The gateway checks the key and whether it may call
get_customer, then forwards the name and input to the connected agent. - The agent checks that the capability exists and validates the input against its schema and policy.
- The agent runs the capability’s executor: the SQL statement, the folder read, the HTTP call, or the Wasm module.
- The agent selects and validates the declared output, and only that leaves the network.
- The gateway returns the result to the client and writes one log line without params or result data.
The agent loads capability.yaml at startup and runs from that definition until it restarts. When the agent connects, the gateway fetches the public contract (input and output schemas, descriptions) and builds OpenAPI and the MCP tool list from it.
Who holds what
| Concern | Gateway | Agent |
|---|---|---|
| Public REST / MCP / OpenAPI endpoint | Yes | No |
| API key authentication | Yes | No |
| Capability authorization | Yes | Yes |
| Rate limiting | Per source IP | Per capability |
| Request log | Yes | No |
| Public capability contract | Cached copy, filtered per API key | Source |
| SQL, folder roots, upstream URLs, Wasm modules | No | Yes |
| Database and API credentials | No | Yes |
| Raw database schema knowledge | No | Yes |
| Input validation | Ingress check against the contract | Full validation before execution |
| Execution policy and output selection | No | Yes |
| Detailed errors | No | Local log only |
| Agent private key | No | Yes |
| Agent public key | Yes | No |
Trust boundary
Onprest assumes the gateway may be observed or compromised. An attacker who controls it learns the public contract of each capability, but cannot read SQL or credentials, cannot invent an operation outside capability.yaml, and cannot bypass the input validation, policy, or output selection the agent enforces.
The agent is the trust boundary. What a capability can reach is limited by the agent’s configuration and its operating-system permissions; Security explains how to keep each executor narrow.
One gateway per customer
Run a dedicated gateway process for each customer or trust domain. API keys, the agent public key, the cached contract, and logs then belong to one environment, and the operational unit matches the trust boundary. A gateway accepts one agent connection at a time.
Network and TLS
TLS termination and the network edge are yours to choose; see Reverse Proxy. The agent always connects outbound and must use wss:// unless the gateway is on the same host. Database and upstream API TLS are configured separately on the agent.
Managed products and dashboards are outside the OSS core and are not dependencies of either binary.