Skip to main content
@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.
The credential is server-side only. It lives behind @personaai/nextjs/server, which the root entry never re-exports — so it cannot reach a client bundle through this package. Keep it in PERSONA_CREDENTIAL (no NEXT_PUBLIC_ prefix).

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

One install covers both halves. The package ships ESM, CommonJS, and TypeScript declarations, and pulls in @personaai/runtime (the engine) and @personaai/react (the hooks) for you.

1. Mount the runtime — one route file

app/api/persona/[...persona]/route.ts
That’s the whole backend. The runtime surface now lives at /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
Every hook — 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:
A resolver returning 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-id header and GET /chat/:runId/resume power reconnects — see Streaming & disconnects.
  • Multipart uploads parsed with the platform’s own Request.formData() — no multer, no formidable. See Uploads.
  • Clean disconnects — a client hanging up mid-stream unsubscribes the runtime immediately.
  • Edge compatible — the server entry imports nothing from node:*, so export const runtime = 'edge' works (see Streaming).
  • Sanitized errors — runtime envelopes ({"error":{code,message}}) are forwarded verbatim; adapter-side failures (e.g. malformed JSON) respond 400 INVALID_REQUEST in the same shape.

Next steps