Skip to main content
The adapter exposes the runtime’s entire route table under whatever catch-all route you create. app/api/persona/[...persona]/route.ts 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. Each HTTP method is a separate named export in Next.js, which is why the handler object is destructured:
app/api/persona/[...persona]/route.ts
All five are the same handler — they exist as five exports only because Next requires it. Omit one and Next answers 405 for that method before the runtime ever sees the request, so export all five unless you deliberately want a method blocked.
Do not also destructure runtime into a route-file export. Next.js treats a route-level runtime export as the segment runtime config ('nodejs' / 'edge'), and exporting an object there is a build error. Keep the handler object in a local variable if you need runtime.close().

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 behind capabilities.* 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, create a second catch-all route with capabilities on and stricter auth. toNextRouteHandlers is the primitive for that — it mounts an existing runtime rather than creating one:
app/api/admin/persona/[...persona]/route.ts
Your end-user route stays exactly as it was — two runtimes, two mounts, two auth policies.

How the adapter translates a request

The adapter maps the Web Request a route handler receives to the runtime’s framework-neutral contract before runtime.handle() runs. The behaviors to know:

Response translation

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_REQUEST in the same envelope shape.
  • runtime.handle() never throws for HTTP errors, so there is no third case to handle: anything the runtime can’t serve comes back as an error response, not an exception.
See Runtime errors for the two detail modes (development vs production).