nvoken

Reference

TypeScript SDK

Call the hosted nvoken API from Node.js with the official TypeScript client, or use the HTTP API from another language.

The TypeScript SDK is the shortest path from a Node.js application to the hosted nvoken API. It handles idempotent admission, polling, pagination, durable Invocation handles, and stream reconnects.

Applications in other languages can use the same HTTP API directly. The HTTP contract is the product boundary; you never need the nvoken service source or a local daemon.

Install

npm install @deepnoodle/nvoken

Node.js 20 or newer is required.

Configure the hosted client

Pass the API base URL and Runtime key copied from your App's API keys page. You can set them explicitly:

import { Client } from "@deepnoodle/nvoken";
 
function requireEnv(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Missing ${name}`);
  return value;
}
 
const client = new Client({
  baseUrl: requireEnv("NVOKEN_BASE_URL"),
  apiKey: requireEnv("NVOKEN_API_KEY"),
  defaultModel: {
    provider: "anthropic",
    id: requireEnv("NVOKEN_MODEL"),
  },
});

Or set NVOKEN_BASE_URL, NVOKEN_API_KEY, NVOKEN_PROVIDER, and NVOKEN_MODEL in the process environment and use new Client().

Keep the Runtime key on your server. Browser code should call your backend, not the nvoken API directly.

Run an ordinary turn

Create an Agent facade from the instructions and defaults your application owns:

const agent = client.agent({
  agentKey: "support",
  spec: { instructions: "Be concise and helpful." },
});
 
console.log(await agent.text("Why was I charged twice?"));

agent.text() waits for the turn to settle and returns the final assistant text. Use agent.run() when you also need usage, messages, structured output, or the complete Invocation result.

Admit now, wait later

Use agent.invoke() when admission and waiting belong in different parts of your application:

const handle = await agent.invoke("Summarize this issue.", {
  idempotencyKey: "issue-1842:summary-v1",
});
 
// A later worker can recover the same hosted turn from its durable ID.
const recovered = client.invocation(handle.invocationId);
const result = await recovered.waitForResult();

The SDK generates an idempotency key when you omit one and safely retries an ambiguous admission. Supply your own stable key when another process must be able to reproduce the request before the handle has been stored.

A local wait timeout stops only the caller. It does not cancel the hosted Invocation. Call handle.cancel() when you intend to stop the remote turn.

Stream output

The high-level stream admits with JSON, then follows the Invocation stream:

for await (const event of agent.stream("Write a short status update.")) {
  if (event.type === "output_text.delta") {
    process.stdout.write(event.text);
  }
 
  if (event.type === "invocation.result") {
    console.log(`\n${event.result.invocation.status}`);
  }
}

Use client.invocation("invk_…").stream() to reconnect to a turn admitted by an earlier process. Read Streaming & recovery before storing preview text or implementing your own cursor loop.

Use the low-level client

client.raw() exposes the complete generated Runtime client when the Agent facade does not cover an operation you need. The typed convenience methods on Client also include model discovery, Session reads, provider-credential management, and Invocation control.

For another language, make ordinary HTTPS requests with bearer authentication. Preserve the request body's idempotency_key, store the returned invocation_id, and treat the terminal Invocation result as authoritative.