Skip to main content
@agent-opfor/sdk is the programmatic surface — the same engine as the CLI, callable from your own code. Use it to embed red-teaming in custom tooling, gate CI on results, or build your own workflows. It’s TypeScript-first.

Install

npm install @agent-opfor/sdk

Quickstart

Both a class-based and a functional API are available — they’re equivalent, so use whichever you prefer.
import { Opfor } from "@agent-opfor/sdk";

const opfor = new Opfor({ apiKey: process.env.ANTHROPIC_API_KEY });

const results = await opfor.run({
  target: { url: "https://api.example.com/chat", apiKeyEnv: "TARGET_API_KEY" },
  suite: "owasp-llm-top10",
});

console.log(results.score, results.findings.length);

Run

Run a suite or a list of evaluators against a target.
const results = await opfor.run({
  target: { url: "https://api.example.com/chat", apiKeyEnv: "TARGET_API_KEY", model: "gpt-4o" },
  suite: "owasp-llm-top10",
  strategy: { effort: "adaptive", turnMode: "multi", turns: 3 },
  attackerModel: "claude-sonnet-4",
  judgeModel: "claude-sonnet-4",
});
Run specific evaluators instead of a suite with evaluators: [...]:
await opfor.run({
  target: { url: "https://api.example.com/chat" },
  evaluators: ["jailbreaking", "prompt-injection", "system-prompt-leakage"],
});

Targets

target: {
  url: "https://api.example.com/chat",
  name: "My Chatbot",
  description: "Customer support chatbot with order-database access",
  apiKeyEnv: "TARGET_API_KEY",
  model: "gpt-4o",
  headers: { "X-Custom-Header": "value" },
  requestFormat: "openai",     // "auto" | "openai" | "json"
  promptPath: "input.message", // for requestFormat: "json"
  responsePath: "output.text",
}

Strategy

Control how thorough the attack loop is.
strategy: {
  effort: "adaptive",   // "adaptive" (one sustained chat) | "comprehensive" (one attack per pattern)
  turnMode: "multi",    // "single" | "multi"
  turns: 3,             // max turns per attack when multi
}

Models

Set attacker and judge LLMs as a shorthand string or a full provider object. The judge defaults to the attacker if unset.
const opfor = new Opfor({ apiKey: process.env.ANTHROPIC_API_KEY });

await opfor.run({
  target: { url: "https://api.example.com/chat" },
  suite: "owasp-llm-top10",
  attackerModel: "claude-sonnet-4",
  judgeModel: { provider: "anthropic", model: "claude-opus-4", apiKeyEnv: "ANTHROPIC_API_KEY" },
});
Provider objects accept { provider, model, apiKeyEnv, baseUrl? }. See providers for the full list and env vars.

Autonomous mode

hunt() runs the autonomous campaign programmatically — adaptive multi-turn attacks driven by an AI agent, with progress streaming.
import { hunt } from "@agent-opfor/sdk";

const results = await hunt({
  target: { url: "https://api.example.com/chat", apiKey: process.env.TARGET_API_KEY },
  objective: "Find jailbreaks, data leaks, and authorization flaws",
  limits: { budgetUsd: 5 },
  onProgress: (event) => {
    if (event.type === "finding") console.log(`Found: ${event.vulnClass} (${event.severity})`);
  },
});

console.log(results.outcome, results.findings.length, results.htmlReportPath);
interface HuntOptions {
  target: {
    url: string;
    name?: string;
    apiKey?: string;
    headers?: Record<string, string>;
    stateful?: boolean;
    sessionField?: string;
    promptPath?: string;
    responsePath?: string;
    model?: string;
  };
  objective: string;
  models?: { commander?: string; operator?: string; scout?: string; verifier?: string };
  limits?: {
    budgetUsd?: number;       // default 10
    maxOperators?: number;    // default 6
    maxTurns?: number;        // default 120
    maxThreadTurns?: number;  // default 25
    maxTotalThreads?: number; // default 40
    maxDepth?: number;        // default 3
    maxReconProbes?: number;  // default 8
  };
  verify?: boolean;
  sequential?: boolean;
  outputDir?: string;
  onProgress?: (event: HuntProgressEvent) => void;
}
onProgress events: line, recon_start, recon_done, thread_start, thread_turn, thread_done, finding, complete. HuntResults includes outcome, summary, recon, findings, recommendations, totalCostUsd, and report paths.

Telemetry

Enable trace-aware testing so the judge sees the target’s internal tool calls and retrievals.
await opfor.run({
  target: { url: "https://api.example.com/chat" },
  suite: "owasp-llm-top10",
  telemetry: {
    provider: "langfuse",
    langfuse: {
      publicKeyEnv: "LANGFUSE_PUBLIC_KEY",
      secretKeyEnv: "LANGFUSE_SECRET_KEY",
      baseUrl: "https://cloud.langfuse.com",
      traceSelection: { lookbackHours: 24, environment: "production" },
    },
    enrichJudgeFromTrace: true,
    propagation: { headers: { "X-Trace-Id": "{{traceId}}" }, traceIdStrategy: "per-attack" },
  },
});
Netra is configured the same way under a netra: { baseUrl, apiKeyEnv, traceSelection } block.

Results

interface RunResults {
  id: string;
  timestamp: string;
  targetName: string;
  targetKind: "agent" | "mcp";
  effort: "adaptive" | "comprehensive";
  attackerModel: string;
  judgeModel: string;
  score: number; // 0–100 safety score
  summary: {
    total: number;
    passed: number;
    failed: number;
    errors: number;
    safetyScore: number;
    attackSuccessRate: number;
  };
  findings: Finding[];
  evaluators: EvaluatorResult[];
}
A Finding carries severity, title, description, evidence?, and a standards map. Each EvaluatorResult holds per-evaluator pass/fail counts and an attacks array with full prompt/response transcripts and verdict.

Reports

const r = opfor.report(results);
await r.json("./report.json");
await r.html("./report.html");

// functional
import { report } from "@agent-opfor/sdk";
await report(results).html("./report.html");

Gate CI on findings

import { run } from "@agent-opfor/sdk";

const results = await run({
  target: { url: process.env.TARGET_URL!, apiKeyEnv: "TARGET_API_KEY" },
  suite: "owasp-llm-top10",
  apiKey: process.env.ANTHROPIC_API_KEY,
});

if (results.findings.length > 0) {
  for (const f of results.findings) console.error(`[${f.severity}] ${f.title}`);
  process.exit(1);
}
console.log(`Safety score: ${results.score}%`);

Exports

import {
  Opfor,          // class API
  run,            // run a suite / evaluators
  hunt,           // autonomous red-team
  report,         // generate reports from results
  listSuites,     // list available suites
  listEvaluators, // list available evaluators (optionally { kind: "mcp" })
} from "@agent-opfor/sdk";
Types are exported too: RunOptions, RunResults, TargetConfig, McpTargetConfig, Finding, EvaluatorResult, AttackResult, TelemetryConfig, and the Hunt* variants.