Skip to main content
@personaai/react is the official React SDK for Persona — a set of hooks and a context provider that let you build a full-featured chat UI against any Persona backend (Express, NestJS, or raw runtime) without writing fetch calls, SSE parsers, or state management by hand. v0.3.2, current release. Requires React 18+.

Install

Peer dependencies: react >= 18. No other packages are required.

Prerequisites

You need a running Persona backend — either:
On Next.js, install @personaai/nextjs instead of this package. It re-exports everything documented here behind a 'use client' boundary — same hooks, same provider, one install for both halves of the app.
The React SDK is a client-side package. It calls your backend’s HTTP routes (/chat, /threads, /files, /memory, /health, /agents) — it never talks directly to persona.hasanraiyan.me or holds any credential.

Set up the Provider

Wrap your app (or the subtree that needs chat) in <PersonaProvider>. It takes three things:
  • baseUrl — where your Persona backend is mounted (e.g. http://localhost:3000/api/persona)
  • getAuthToken — an async getter for the user’s Bearer token (Clerk, JWT, session, whatever your app uses). Omit if your backend doesn’t require auth.
  • defaultAgentId — optional; lets you skip passing agentId to every hook call.
The Provider is a standard React Context — it doesn’t render anything, just makes fetchWithAuth available to every hook downstream. Every hook must be called inside this provider.

Minimal chat example

Here’s a complete, working chat UI in one file — streaming messages, input box, and error handling:
That’s a fully working chat — streaming text, stop button, error display, and loading states. The useChat hook handles SSE parsing, message state, abort controllers, and thread management internally.

Adding thread history

Wrap your chat in a sidebar that lists past conversations:

How sendMessage works

sendMessage is the raw send function. It takes:
  1. content (optional) — the message text. If omitted, uses the current input value.
  2. overrideOptions (optional) — { agentId?, threadId?, resume? } to override the hook-level defaults for this specific send.
When threadId is not set and this is the first message, useChat will fail unless your backend supports implicit thread creation. Use useThreads().createThread() first if you need explicit thread management.

Handling interrupts (HITL & clarifications)

When the agent pauses for human-in-the-loop approval or a clarification question, the hook exposes an interrupt object. Render it and call resumeInterrupt when the user responds:

Full return value of useChat

Next steps

  • Hooks reference — every hook in depth, with full parameter/return docs.
  • Streaming events — the AG-UI event shapes useChat consumes, and how to use the onEvent callback.
  • Types reference — every exported type, interface, and alias.