SDKs

TypeScript protection and tracing clients are on public npm. Python stays in the monorepo (not on PyPI). You can also skip the Intertrace SDK and point any OpenAI-compatible client at the Intertrace edge.

Install from npm

npm install @intertrace-runtime/runtime
npm install @intertrace-runtime/tracing

Runtime protection

Wrap tools so authorize + execution permits run before the body. Mint an itr_rt_* key in Settings. The SDK talks to the Intertrace edge at https://intertrace.fly.dev. fromEnv() reads INTERTRACE_*. The first protected call starts a real session if you skip startSession().

import { IntertraceRuntime } from "@intertrace-runtime/runtime";

const runtime = IntertraceRuntime.fromEnv();
// Default baseUrl: "https://intertrace.fly.dev"
const { sessionId } = await runtime.startSession({ taskSummary: "Handle ticket" });

const sendEmail = runtime.protectTool(
  {
    name: "send_email",
    category: "external_communication",
    actionType: "write",
    dataBoundary: "external",
    possibleDataClasses: ["customer_pii"],
  },
  async (args: { to: string; body: string }) => {
    return { ok: true, to: args.to };
  }
);

await sendEmail({ to: "user@example.com", body: "Hello" });
await runtime.endSession(sessionId);

Agent builders

LLM plane: openaiCompatibleConfig() or baseURL=https://intertrace.fly.dev/v1. Tool plane: LangChain/LangGraph, OpenAI Agents, Vercel AI SDK 5, Mastra, CrewAI, LlamaIndex, AutoGen, Semantic Kernel, and Pydantic AI. Full cookbook: Agent frameworks.

import { openaiCompatibleConfig } from "@intertrace-runtime/runtime";

const edge = openaiCompatibleConfig({
  apiKey: process.env.INTERTRACE_RUNTIME_API_KEY!,
  assetId: "support-agent",
});
// new OpenAI(edge) · ChatOpenAI({ configuration: { baseURL: edge.baseURL } })

Errors

Catch typed errors. isIntertraceError(err) is the type guard. Blocked and approval-required decisions never run the tool body.

import {
  IntertraceBlockedActionError,
  IntertraceReviewRequiredError,
  IntertraceScopeMismatchError,
  isIntertraceError,
} from "@intertrace-runtime/runtime";

try {
  await sendEmail({ to: "user@example.com", body: "Hello" });
} catch (err) {
  if (err instanceof IntertraceReviewRequiredError) {
    // wait for approval, then retry with the approval id
  } else if (err instanceof IntertraceBlockedActionError) {
    // show err.message + err.policyReasons
  } else if (err instanceof IntertraceScopeMismatchError) {
    // 0.4.0+: fix INTERTRACE_ORG_ID / PROJECT_ID / AGENT_ID (err.gatewayCode); retrying won't help
  } else if (isIntertraceError(err) && err.retryable) {
    // transient edge error
  } else {
    throw err;
  }
}

Approvals, plans and confirm

waitForApproval(id) long-polls GET /v1/runtime/approvals/{id}?wait=… (protectTool does this for you). submitPlan() posts to POST /v1/runtime/plans so one approval covers the listed steps in this session; blocks still apply, and payments, admin changes and outbound messages still ask each time. A confirm callback (0.4.0 and later) lets your own user answer developer-level asks outside production when the organization allows it; organization-level asks still wait for a person in Intertrace. setUserRequest(text) sends the user's latest message for the intent check.

const runtime = IntertraceRuntime.fromEnv({
  confirm: async ({ question }) => askUser(question),
});

await runtime.submitPlan({
  summary: "Refund order 1042",
  steps: [{ tool: "orders_lookup" }, { tool: "refunds_create", why: "Customer request" }],
  ttlMinutes: 30,
});

Tracing

Films the session into Estate → Sessions. fromEnv() plus bindSession() share the runtime job. Patches Chat Completions, Responses, and Anthropic Messages. Nested trace() sets parent spans.

import { fromEnv, instrumentOpenAI } from "@intertrace-runtime/tracing";
import OpenAI from "openai";

const tracer = fromEnv();
tracer.bindSession(sessionId);

const openai = instrumentOpenAI(
  new OpenAI({
    apiKey: process.env.INTERTRACE_API_KEY,
    baseURL: "https://intertrace.fly.dev/v1",
  })
);

await tracer.trace("handle ticket", async () => {
  await openai.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: "Summarize the ticket" }],
  });
});

OpenAI-compatible (no Intertrace SDK)

Point the official OpenAI client at the edge with a runtime key. Full pack: OpenAI SDK.

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.INTERTRACE_RUNTIME_API_KEY,
  baseURL: "https://intertrace.fly.dev/v1",
});

Python

The Python SDK is not on PyPI. Install from the monorepo, or use the OpenAI SDK against https://intertrace.fly.dev/v1.

# From this repo
pip install -e packages/python-sdk

from intertrace import IntertraceRuntime

runtime = IntertraceRuntime.from_env()
session_id = runtime.start_session(task_summary="Handle ticket")
runtime.end_session(session_id)

Environment

The runtime key decides the organization, project and agent. The SDK also sends the values below, and the edge rejects any that disagree with the key, so every value you set must match the key's binding.

  • INTERTRACE_API_KEY / INTERTRACE_RUNTIME_API_KEY: itr_rt_* from Settings, bound to one agent
  • INTERTRACE_PROJECT_ID: required. The project the key was minted in (the project_id that POST /api/runtime/keys/create returns), not the organization UUID. Any other value is rejected with 401 PROJECT_NOT_FOUND.
  • INTERTRACE_ORG_ID: optional, your organization UUID. Leave it unset and the gateway takes the organization from the key (0.4.1 and later). When set, authorize sends it as tenant_id, and a value that disagrees with the key is rejected with 403 TENANT_MISMATCH. Before 0.4.1 the SDK sent the project id when it was unset, which always failed, so upgrade or set it.
  • INTERTRACE_AGENT_ID: the slug (agent key) or asset id of the agent the key is bound to, not its display name. A mismatch is 403 AGENT_NOT_FOUND. INTERTRACE_AGENT_PURPOSE is required free text.
  • SDK 0.4.0 and later raise these three as IntertraceScopeMismatchError (code INVALID_CONFIGURATION, not retryable; gatewayCode says which value is wrong). 0.3.1 reports them as an invalid key (401) or an unavailable error (403).
  • INTERTRACE_MODE: enforce (default) or monitor. INTERTRACE_SESSION_ID binds an existing session.
  • Runtime / OpenAI edge: https://intertrace.fly.dev (/v1 for chat)

Interactive API: API reference · Machine spec: /openapi.json.