Supyagent
Package ReferenceSDK (Node.js)

Partner Guide

Use the SDK to manage connected accounts and act on behalf of your users with client.asAccount().

Partner Guide

Partners (platforms, SaaS apps) use a single API key to manage many end-user accounts. The SDK provides two distinct surfaces for this:

SurfaceAccess viaPurpose
Management planeclient.accounts.*Create accounts, initiate OAuth, manage integrations
Data planeclient.asAccount(externalId)Fetch tools/skills and make API calls scoped to a user

Setup

import { supyagent } from '@supyagent/sdk';

const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });

Managing Accounts

Use client.accounts to create and manage connected accounts. These methods never require an X-Account-Id header — they operate on your partner-level API key.

// Create an account for one of your users
const account = await client.accounts.create({
  externalId: 'user_123',
  displayName: 'Jane Smith',
  metadata: { plan: 'pro' },
});

// List all accounts
const { accounts, total } = await client.accounts.list({ limit: 50 });

// Get account with integrations
const details = await client.accounts.get(account.id);
console.log(details.integrations); // [{ provider: 'google', status: 'active', ... }]

OAuth Connect Flow

Initiate an OAuth session for a connected account, then redirect the user:

const session = await client.accounts.connect(account.id, {
  provider: 'google',
  redirectUrl: 'https://yourapp.com/callback',
  scopes: ['gmail.read', 'calendar.read'],
});

// Redirect user to session.connectUrl

Check the session status after the user returns:

const status = await client.accounts.getSession(account.id, session.sessionId);

if (status.status === 'completed') {
  console.log(`${status.provider} connected successfully`);
}

If you're using React, see the React hooks for useSupyagentConnect() and <ConnectCallback>.

Acting on Behalf of Users

Once a user has connected integrations, use client.asAccount() to fetch tools and skills scoped to that user. Every request from the scoped client automatically includes the X-Account-Id header.

const userClient = client.asAccount('user_123');

// Fetch tools scoped to this user's integrations
const tools = await userClient.tools({ cache: 300 });

// Or use skills (more token-efficient)
const { systemPrompt, tools: skillTools } = await userClient.skills({ cache: 300 });

// Check the user's account info
const me = await userClient.me();

The scoped client has tools(), skills(), and me() — but not accounts or asAccount(). Management stays on the parent client; nesting is not allowed.

Each scoped client has its own cache, separate from the parent and other scoped clients.

Using with Vercel AI SDK

app/api/chat/route.ts
import { streamText } from 'ai';
import { supyagent } from '@supyagent/sdk';
import { openai } from '@ai-sdk/openai';

const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });

export async function POST(req: Request) {
  const { messages, userId } = await req.json();

  // Get tools scoped to this user
  const userClient = client.asAccount(userId);
  const { systemPrompt, tools } = await userClient.skills({ cache: 300 });

  const result = streamText({
    model: openai('gpt-4o'),
    system: `You are a helpful assistant.\n\n${systemPrompt}`,
    messages,
    tools,
  });

  return result.toDataStreamResponse();
}

Full Next.js Example

End-to-end flow: create account, initiate OAuth, then use scoped tools.

app/api/integrations/connect/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { supyagent } from '@supyagent/sdk';

const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });

export async function POST(request: NextRequest) {
  const { userId, provider } = await request.json();

  // 1. Create or look up the connected account
  let account;
  try {
    account = await client.accounts.create({ externalId: userId });
  } catch {
    // Account already exists — look it up
    const { accounts } = await client.accounts.list();
    account = accounts.find((a) => a.externalId === userId);
  }

  if (!account) {
    return NextResponse.json({ error: 'Account not found' }, { status: 404 });
  }

  // 2. Create a connect session
  const session = await client.accounts.connect(account.id, {
    provider,
    redirectUrl: `${process.env.NEXT_PUBLIC_APP_URL}/integrations/callback`,
  });

  return NextResponse.json({ connectUrl: session.connectUrl });
}
app/api/chat/route.ts
import { streamText } from 'ai';
import { supyagent } from '@supyagent/sdk';
import { openai } from '@ai-sdk/openai';

const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });

export async function POST(req: Request) {
  const { messages, userId } = await req.json();

  // Scoped to the user's integrations
  const userClient = client.asAccount(userId);
  const tools = await userClient.tools({ cache: 300 });

  const result = streamText({
    model: openai('gpt-4o'),
    messages,
    tools,
  });

  return result.toDataStreamResponse();
}