checkrd

OpenAI Agents SDK (TypeScript)

Wire Checkrd into @openai/agents via TracingProcessor and Guardrail.

OpenAI Agents SDK — TypeScript

The @openai/agents package mirrors the Python SDK's two-layer extension model:

  1. Tracing processors — observation-only.
  2. Guardrails — enforcement (tripwire to abort).

Checkrd ships both:

  • CheckrdTracingProcessor — emits a Checkrd telemetry event per span. Register via addTraceProcessor(...).
  • checkrdInputGuardrail() / checkrdOutputGuardrail() — return guardrails the user passes to new Agent({ inputGuardrails: [...] }) or outputGuardrails.

Install

bash
npm install checkrd @openai/agents

Quickstart

typescript
import { Agent, run, addTraceProcessor } from "@openai/agents";
import { initAsync } from "checkrd";
import {
  CheckrdTracingProcessor,
  checkrdInputGuardrail,
} from "checkrd/openai-agents";

const checkrd = await initAsync({
  policy: "policy.yaml",
  agentId: "research-agent",
});

// 1. Wire telemetry (observation only)
addTraceProcessor(
  new CheckrdTracingProcessor({
    engine: checkrd.engine,
    enforce: true,
    agentId: "research-agent",
    sink: checkrd.sink,
  }),
);

// 2. Wire enforcement on each agent
const agent = new Agent({
  name: "research-agent",
  instructions: "Summarize tomorrow's calendar.",
  inputGuardrails: [
    checkrdInputGuardrail({
      engine: checkrd.engine,
      enforce: true,
      agentId: "research-agent",
      sink: checkrd.sink,
    }),
  ],
});

const result = await run(agent, "Tomorrow's calendar");
console.log(result.finalOutput);

Output guardrails

Use checkrdOutputGuardrail() when output content (not just input) needs policy filtering. Same options shape; same synthetic-URL scheme.

typescript
const agent = new Agent({
  name: "bot",
  outputGuardrails: [
    checkrdOutputGuardrail({ engine, enforce: true, agentId, sink }),
  ],
});

Why the split

The Agents SDK's tracing processor is observation-only by design. Trying to enforce from a tracing processor would break in the next minor version. Guardrails are the explicit enforcement seam.

The split lets you wire telemetry once globally (the OpenAI traces dashboard keeps working alongside Checkrd) and add enforcement per-agent based on each agent's threat model.

What gets enforced

GuardrailSynthetic URL
checkrdInputGuardrailhttps://openai-agents.local/input/{agent_name}
checkrdOutputGuardrailhttps://openai-agents.local/output/{agent_name}
yaml
agent: research-agent
default: allow

rules:
  - name: deny-pii-extraction
    deny:
      url: "openai-agents.local/input/*"
      body:
        input: "*ssn*|*social security*"

Tracing event shapes

Spans are classified by their spanData.type and emitted as openai_agents_<kind>_start / <kind>_end. Common kinds: generation, function, agent, handoff, guardrail. Trace correlation: request_id = span's traceId, span_id = spanId, parent_span_id = parentId.

Observation mode

typescript
checkrdInputGuardrail({
  engine: checkrd.engine,
  enforce: false, // observation mode — never tripwires
  agentId: "research-agent",
  sink: checkrd.sink,
});

The guardrail returns tripwireTriggered: false even on policy deny. The deny is logged and emitted as a *_denied telemetry event.

Caveats

  • addTraceProcessor is additive — your OpenAI traces dashboard keeps working alongside Checkrd. Use setTraceProcessors([...]) only if you want to replace defaults.
  • Tracing processors are sync. Heavy work goes on the sink's batch queue.
  • Duck-typed against the SDK shape: a minor @openai/agents version bump won't force a Checkrd release.