Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@syncagent/js

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@syncagent/js

SyncAgent JavaScript SDK — AI database agent for any app

Source
npmnpm
Version
0.3.3
Version published
Weekly downloads
532
164.68%
Maintainers
1
Weekly downloads
 
Created
Source

@syncagent/js

Core JavaScript/TypeScript SDK for SyncAgent — add an AI database agent to any app.

Install

npm install @syncagent/js

Quick Start

import { SyncAgentClient } from "@syncagent/js";

const agent = new SyncAgentClient({
  apiKey: "sa_your_api_key",
  connectionString: process.env.DATABASE_URL,
  // baseUrl: "http://localhost:3100", // dev only — defaults to https://syncagent.dev
});

const result = await agent.chat([
  { role: "user", content: "How many users do we have?" }
]);
console.log(result.text);

Configuration

new SyncAgentClient(config: SyncAgentConfig)
OptionTypeRequiredDescription
apiKeystringYour SyncAgent API key (sa_...)
connectionStringstringYour database URL — sent at runtime, never stored
toolsRecord<string, ToolDefinition>Custom tools the agent can call client-side
baseUrlstringOverride API URL. Defaults to https://syncagent.dev
filterRecord<string, any>Mandatory query filter — scopes ALL operations to matching records. Use for multi-tenant SaaS.
operations("read"|"create"|"update"|"delete")[]Restrict which operations are allowed for this session. Must be a subset of the project's configured operations.
toolsOnlybooleanWhen true, disables all built-in DB tools — the agent only uses your custom tools. connectionString becomes optional.
autoDetectPagebooleantrueAuto-detect current page from window.location and include in context. Set false to disable.
systemInstructionstringCustom instructions for the agent — personality, tone, rules. Prepended to system prompt.
confirmWritesbooleanfalseWhen true, agent asks for explicit user confirmation before any create/update/delete.
languagestringLanguage the agent responds in. E.g. "French", "Spanish", "Japanese".
maxResultsnumber50Default max records per query. Set lower for mobile, higher for dashboards.
sensitiveFieldsstring[]["password","token","secret"]Fields the agent masks as "••••••••" in responses.
onBeforeToolCall(name, args) => booleanCalled before each client tool executes. Return false to block.
onAfterToolCall(name, args, result) => voidCalled after each client tool executes. Use for logging/analytics.

client.chat(messages, options?)

const result = await agent.chat(messages, options);

messagesMessage[]

{ role: "user" | "assistant"; content: string }

optionsChatOptions

OptionTypeDescription
onToken(token: string) => voidCalled for each streamed text chunk
onComplete(text: string) => voidCalled with the full response text
onError(error: Error) => voidCalled on error
onStatus(step: string, label: string) => voidCalled with live status updates while working
onData(data: ToolData) => voidCalled when a DB tool returns structured data
onToolCall(name: string, args: any, result: any) => voidCalled when a custom tool executes
signalAbortSignalCancel the request
contextRecord<string, any>Extra context injected into every message

Returns Promise<ChatResult>{ text: string }

Status steps

onStatus fires with these step values:

  • "connecting" — connecting to the database
  • "schema" — discovering schema
  • "thinking" — AI is reasoning
  • "querying" — executing a DB tool
  • "done" — complete

client.getSchema()

const schema = await agent.getSchema();
// CollectionSchema[]

Context injection

The SDK automatically detects the current page from window.location on every message. The agent knows what page the user is on, what record they're viewing, and any relevant query params — with zero developer code.

URL: /dashboard/orders/ord_123?tab=details

Auto-detected context:
  currentPage: "orders"
  currentPath: "/dashboard/orders/ord_123"
  currentRecordId: "ord_123"
  param_tab: "details"

The user can now say "show me this order" and the agent knows to query ord_123.

You can also pass additional context that merges on top of the auto-detected values:

await agent.chat(messages, {
  context: {
    userId: "user_123",
    userRole: "admin",
    orgName: "Acme Corp",
  }
});

To disable auto-detection:

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  autoDetectPage: false, // only use manually passed context
});

Context is sent as a dedicated field in the request body and injected into the AI system prompt — not appended to the user's message text.

onData callback

React to structured query results in your own UI:

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
});

await agent.chat(messages, {
  onData: (data) => {
    // data.tool — "query_documents" | "aggregate_documents"
    // data.collection — e.g. "orders"
    // data.data — array of result rows
    // data.count — number of results
    console.log(`Got ${data.count} rows from ${data.collection}`);
    setTableData(data.data); // update your own table component
  }
});

Custom Tools

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  tools: {
    sendEmail: {
      description: "Send an email to a user",
      inputSchema: {
        to:      { type: "string", description: "Recipient email" },
        subject: { type: "string", description: "Subject line" },
        body:    { type: "string", description: "Email body" },
      },
      execute: async ({ to, subject, body }) => {
        await mailer.send({ to, subject, text: body });
        return { sent: true };
      },
    },
  },
});

Multi-tenant SaaS — scoping queries per organization

When building a SaaS app, multiple organizations share the same database. Pass filter to scope every agent operation to the current user's organization. The agent cannot query, insert, update, or delete outside this scope — it's enforced server-side.

import { SyncAgentClient } from "@syncagent/js";

// Scope to the current user's organization
const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  filter: { organizationId: currentUser.orgId },
});

// Every query is now automatically scoped:
// "Show all orders" → db.orders.find({ organizationId: "org_123" })
// "Count users"     → db.users.countDocuments({ organizationId: "org_123" })
// "Add a product"   → db.products.insertOne({ ...doc, organizationId: "org_123" })

Without filter — agent queries everything (suitable for single-tenant apps or admin tools).

With filter — every read, write, update, and delete is strictly scoped. The agent is told about the scope in its system prompt and cannot override it.

Common patterns:

// By organization ID
filter: { organizationId: org.id }

// By tenant slug
filter: { tenant: "acme-corp" }

// By user ID (personal data)
filter: { userId: currentUser.id }

// Multiple fields
filter: { orgId: org.id, deleted: false }

// SQL databases (same syntax)
filter: { tenant_id: tenant.id }

Multi-turn conversations

const history: Message[] = [];

history.push({ role: "user", content: "Show top 5 customers" });
const r1 = await agent.chat(history);
history.push({ role: "assistant", content: r1.text });

history.push({ role: "user", content: "Now email all of them" });
const r2 = await agent.chat(history);

Abort / cancel

const controller = new AbortController();
agent.chat(messages, { signal: controller.signal });
controller.abort(); // cancel at any time

TypeScript types

import type {
  SyncAgentConfig, Message, ChatOptions, ChatResult,
  CollectionSchema, SchemaField, ToolDefinition, ToolParameter, ToolData,
} from "@syncagent/js";

License

MIT

Per-user operation restrictions

Use operations to give different users different levels of access within the same project. The client can only restrict further — it can never grant more than what the project dashboard allows.

// Read-only for regular users
const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  filter: { organizationId: currentUser.orgId },
  operations: ["read"],
});

// Full access for admins
const adminAgent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  filter: { organizationId: currentUser.orgId },
  operations: ["read", "create", "update", "delete"],
});

Tools-only mode

When you want the agent to only use your custom tools — with no database access at all — set toolsOnly: true. This is useful when you want to build an AI assistant powered by your own APIs, webhooks, or business logic.

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  toolsOnly: true, // no connectionString needed
  tools: {
    searchProducts: {
      description: "Search products by name or category",
      inputSchema: {
        query: { type: "string", description: "Search query" },
      },
      execute: async ({ query }) => {
        const res = await fetch(`/api/products?q=${query}`);
        return res.json();
      },
    },
    createOrder: {
      description: "Create a new order for a customer",
      inputSchema: {
        productId: { type: "string", description: "Product ID" },
        quantity:  { type: "number", description: "Quantity" },
      },
      execute: async ({ productId, quantity }) => {
        const res = await fetch("/api/orders", {
          method: "POST",
          body: JSON.stringify({ productId, quantity }),
        });
        return res.json();
      },
    },
  },
});

// The agent will ONLY call searchProducts and createOrder.
// No database queries, no schema discovery, no DB connection.

You can also combine toolsOnly with a connectionString if you want — the DB connection is simply skipped when toolsOnly is enabled.

System Instructions

Customize the agent's personality, tone, domain knowledge, or rules:

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  systemInstruction: "You are a friendly sales assistant for Acme Corp. Always suggest upsells when showing order data. Never mention competitor names.",
});

Instructions are prepended to the system prompt and take priority over default behavior.

Write Confirmation

Require explicit user confirmation before any create, update, or delete:

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  confirmWrites: true,
});

// User: "Add a new customer named John"
// Agent: "I'd like to create a record in customers: name=John. Should I proceed?"
// User: "yes"
// Agent: "✅ Created customer John"

Response Language

Make the agent respond in any language:

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  language: "French",
});

// User: "Show me all orders"
// Agent: "Voici toutes les commandes..."

Field names and code stay in English so tools work correctly.

Max Results

Control the default query limit:

// Mobile app
new SyncAgentClient({ ..., maxResults: 10 });

// Admin dashboard
new SyncAgentClient({ ..., maxResults: 100 });

Sensitive Field Masking

Specify which fields the agent should mask in responses:

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  sensitiveFields: ["ssn", "creditCard", "salary", "bankAccount"],
});

// Agent shows: ssn: "••••••••", salary: "••••••••"

Default: ["password", "token", "secret"].

Middleware Hooks

Intercept tool calls for logging, audit trails, or dynamic blocking:

const agent = new SyncAgentClient({
  apiKey: "sa_your_key",
  connectionString: process.env.DATABASE_URL,
  tools: { /* your tools */ },

  // Block specific operations dynamically
  onBeforeToolCall: (toolName, args) => {
    console.log(`[Audit] ${toolName}`, args);
    if (toolName === "deleteUser" && !currentUser.isAdmin) return false;
    return true;
  },

  // Log every result
  onAfterToolCall: (toolName, args, result) => {
    analytics.track("tool_call", { tool: toolName, success: result.success });
  },
});

When onBeforeToolCall returns false, the tool is blocked and the AI receives an error message explaining the operation was denied.

Keywords

syncagent

FAQs

Package last updated on 08 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts