@syncagent/nextjs
Next.js SDK for SyncAgent — server-safe helpers that keep your database connection string out of the browser bundle.
Works with MongoDB, PostgreSQL, MySQL, SQLite, SQL Server, and Supabase.

Get Your API Key
- Sign up for a free account
- Go to your Dashboard → New Project → choose your database type
- Copy your API key (starts with
sa_)
Every new project gets a 14-day trial with 500 free requests — no credit card required. After the trial, you get 100 free requests/month on the Free plan.
Install
npm install @syncagent/nextjs @syncagent/js @syncagent/react
Why Use This Instead of @syncagent/react?
The @syncagent/nextjs package provides createServerConfig() which lets you safely pass your database connection string from Server Components — it never reaches the browser bundle. All config options from @syncagent/js are supported.
Quick Start
import { createServerConfig } from "@syncagent/nextjs/server";
import { SyncAgentChat } from "@syncagent/nextjs";
import { getServerSession } from "next-auth";
export default async function DashboardPage() {
const session = await getServerSession();
const config = createServerConfig({
apiKey: process.env.SYNCAGENT_KEY!,
connectionString: process.env.DATABASE_URL!,
filter: { organizationId: session.user.orgId },
operations: session.user.isAdmin
? ["read", "create", "update", "delete"]
: ["read"],
});
return (
<SyncAgentChat
config={config}
persistKey={session.user.id}
accentColor="#6366f1"
context={{ userId: session.user.id, page: "dashboard" }}
/>
);
}
From Environment Variables
import { createServerConfigFromEnv } from "@syncagent/nextjs/server";
const config = createServerConfigFromEnv({
filter: { orgId: session.user.orgId },
language: "French",
});
# .env.local
SYNCAGENT_KEY=sa_your_api_key
DATABASE_URL=mongodb+srv://user:pass@cluster/db
All Config Options
createServerConfig accepts all SyncAgentConfig options:
apiKey | string | ✅ | Your SyncAgent API key |
connectionString | string | ✅* | Your database URL — stays on the server. *Optional when toolsOnly: true. |
filter | Record<string,any> | — | Mandatory query filter for multi-tenancy |
operations | string[] | — | Restrict operations for this session |
toolsOnly | boolean | — | Disables all DB tools — agent only uses custom tools |
systemInstruction | string | — | Custom agent instructions — personality, tone, rules |
confirmWrites | boolean | — | Ask for confirmation before writes |
language | string | — | Language the agent responds in (e.g. "French") |
maxResults | number | — | Default max records per query (default 50) |
sensitiveFields | string[] | — | Fields to mask in responses |
autoDetectPage | boolean | — | Auto-detect page from URL (default true) |
baseUrl | string | — | Override API URL (dev only) |
Full Example — Multi-tenant SaaS
import { createServerConfig } from "@syncagent/nextjs/server";
import { SyncAgentChat } from "@syncagent/nextjs";
import { getSession } from "@/lib/auth";
import { getOrganization } from "@/lib/db";
export default async function AppPage({ params }: { params: { orgSlug: string } }) {
const session = await getSession();
const org = await getOrganization(params.orgSlug);
const config = createServerConfig({
apiKey: process.env.SYNCAGENT_KEY!,
connectionString: process.env.DATABASE_URL!,
filter: { organizationId: org.id },
operations: session.user.role === "admin"
? ["read", "create", "update", "delete"]
: ["read"],
systemInstruction: `You are the AI assistant for ${org.name}. Be professional and helpful.`,
language: org.language || "English",
confirmWrites: true,
maxResults: 25,
sensitiveFields: ["ssn", "salary", "password"],
});
return (
<SyncAgentChat
config={config}
persistKey={`${org.id}-${session.user.id}`}
title={`${org.name} AI`}
accentColor={org.brandColor}
context={{ userId: session.user.id, userRole: session.user.role, orgName: org.name }}
/>
);
}
Tools-only Mode
import { createServerConfig } from "@syncagent/nextjs/server";
import { ChatWithTools } from "./chat-with-tools";
export default async function Page() {
const config = createServerConfig({
apiKey: process.env.SYNCAGENT_KEY!,
toolsOnly: true,
systemInstruction: "You are a product search assistant.",
});
return <ChatWithTools serverConfig={config} />;
}
import { SyncAgentChat } from "@syncagent/nextjs";
export function ChatWithTools({ serverConfig }) {
return (
<SyncAgentChat
config={{
...serverConfig,
tools: {
searchProducts: {
description: "Search products",
inputSchema: { query: { type: "string" } },
execute: async ({ query }) => {
const res = await fetch(`/api/products?q=${query}`);
return res.json();
},
},
},
}}
/>
);
}
Middleware Hooks (Client-side Only)
Functions like onBeforeToolCall can't be serialized from Server Components. Define them in a Client Component:
import { SyncAgentChat } from "@syncagent/nextjs";
export function Chat({ serverConfig }) {
return (
<SyncAgentChat
config={{
...serverConfig,
onBeforeToolCall: (name, args) => {
console.log(`[Audit] ${name}`, args);
return true;
},
}}
/>
);
}
Re-exported Components
All components and hooks from @syncagent/react are re-exported:
import { SyncAgentChat, SyncAgentProvider, useSyncAgent, SyncAgentClient } from "@syncagent/nextjs";
API Reference
createServerConfig(options) | SyncAgentConfig | Server only | Create config with all options |
createServerConfigFromEnv(overrides?) | SyncAgentConfig | Server only | Create config from SYNCAGENT_KEY + DATABASE_URL env vars |
Security
- Your database connection string is never stored on SyncAgent servers
createServerConfig ensures the connection string stays in the server bundle
- API keys are hashed with bcrypt — raw keys are never stored
- Never use
NEXT_PUBLIC_ prefix for your database URL
Plans & Pricing
| Free (+ 14-day trial) | 100 (500 during trial) | 5 | GH₵0 |
| Starter | 5,000 | 20 | GH₵150/mo |
| Pro | 50,000 | Unlimited | GH₵500/mo |
| Enterprise | Unlimited | Unlimited | Custom |
View full pricing →
Resources
License
MIT