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/tracingRuntime 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 agentINTERTRACE_PROJECT_ID: required. The project the key was minted in (theproject_idthatPOST /api/runtime/keys/createreturns), not the organization UUID. Any other value is rejected with 401PROJECT_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 astenant_id, and a value that disagrees with the key is rejected with 403TENANT_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 403AGENT_NOT_FOUND.INTERTRACE_AGENT_PURPOSEis required free text.- SDK 0.4.0 and later raise these three as
IntertraceScopeMismatchError(codeINVALID_CONFIGURATION, not retryable;gatewayCodesays which value is wrong). 0.3.1 reports them as an invalid key (401) or an unavailable error (403). INTERTRACE_MODE:enforce(default) ormonitor.INTERTRACE_SESSION_IDbinds an existing session.- Runtime / OpenAI edge:
https://intertrace.fly.dev(/v1for chat)
Interactive API: API reference · Machine spec: /openapi.json.