routePrefix you configure (default: /api/persona). The middleware is a single catch-all: PersonaMiddleware handles every request under the prefix and forwards it to runtime.handle(). The runtime owns matching, params, and 404/405 — the adapter adds no routes of its own.
Always-on routes (end-user scoped)
Every route except
GET /health requires an authenticated user (401 when the resolver returns null or throws). For the exact SDK call each route proxies to, see the Runtime routes reference.
Opt-in admin routes
The Project-level admin surface (agents CRUD, providers, skills, knowledge, stores, MCPs, audit logs, architect) is off by default — it’s gated behindcapabilities.* on the runtime. When a capability is disabled, its routes are simply absent (a request 404s or 405s, never 403). See Runtime capabilities.
To expose the admin surface, register a second module with capabilities on and stricter auth:
PersonaModule.forRoot() with routePrefix: '/api/admin/persona' and stricter resolveUser in a separate feature module, or use PersonaService.runtime.handle() directly in an admin controller.
How the middleware translates a request
PersonaMiddleware translates the NestJS request to the runtime’s framework-neutral contract before runtime.handle() runs:
Error responses
- Runtime responses — including sanitized error envelopes
{"error":{code,message}}— are forwarded verbatim (status, headers, body). - Adapter translation failures (malformed JSON, unparsable multipart) respond
400 INVALID_REQUESTin the same envelope shape. - Any other adapter-side error is forwarded to NestJS’s exception filter — unless headers are already sent, in which case the connection is ended cleanly.
development vs production).