Skip to main content
← Back to Docs

SDK Reference

Node.js SDK

Full reference for the @rankigi/sdk package.

Installation

bash
npm install @rankigi/sdk

Requires Node.js 18+ and TypeScript 5+ (recommended).

Configuration

Run npx @rankigi/cli init to issue a credential. The CLI writes a single RANKIGI_CREDENTIAL token plus RANKIGI_CHAIN_ID to your .env.

bash
RANKIGI_CREDENTIAL=rnk_live_cred_v1...
RANKIGI_CHAIN_ID=chn_your_chain_id
typescript
import "dotenv/config";
import { Rankigi } from "@rankigi/sdk";

// Reads RANKIGI_CREDENTIAL (preferred single-token form)
// and RANKIGI_CHAIN_ID from your environment.
const rankigi = Rankigi.fromEnv();

// Or from a single credential token explicitly:
// const rankigi = Rankigi.fromCredential(process.env.RANKIGI_CREDENTIAL!);

// Advanced / legacy: explicit four-variable form.
// const rankigi = new Rankigi({
//   apiKey:            process.env.RANKIGI_API_KEY!,
//   agentId:           process.env.RANKIGI_AGENT_ID!,
//   passportId:        process.env.RANKIGI_PASSPORT_ID!,
//   signingPrivateKey: process.env.RANKIGI_SIGNING_KEY!,
// });

Scoping events to a chain

Every event the SDK emits is scoped to a chain. Rankigi.fromEnv() reads RANKIGI_CHAIN_ID automatically. You can also pass chainId to the constructor.

typescript
// .env
// RANKIGI_CREDENTIAL=rnk_live_cred_v1...
// RANKIGI_CHAIN_ID=chn_your_chain_id

import { Rankigi } from "@rankigi/sdk";

// fromEnv() picks up RANKIGI_CHAIN_ID automatically.
const rankigi = Rankigi.fromEnv();

// Or pass chainId explicitly:
// const rankigi = new Rankigi({
//   apiKey, agentId, passportId, signingPrivateKey,
//   chainId: "chn_your_chain_id",
// });

Methods

wrapAnthropic(label, args, fn)

Wrap an Anthropic Messages call. The label, args, and result are hashed and chained.

typescript
const response = await rankigi.wrapAnthropic(
  "contract-review",
  { prompt, model: "claude-sonnet-4-20250514" },
  () => client.messages.create({ model, max_tokens: 1024, messages }),
);

wrapOpenAI(label, args, fn)

Wrap an OpenAI Chat Completions call.

typescript
const completion = await rankigi.wrapOpenAI(
  "answer-generation",
  { model: "gpt-4o", messages },
  () => openai.chat.completions.create({ model, messages }),
);

wrap(label, args, fn)

Wrap any async function with the same governed-call pattern.

typescript
const result = await rankigi.wrap(
  "custom-step",
  { input },
  async () => doWork(input),
);

trackToolCall(tool, input, output)

Record a tool invocation. Input and output are SHA-256 hashed before transmission.

typescript
await rankigi.trackToolCall(
  "stripe_refund",
  { charge_id: "ch_abc", amount: 100 },
  { success: true, refund_id: "re_abc123" },
);

trackAgentOutput(output)

Record an agent output as a chain event.

typescript
await rankigi.trackAgentOutput({
  report_id: "rpt_456",
  pages: 12,
});

trackError(error)

Record an error as a chain event.

typescript
try {
  await runStep();
} catch (err) {
  await rankigi.trackError(err);
  throw err;
}

withSession(id, fn) / withRun(id, fn)

Scope a block of work to a session or run identifier.

typescript
await rankigi.withSession("sess_abc123", async () => {
  await rankigi.withRun("run_xyz789", async () => {
    await rankigi.trackToolCall("web_search", input, output);
  });
});

close()

Flush pending events and shut down the background sender.

typescript
// Flush pending events and shut down the background sender.
await rankigi.close();

Failure behavior

The SDK is non-blocking. Each track() call posts one event to the ingest endpoint. Failures retry 3 times with exponential backoff, then are logged to stderr and dropped, your agent never sees an exception from RANKIGI. Enable debug: true (or RANKIGI_DEBUG=true) to see verbose retry logs.

TransportOne POST per event
Retry strategyExponential backoff, 3 retries
Failure behaviorLogged to stderr, dropped (never thrown)
Debug logsdebug: true or RANKIGI_DEBUG=true

TypeScript Types

typescript
interface RankigiConfig {
  apiKey:            string;
  agentId:           string;
  passportId:        string;
  signingPrivateKey: string;
  chainId?:          string;   // also read from RANKIGI_CHAIN_ID
  baseUrl?:          string;   // default: "https://rankigi.com"
  debug?:            boolean;  // also read from RANKIGI_DEBUG
}

// Factory shortcuts:
// Rankigi.fromEnv()
// Rankigi.fromCredential("rnk_live_cred_v1.<token>")

// Method signatures:
type WrapFn<T> = () => Promise<T>;

rankigi.wrapAnthropic<T>(label: string, args: object, fn: WrapFn<T>): Promise<T>;
rankigi.wrapOpenAI<T>(label: string, args: object, fn: WrapFn<T>): Promise<T>;
rankigi.wrap<T>(label: string, args: object, fn: WrapFn<T>): Promise<T>;

rankigi.trackToolCall(tool: string, input: unknown, output: unknown): Promise<void>;
rankigi.trackAgentOutput(output: Record<string, unknown>): Promise<void>;
rankigi.trackError(error: Error): Promise<void>;

rankigi.withSession(sessionId: string, fn: () => Promise<void>): Promise<void>;
rankigi.withRun(runId: string, fn: () => Promise<void>): Promise<void>;
rankigi.close(): Promise<void>;

Full Example

typescript
import "dotenv/config";
import { Rankigi } from "@rankigi/sdk";
import Anthropic from "@anthropic-ai/sdk";

const rankigi = Rankigi.fromEnv();
const anthropic = new Anthropic();

async function reviewContract(text: string) {
  return rankigi.wrapAnthropic(
    "contract-review",
    { text, model: "claude-sonnet-4-20250514" },
    () =>
      anthropic.messages.create({
        model: "claude-sonnet-4-20250514",
        max_tokens: 1024,
        messages: [{ role: "user", content: text }],
      }),
  );
}

async function refundCharge(chargeId: string, amount: number) {
  try {
    const result = await stripe.refunds.create({ charge: chargeId, amount });
    await rankigi.trackToolCall(
      "stripe_refund",
      { charge_id: chargeId, amount },
      { success: true, refund_id: result.id },
    );
    return result;
  } catch (err) {
    await rankigi.trackError(err);
    throw err;
  }
}

process.on("SIGTERM", async () => {
  await rankigi.close();
  process.exit(0);
});

Error Handling

typescript
import "dotenv/config";
import { Rankigi } from "@rankigi/sdk";

const rankigi = Rankigi.fromEnv();

// The SDK is non-blocking. If ingest fails, your agent
// continues. Failures are logged to stderr but never thrown
// to your handler. Each track() call posts one event with
// 3 retries on transient failure (exponential backoff).
//
// For verbose retry logs, enable debug mode:
//
// const rankigi = new Rankigi({
//   apiKey, agentId, passportId, signingPrivateKey,
//   debug: true, // or set RANKIGI_DEBUG=true
// });