anoman
MasukDapatkan API Key
Sdk
Beranda Dokumentasi

SDK TypeScript.

Klien nol-dependensi untuk browser, Node, Bun, Deno, dan runtime Edge. Iterator async untuk streaming, pembatalan yang sadar-AbortController, helper poll batch, metadata _anoman yang typed.

Instalasi

Package manager apa saja

npm

npm install anoman-ai

pnpm

pnpm add anoman-ai

yarn

yarn add anoman-ai

bun

bun add anoman-ai

Nol dependensi runtime. Dual export ESM + CJS. npm ↗

Inisialisasi klien

Klien yang sama, setiap runtime

Standar

import { AnomanClient } from "anoman-ai";
 
const client = new AnomanClient({
  apiKey: process.env.ANOMAN_API_KEY!,
  // baseURL defaults to https://api.anoman.io
  timeout: 120_000,    // ms
  maxRetries: 3,       // retried only on 429 / 503 / 504
});

Runtime Edge (Cloudflare Workers, Vercel Edge)

import { AnomanClient } from "anoman-ai/edge";  // zero-Node-API entrypoint
 
export default {
  async fetch(request: Request, env: Env) {
    const client = new AnomanClient({ apiKey: env.ANOMAN_API_KEY });
    const response = await client.chat.completions.create({
      model: "gpt-4o-mini",
      messages: [{ role: "user", content: "Hi" }],
    });
    return Response.json(response);
  },
};

Untuk Cloudflare Workers / Vercel Edge / Deno, gunakan entrypoint anoman-ai/edge — tanpa Node API.

Chat completions

Bentuk sama seperti OpenAI + _anoman yang typed

Completion dasar

const response = await client.chat.completions.create({
  model: "claude-sonnet-4-6",
  messages: [
    { role: "system", content: "You are a helpful assistant." },
    { role: "user", content: "What's the capital of Indonesia?" },
  ],
  temperature: 0.7,
  max_tokens: 200,
});
 
// Standard fields — identical to OpenAI SDK
console.log(response.choices[0].message.content);
console.log(response.usage.total_tokens);
 
// Anoman extension — fully typed
console.log(response.anoman.cost_usd);                  // "0.000041"
console.log(response.anoman.guardrails.injection);      // { status: "pass", score: 0.02 }
console.log(response.anoman.cache.hit);                 // false
console.log(response.anoman.routing.region);            // "id"

Dengan tools

interface WeatherArgs { city: string }
 
const response = await client.chat.completions.create({
  model: "claude-sonnet-4-6",
  messages: [{ role: "user", content: "Weather in Jakarta?" }],
  tools: [{
    type: "function",
    function: {
      name: "get_weather",
      parameters: {
        type: "object",
        properties: { city: { type: "string" } },
        required: ["city"],
      },
    },
  }],
});
 
const call = response.choices[0].message.tool_calls?.[0];
if (call?.function.name === "get_weather") {
  const args: WeatherArgs = JSON.parse(call.function.arguments);
  console.log(`Looking up weather for ${args.city}`);
}

Input vision

const response = await client.chat.completions.create({
  model: "gpt-4o",
  messages: [{
    role: "user",
    content: [
      { type: "text", text: "What's in this image?" },
      { type: "image_url", image_url: { url: "https://example.com/chart.png" } },
    ],
  }],
});

Referensi endpoint lengkap di /docs/endpoints/chat-completions.

Streaming

Iterasi async native

Streaming dengan iterasi async

const stream = await client.chat.completions.create({
  model: "claude-sonnet-4-6",
  messages: [{ role: "user", content: "Tell me a short story" }],
  stream: true,
});
 
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
 
// The final _anoman frame is exposed as a promise on the stream
const meta = await stream.anomanMeta;
console.log(`Cost: ${meta.cost_usd}`);

Batalkan dengan AbortController

const controller = new AbortController();
 
setTimeout(() => controller.abort(), 5000);   // cancel after 5s
 
try {
  const stream = await client.chat.completions.create(
    {
      model: "claude-sonnet-4-6",
      messages: [{ role: "user", content: "Write a long essay" }],
      stream: true,
    },
    { signal: controller.signal },
  );
  for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
  }
} catch (err) {
  if ((err as Error).name === "AbortError") {
    console.log("\n[cancelled]");
  } else {
    throw err;
  }
}

Batch

Enqueue + poll dalam satu panggilan

Helper enqueue + poll

const job = await client.chat.completions.create({
  model: "deepseek-v3",
  messages: [{ role: "user", content: "Summarize this 50-page doc..." }],
  preferBatch: true,        // x-anoman-prefer-batch
});
 
console.log(`Queued ${job.id}, SLA ${job.sla_minutes}m`);
 
// Poll to completion — SDK handles 202/200 + Retry-After
const result = await client.pollBatch(job.id, {
  deadlineMinutes: 30,
  onProgress: (r) => console.log(`  remaining ${r.sla_remaining_minutes}m`),
});
 
console.log(result.choices[0].message.content);
console.log(`Saved: $${result.anoman.savings_usd}`);

Batalkan job yang antre

await client.batch.cancel(job.id);            // throws if already executing
const status = await client.batch.get(job.id);
console.log(status.status);                  // "cancelled"

Siklus batch lengkap di /docs/endpoints/batch.

Error

Hierarki exception yang typed

Semua error meng-extend AnomanError. Gunakan instanceof untuk bercabang.

Penanganan error

import {
  AnomanError,
  AuthError,            // 401, 403 auth_*
  BudgetExceededError,  // 402
  GuardrailError,       // 403 guardrail_*
  RateLimitError,       // 429
  ProviderError,        // 503, 504
} from "anoman-ai";
 
try {
  const response = await client.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: "Hi" }],
  });
} catch (err) {
  if (err instanceof GuardrailError) {
    console.log(`Blocked: ${err.code} — ${err.message}`);
  } else if (err instanceof RateLimitError) {
    console.log(`Wait ${err.retryAfter}s`);
  } else if (err instanceof ProviderError) {
    console.log(`Upstream ${err.statusCode}: ${err.message}`);
  } else if (err instanceof BudgetExceededError) {
    console.log("Out of budget");
  } else if (err instanceof AuthError) {
    console.log("Auth failed");
  } else if (err instanceof AnomanError) {
    console.log(`Unexpected: ${err}`);
  } else {
    throw err;  // not from Anoman
  }
}

Opsi khusus Anoman

kwargs camelCase untuk header

Header x-anoman-* yang umum diekspos sebagai kwargs bertipe.

Session + agent ID

const response = await client.chat.completions.create({
  model: "claude-sonnet-4-6",
  messages: [/* ... */],
  sessionId: "conv-7k4mP",      // x-anoman-session-id
  agentId: "support-bot-v3",    // x-anoman-agent-id
  metadata: { customer_tier: "enterprise" },  // surfaces in traces
});

Paksa realtime

await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [/* ... */],
  forceRealtime: true,   // x-anoman-realtime
});

Lewati semantic cache

await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [/* ... */],
  noCache: true,   // x-anoman-no-cache
});

Lebih suka Python?

Cakupan sama. Klien sync + async.