Back to agents docs
Quickstart · TypeScript

Wire a TS agent into Orrery

Native fetch + the official Anthropic SDK. Same shape as the Python quickstart; agents pay USDC per request via x402 (preview mode is free during marketplace review).

Install

npm install @anthropic-ai/sdk

Minimal agent (~30 lines)

briefing.ts
import Anthropic from "@anthropic-ai/sdk";

const ORRERY = "https://orrery.me/api/x402/v1";
const client = new Anthropic();  // reads ANTHROPIC_API_KEY

async function fetchJson<T>(url: string): Promise<T> {
  const r = await fetch(url);
  if (!r.ok) throw new Error(`${r.status} ${url}`);
  return (await r.json()).data as T;
}

// 1. Today's brief.
const brief = await fetchJson<{
  headline: string;
  biggest_moves: { slug: string; question: string; delta_24h: number }[];
}>(`${ORRERY}/brief/today`);

// 2. Why did the top mover move?
const top = brief.biggest_moves[0];
const why = await fetchJson<{ factors: { type: string; summary: string }[] }>(
  `${ORRERY}/markets/${top.slug}/why`,
);

// 3. Resolution-risk before treating it as news.
const risk = await fetchJson<{ risk_level: string; what_to_verify: string[] }>(
  `${ORRERY}/markets/${top.slug}/resolution-risk`,
);

// Hand it to Claude. Orrery already structured the data, so the
// system prompt can be tight: stay grounded, don't predict.
const msg = await client.messages.create({
  model: "claude-opus-4-7",
  max_tokens: 600,
  thinking: { type: "adaptive" },
  system:
    "You summarise prediction-market intelligence for a daily briefing. " +
    "Stay grounded in the supplied JSON; never predict outcomes; flag " +
    "resolution risk when present.",
  messages: [{
    role: "user",
    content:
      `Today's brief headline: ${brief.headline}\n\n` +
      `Top mover: ${JSON.stringify(top)}\n\n` +
      `Why it moved: ${JSON.stringify(why.factors)}\n\n` +
      `Resolution-risk: ${JSON.stringify(risk)}\n\n` +
      "Write a 4-sentence briefing for a busy reader.",
  }],
});
console.log(msg.content[0].type === "text" ? msg.content[0].text : "");

Replaying with X-PAYMENT

async function fetchWithPayment(url: string, payer: X402Payer) {
  const r = await fetch(url);
  if (r.status !== 402) return (await r.json()).data;
  const challenge = (await r.json()).accepts[0];
  const proof = await payer.settle({
    amount: challenge.amount,
    asset: challenge.asset,    // "USDC"
    network: challenge.network, // "base"
  });
  const r2 = await fetch(url, { headers: { "X-PAYMENT": proof } });
  if (!r2.ok) throw new Error(`${r2.status} after payment`);
  return (await r2.json()).data;
}

During v1 preview the 402 branch never fires; calls just return 200 with payment_status: "preview". Wire the payer once and the same code keeps working after enforcement is enabled.

Next steps

  • • Cache responses client-side using each endpoint's meta.cache_seconds hint to keep your usage in budget.
  • • For a Discord bot, fetch /signals/resolution_risk every 10 minutes and re-broadcast new fires only.
  • Python quickstart · Raw HTTP / cURL
Orrery for AI agents — TypeScript quickstart | Orrery