Skip to content

Qoni SDK

This page describes the currently public Qoni SDK, its requirements and capability surface, minimal usage, run handles and error handling, and the publication status of SDKs for other languages.

Available SDK

The public unified Qoni SDK is the Node.js and TypeScript package @qoniai/qoni. Its source is available in QoniAI/qoni-sdk-node.

ItemCurrent status
npm package@qoniai/qoni
GitHub repositoryQoniAI/qoni-sdk-node
Current public version0.4.0
RuntimeNode.js 18 or later with server-side fetch
Module formatsESM, CommonJS, and TypeScript declarations
LicenseMIT

Server-side credentials

Keep the Qoni accessKey and secretKey on a trusted server. Do not bundle them into browsers, mobile apps, public CLI configuration, or untrusted Agent runtimes.

Capability surface

The unified SDK exposes these capabilities from Qoni:

NamespacePurpose
genauthRead the current user and manage GenAuth users
gumemCreate sessions, add messages, recall Memory, upload resources, and record Actions
doAnythingStart or reattach to general Web Agent tasks
webSearchSearch the public web and read results
deepResearchRun long-form research and download artifacts
trackCreate, inspect, pause, resume, and run monitors

Runtime product calls use short-lived delegation tokens. The SDK handles runtime discovery and downstream product-token exchange. Application code should not construct internal /api/v3/eak/* routes or internal claims.

Install

bash
npm install @qoniai/qoni

You can also use pnpm or Yarn:

bash
pnpm add @qoniai/qoni
# or
yarn add @qoniai/qoni

Initialize the client

ts
import { Qoni, QoniScopes } from "@qoniai/qoni";

const qoni = new Qoni({
  accessKey: process.env.QONI_ACCESS_KEY!,
  secretKey: process.env.QONI_SECRET_KEY!,
});

Private or local deployments can pass host. It must point to the Qoni Console or SDK gateway, not directly to GenAuth, Web Agent, or GUMem. Leave host unset for hosted Qoni.

Qoni accepts the following options:

OptionRequiredDescription
accessKeyYesAccess key created in the Qoni Console
secretKeyYesSecret key created in the Qoni Console
hostNoQoni gateway address for private deployments; overrides runtime discovery
fetchNoCustom fetch implementation for proxies or test environments
timeoutMsNoPer-request timeout, default 30000; event-stream waiting is not limited by it
sseMaxRetriesNoEvent-stream reconnect attempt limit, default 5; set 0 to disable

Obtain a delegation token

Web Agent and GUMem products act for an end user. Silent delegation requires a real GenAuth user ID from the user pool bound to the Qoni credential:

ts
const { token } = (
  await qoni.delegateToken({
    user: { id: process.env.QONI_USER_ID! },
    agent: "research-assistant",
    products: ["webSearch"],
    scopes: [QoniScopes.GUMEM_MEMORY_READ, QoniScopes.GUMEM_MEMORY_WRITE],
  })
).data;

Prefer mode: "interactive" for higher-risk operations such as site login, browser takeover, long-running monitoring, or sensitive artifacts. Complete interactive authorization on the server with completeDelegateToken({ grantId, code, state }); the browser never receives the delegation token.

Fine-grained permissions are declared with scopes in the <namespace>.<resource>:<verb> format, for example webagent.web_search:read. Each Web Agent product has exactly two verbs, read and manage; products: ["webSearch"] requests the whole product as a shorthand. The SDK exports the QoniScopes constants and QoniScopeBundles presets (such as GUMEM_SESSION_RECALL) so you avoid hand-writing scope strings; a malformed scope throws QoniValidationError locally. Use grantedScopes, grantId, and auditId from the response for application-side audit records.

ts
const search = await qoni.webSearch.run({
  token,
  prompt: "Qoni SDK documentation",
  maxResultsPerQuery: 5,
});

const result = await search.wait();
console.log(result.output);

run() returns a reattachable handle. For a long task, save run.id and reconnect later with qoni.webSearch.attach(run.id, { token }).

Call GUMem

After requesting the required GUMem permissions, create a session, add confirmed user information, and recall relevant context:

ts
await qoni.gumem.createSession({
  token,
  userId: process.env.QONI_USER_ID!,
  sessionId: "daily-assistant",
  title: "Daily assistant memory",
});

await qoni.gumem.addMessages({
  token,
  sessionId: "daily-assistant",
  messages: [
    { role: "user", content: "Keep planning suggestions concise." },
  ],
});

const { data: context } = await qoni.gumem.recall({
  token,
  sessionId: "daily-assistant",
  query: "What preferences should the assistant follow?",
  details: true,
});

Run handles and event streams

run() for doAnything, webSearch, and deepResearch returns a reattachable RunHandle:

MemberPurpose
wait({ onScreenshot, onInteraction, timeoutMs })Wait for completion; consume step screenshots and interaction requests in callbacks
events()Async-iterate typed events; the iterator ends on the terminal done event
status()Query the current run status
cancel(reason)Cancel the task
sessionRefPass to the next run({ session }) to reuse the session
run.id and attach()Save the run ID and reattach to a long task at any time

If the event stream disconnects, the SDK reconnects automatically and resumes with Last-Event-ID. Common event types include progress, message, screenshot, interaction, and done; constants live in QoniEventTypes. Read event.raw when you need the original wire event.

ts
for await (const event of run.events()) {
  if (event.type === "progress") appendTrace(event.data);
  if (event.type === "screenshot") renderScreenshot(event.image);
  if (event.type === "interaction") handleInteraction(event.data);
  if (event.type === "done") return event.data.output;
}

Human-in-the-loop interactions

Web Agent tasks may require user participation. The SDK models these steps as interactions, with types site_login, clarification, confirmation, take_control, and wait (constants in InteractionTypes). When you receive an interaction in wait({ onInteraction }) or from the event stream, check the available actions with can(kind) before calling methods such as answer(), confirm(), reject(), openLogin(), or confirmSignedIn(). Calling an action that was not declared throws, preventing accidental operations on the user session.

Error handling

All SDK errors extend QoniError and carry code, status, requestId, traceId, auditId, and a retryable flag. Regular HTTP requests are not retried automatically; your application decides the retry policy for errors with retryable: true. The events() SSE stream reconnects according to sseMaxRetries.

Error classTriggered when
QoniValidationErrorLocal input validation fails, for example a malformed scope or silent delegation without user
QoniAuthErrorThe accessKey / secretKey signature is rejected
QoniPermissionDeniedErrorThe delegation token lacks a required scope (HTTP 403)
QoniTokenExpiredErrorThe delegation token has expired
QoniDelegationRequiredErrorA product call is missing token, or the gateway rejects the token
QoniRateLimitErrorRate limited (HTTP 429)
QoniTimeoutErrorA request or wait() times out; the run continues server-side and can be reattached with attach()
QoniUpstreamErrorA downstream product service fails

Migrating from versions before 0.4.0

0.4.0 (2026-08-18) is a breaking rename release; the server-side wire contract is unchanged:

  • The package was renamed from @eazo/anima to @qoniai/qoni, the recommended primary constructor was consolidated as Qoni, and environment variables moved to the QONI_* prefix. The public 0.4.0 package still includes the old long-form constructor export as a compatibility alias; new code should use only Qoni.
  • delegateAgent / completeDelegateAgent are deprecated in favor of delegateToken / completeDelegateToken; interactive callbacks must include grantId — the old { code, state } form is no longer supported.
  • The top-level userId parameter of delegateToken is deprecated in favor of user: { id }; the constructor option accessKeyId is now accessKey.
  • Gateway routes remain under /api/v3/eak/*, and token claims and eak.* error codes are unchanged; applications should not construct these internal values themselves.

Publication status of other SDKs

As of August 19, 2026, the QoniAI GitHub organization has one public SDK repository: qoni-sdk-node. No unified Qoni SDK for Python, Java, Go, PHP, or C# is currently visible in that organization.

Product-specific GUMem, Web Agent, or GenAuth SDK references elsewhere in these docs are product integration material or historical SDKs. They do not prove that a corresponding unified SDK has been published by the QoniAI organization. Before selecting a production dependency, verify its package registry entry, source repository, and released version instead of inferring publication from an example package name.

Check the installation

Confirm that npm resolves the current package version:

bash
npm view @qoniai/qoni version

Then verify that the application reads QONI_ACCESS_KEY and QONI_SECRET_KEY only on the server and uses a real GenAuth user ID for silent delegation.

Next step

  • Read the Quickstart for the combined identity, Memory, and Web Agent flow.
  • See the qoni-sdk-node README for the complete API surface, error types, and event model.