@personaai/nextjs is the one package a Next.js app installs. One App Router catch-all route
file is the entire backend integration — AG-UI streaming chat, threads, files, memory, MCP OAuth
callbacks, health — and the same package’s root entry gives you <PersonaProvider> and every
React hook on the client.
It’s a thin translation layer: all logic lives in the runtime. If
you need a raw call the adapter doesn’t cover, drop down to
@personaai/sdk in a server action or route handler alongside it.
Prerequisites
- Next.js 14+ with the App Router, Node.js 18+
- A Project credential shaped
"<keyId>.<secret>", minted in Developer Studio - An Agent to talk to (create one in Studio, or via the SDK’s
agents.create)
Install
@personaai/runtime (the engine) and @personaai/react (the hooks) for you.
1. Mount the runtime — one route file
app/api/persona/[...persona]/route.ts
/api/persona/*:
The complete route table is in the Next.js routes reference, and the
underlying SDK calls each route proxies to are in the
Runtime routes reference.
The catch-all segment can be named anything (
[...persona], [...slug]) and mounted anywhere
(app/api/ai/[...slug]/route.ts). The adapter reads the segments Next hands it, so the path
resolves correctly either way — just point the provider’s baseUrl at the same place.2. Wrap your layout
PersonaProvider ships behind a 'use client' boundary, so it drops straight into a server
layout — no wrapper file of your own:
app/layout.tsx
baseUrl is the path you mounted the route at. Because it’s same-origin, the browser’s own
session cookie authenticates every call — the resolver in step 1 reads it server-side.
3. Chat
app/chat/page.tsx
useChat, useThreads, useFiles, useMemory, useAgents, useMcpConnections —
imports from @personaai/nextjs. They are the React SDK’s hooks
re-exported verbatim; that reference is the one to read for their full APIs.
The two entry points
The split is a safety boundary as much as an ergonomic one: nothing server-side is re-exported
from the root, so your credential can’t reach the browser through it.
Telling the runtime who a request is from
Persona never authenticates users. The runtime asks you who a request is from — see the auth guide for the full picture. Both idioms in brief:resolveUserFrom(req) — the Next.js-native choice, shown above. It receives the Web Request,
but most Next auth libraries read the session from async context, so it usually ignores its
argument entirely.
resolveUser(request) — the general runtime-level resolver; it receives the translated
request, so you read request.headers / request.query yourself:
null (or throwing) makes the runtime respond 401. Every route except
GET /health requires an authenticated user.
Lifecycle hooks
All eight hooks (beforeRun, afterRun, onError, beforeToolCall, afterToolCall,
onFileUpload, onThreadCreate, onMemoryWrite) pass straight through to the runtime — see the
Runtime Hooks reference:
What you get for free
- SSE streaming with heartbeats and platform-native backpressure; the chat
x-persona-run-idheader andGET /chat/:runId/resumepower reconnects — see Streaming & disconnects. - Multipart uploads parsed with the platform’s own
Request.formData()— nomulter, noformidable. See Uploads. - Clean disconnects — a client hanging up mid-stream unsubscribes the runtime immediately.
- Edge compatible — the server entry imports nothing from
node:*, soexport const runtime = 'edge'works (see Streaming). - Sanitized errors — runtime envelopes (
{"error":{code,message}}) are forwarded verbatim; adapter-side failures (e.g. malformed JSON) respond400 INVALID_REQUESTin the same shape.
Next steps
- Auth & user resolution — resolver patterns, middleware ordering,
401s. - Routes — every route the mount exposes, and translation details.
- Uploads — multipart parsing and body-size limits.
- Streaming & disconnects — SSE, backpressure, reconnect, Edge.
- React SDK reference — the hooks this package re-exports.
- UI components — drop-in chat surfaces built on those hooks.