Skip to main content

Refrain

The Refrain class runs runbooks in a local browser instance.
import { Refrain } from "@refrainai/sdk";

const client = new Refrain({
  ai: {
    modelId: "claude-sonnet-4-6",
    provider: "anthropic",
    apiKey: process.env.ANTHROPIC_API_KEY!,
  },
});

Configuration

The constructor accepts an RefrainConfig object:
PropertyRequiredDefaultDescription
aiYesAI model configuration (see below)
headlessNotrueLaunch browser in headless mode
loggerFactoryNonoopCustom logging implementation
debugNofalseEnable debug logging
apiKeyNoAPI key for plan features
localeNo"en"UI language: "en" or "ja"
stealthNoBot detection evasion (Pro+)
proxyNoHTTP proxy URL or config object

AI model configuration

PropertyRequiredDescription
modelIdYesModel identifier (e.g., "claude-sonnet-4-6", "gpt-4o")
providerYesanthropic | openai | openai-compatible | google | azure | bedrock | vertex
apiKeyNoAPI key for the provider
baseURLNoCustom endpoint (for openai-compatible)
modelOverridesNoPer-purpose model IDs (see below)

Provider-specific properties

PropertyDescription
azureResourceNameAzure resource name
azureApiVersionAzure API version

Model overrides

Override the model used for specific tasks (Business+ plan):
const client = new Refrain({
  ai: {
    modelId: "claude-sonnet-4-6",
    provider: "anthropic",
    apiKey: "sk-ant-...",
    modelOverrides: {
      selector: "claude-haiku-4-5-20251001",    // Fast model for selector resolution
      extraction: "claude-haiku-4-5-20251001",  // Fast model for data extraction
      review: "claude-sonnet-4-6",              // Sonnet for review
      vision: "claude-sonnet-4-6",              // Vision-capable model
    },
  },
});
PurposeDescription
explorationRunbook generation
exploration-lightRoutine exploration steps
selectorHigh-frequency selector resolution
extractionHigh-frequency data extraction
reviewReview, patch, suggestions
fallbackAgent Fallback
visionVision Fallback (screenshot-based)

Proxy configuration

// URL string
const client = new Refrain({
  ai: { ... },
  proxy: "http://user:[email protected]:8080",
});

// Config object
const client = new Refrain({
  ai: { ... },
  proxy: {
    server: "http://proxy.example.com:8080",
    username: "user",
    password: "pass",
  },
});

execute()

const report = await client.execute(runbook, options);

ExecuteOptions

PropertyRequiredDefaultDescription
contextMarkdownYesSupplementary context markdown
variablesNoTemplate variable values
secretsNoSecret variables (masked in logs)
stepDelayNoYAML valueDelay between steps (ms)
executionStrategyNoCustom retry strategy
enableSelectorCacheNofalsePersist successful selector resolutions
enableAgentFallbackNofalseAI alternative path exploration
enableVisionFallbackNofalseScreenshot-based resolution
outputDirNoDirectory for downloads and exports
screenshotDirNoDirectory to save screenshots
debugLogPathNoPath for debug log (JSONL)
runbookPathNoRunbook file path (used as cache key)
mergeDownloadsNofalseMerge downloaded CSV files
jobTimeoutMsNoplan valueJob timeout in milliseconds
skillsNoSkill plugin names
dataStoreNoMemory data collection store

ExecutionReport

The execute() method returns an ExecutionReport:
interface ExecutionReport {
  runbookTitle: string;
  startUrl: string;
  totalSteps: number;
  executed: number;
  succeeded: number;
  failed: number;
  skipped: number;
  aborted: boolean;
  steps: StepExecutionResult[];
  totalDurationMs: number;
  memoryCollections?: Record<string, number>;
  downloadedFiles?: string[];
  videoPaths?: string[];
  aiMetrics?: AIMetricsSummary;
}
See Types for the full StepExecutionResult reference.

loadRunbook()

Load and parse a YAML file:
import { loadRunbook } from "@refrainai/sdk";

const runbook = await loadRunbook("./runbooks/login-flow.yaml");
console.log(runbook.title, runbook.steps.length);

dispose()

Clean up resources:
await client.dispose();
Always call dispose() when you’re done to ensure the browser process is properly terminated.