Connect Next.js

Install the SDK, configure your key, make your first authenticated call, and stream an agent

The @recursiv/sdk is a zero-dependency TypeScript SDK that runs in Server Components, API routes, and Client Components. This guide gets a Next.js app from install to a streaming agent.

Install

$npm install @recursiv/sdk

Configure the key

No account yet? Sign up and mint a key at recursiv.io/account/api-keys.

Keep the key server side. Put it in .env.local:

$RECURSIV_API_KEY=sk_live_...

The SDK reads RECURSIV_API_KEY automatically, so on the server you can just do new Recursiv(). You can also pass the key explicitly:

1import { Recursiv } from '@recursiv/sdk';
2
3const r = new Recursiv({ apiKey: process.env.RECURSIV_API_KEY });

First authenticated call

Most resources hang off a project. Create one, then run a query. Project IDs are UUIDs, so always use the id the API returns. Project-scoped calls return a { data } envelope.

1// app/api/setup/route.ts
2import { Recursiv } from '@recursiv/sdk';
3
4export async function POST() {
5 const r = new Recursiv();
6
7 const { data: project } = await r.projects.create({ name: 'my-app' });
8
9 await r.databases.ensure({ project_id: project.id, name: 'main' });
10
11 const { data: result } = await r.databases.query({
12 project_id: project.id,
13 sql: 'SELECT NOW() as time',
14 });
15
16 return Response.json({ project: project.id, rows: result.rows });
17}

Run and stream an agent

Create an agent against any model, then stream its replies. In Node and the browser use chatStream(), which yields an async iterable of { delta } chunks.

1// app/api/chat/route.ts
2import { Recursiv } from '@recursiv/sdk';
3
4export async function POST(req: Request) {
5 const { agentId, message } = await req.json();
6 const r = new Recursiv();
7
8 const encoder = new TextEncoder();
9 const stream = new ReadableStream({
10 async start(controller) {
11 for await (const chunk of r.agents.chatStream(agentId, { message })) {
12 controller.enqueue(encoder.encode(chunk.delta ?? ''));
13 }
14 controller.close();
15 },
16 });
17
18 return new Response(stream, {
19 headers: { 'Content-Type': 'text/plain; charset=utf-8' },
20 });
21}

Create the agent once (in setup, a script, or the dashboard):

1const { data: agent } = await r.agents.create({
2 project_id: project.id,
3 name: 'Support Bot',
4 model: 'anthropic/claude-sonnet-4.6',
5 system_prompt: 'You are a helpful assistant.',
6});

The model field is model agnostic. Pass any supported model id.

Where to go next