app.use('/api/persona', toExpressRouter(runtime)) forwards
every request under /api/persona/ to runtime.handle(). The runtime owns matching, params, and
404/405 (with Allow) — 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, mount a second runtime with capabilities on and stricter auth:
How the adapter translates a request
toExpressRouter maps an Express Request to the runtime’s framework-neutral contract before
runtime.handle() runs. The behaviors to know:
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 goes to
next(err)so your normal Express error middleware handles it — unless headers are already sent, in which case the connection is ended cleanly.
development vs
production).