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.
| Item | Current status |
|---|---|
| npm package | @qoniai/qoni |
| GitHub repository | QoniAI/qoni-sdk-node |
| Current public version | 0.4.0 |
| Runtime | Node.js 18 or later with server-side fetch |
| Module formats | ESM, CommonJS, and TypeScript declarations |
| License | MIT |
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:
| Namespace | Purpose |
|---|---|
genauth | Read the current user and manage GenAuth users |
gumem | Create sessions, add messages, recall Memory, upload resources, and record Actions |
doAnything | Start or reattach to general Web Agent tasks |
webSearch | Search the public web and read results |
deepResearch | Run long-form research and download artifacts |
track | Create, 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
npm install @qoniai/qoniYou can also use pnpm or Yarn:
pnpm add @qoniai/qoni
# or
yarn add @qoniai/qoniInitialize the client
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:
| Option | Required | Description |
|---|---|---|
accessKey | Yes | Access key created in the Qoni Console |
secretKey | Yes | Secret key created in the Qoni Console |
host | No | Qoni gateway address for private deployments; overrides runtime discovery |
fetch | No | Custom fetch implementation for proxies or test environments |
timeoutMs | No | Per-request timeout, default 30000; event-stream waiting is not limited by it |
sseMaxRetries | No | Event-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:
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.
Call Web Search
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:
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:
| Member | Purpose |
|---|---|
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 |
sessionRef | Pass 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.
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 class | Triggered when |
|---|---|
QoniValidationError | Local input validation fails, for example a malformed scope or silent delegation without user |
QoniAuthError | The accessKey / secretKey signature is rejected |
QoniPermissionDeniedError | The delegation token lacks a required scope (HTTP 403) |
QoniTokenExpiredError | The delegation token has expired |
QoniDelegationRequiredError | A product call is missing token, or the gateway rejects the token |
QoniRateLimitError | Rate limited (HTTP 429) |
QoniTimeoutError | A request or wait() times out; the run continues server-side and can be reattached with attach() |
QoniUpstreamError | A 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/animato@qoniai/qoni, the recommended primary constructor was consolidated asQoni, and environment variables moved to theQONI_*prefix. The public0.4.0package still includes the old long-form constructor export as a compatibility alias; new code should use onlyQoni. delegateAgent/completeDelegateAgentare deprecated in favor ofdelegateToken/completeDelegateToken; interactive callbacks must includegrantId— the old{ code, state }form is no longer supported.- The top-level
userIdparameter ofdelegateTokenis deprecated in favor ofuser: { id }; the constructor optionaccessKeyIdis nowaccessKey. - Gateway routes remain under
/api/v3/eak/*, and token claims andeak.*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:
npm view @qoniai/qoni versionThen 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-nodeREADME for the complete API surface, error types, and event model.