Trayntrayn.ai

Connect Your Agent

Connect OpenClaw or a custom SDK agent to a Trayn run.

Before You Connect

Create the API key and rollout in the Trayn app first. Your runtime needs:

ValueSource
TRAYN_API_KEYAPI Keys page in the Trayn app.
TRAYN_APP_URLUsually https://app.trayn.ai.
agentIdRequired for direct harness() use. The CLI can resolve it from the run config.
experimentIdCreated when the app starts a run.
rolloutIdThe active child run.
sandboxRolloutUrlSandbox URL with sandbox_overlay=rollout and rollout_id.

TRAYN_API_KEY is mandatory for SDK and CLI runtimes. If it is missing, the CLI fails before launching the browser with a clear configuration error instead of starting a partial run.

OpenClaw Plugin

Use the Trayn OpenClaw plugin when OpenClaw owns the browser-control loop. The plugin uses the same rolloutId for task config, step capture, memory retrieval, and judging.

{
  "apiBaseUrl": "https://app.trayn.ai",
  "sandboxOrigin": "https://app.trayn.ai",
  "apiKey": "<api-key-from-trayn>",
  "gatewayToken": "..."
}
FieldPurpose
apiBaseUrlTrayn app API origin. Defaults to TRAYN_APP_URL.
sandboxOriginOrigin used for sandbox and judging URLs. Defaults to TRAYN_APP_URL.
apiKeyTrayn API key sent as Bearer to Trayn rollout APIs.
gatewayTokenOpenClaw gateway token. This is separate from the Trayn API key.

TypeScript SDK

Install the SDK with Bun:

bun add @trayn/agent-sdk
bunx playwright install chromium

Implement Agent and pass the run IDs from the app:

import { harness } from "@trayn/agent-sdk";

await harness({
  agent_id: "{agentId}",
  experiment_id: "{experimentId}",
  rollout_id: "{rolloutId}",
  url_override: "{sandboxRolloutUrl}",
  max_steps: 15,
  agentargs: {
    agent_name: "support-agent",
    make_agent: () => ({
      async init_session(params) {
        console.log(params.agentId, params.rolloutId, params.goal);
      },
      async get_action(obs) {
        return ["click('42')", { think: "Selecting the matching control." }];
      },
      async store_grades(result) {
        console.log(result.taskCompleted);
      },
    }),
  },
}).run();
interface Agent {
  get_action(obs: Observation): Promise<[string, AgentInfo]>;
  store_grades(result: JudgeResult): Promise<void>;
  init_session?(params: {
    agentId: string;
    sessionId: string;
    experimentId: string;
    rolloutId: string;
    taskId: string;
    host: string;
    goal: string;
    maxSteps?: number;
    startUrl: string;
  }): Promise<void>;
  reset?(): void;
  getRep?(): number;
}

The app-owned OpenClaw run fetches the task, drives the browser, streams steps to Trayn, triggers judging, and writes validated results back through the rollout APIs.

CLI

The packaged CLI is a control/viewer for that same app-owned OpenClaw run. It resolves agentId and rolloutId from Trayn, starts or resumes the stored run through the app endpoint, and renders timeline, state, pause, and judging events from the same SDK live-session stream as the browser UI.

TRAYN_APP_URL=https://app.trayn.ai TRAYN_API_KEY=... trayn \
  --url "{sandboxRolloutUrl}" \
  --experiment-id "{experimentId}" \
  --rollout-id "{rolloutId}" \
  --session-id "{sessionId}"

Local repo installs expose the same CLI as trayn after just install.

The CLI calls GET /api/rollouts/{rolloutId}/config, validates any supplied --agent-id, --experiment-id, and --session-id against the server response, then starts or resumes the stored app-owned OpenClaw run through POST /api/agents/{agentId}/run/start. It uses openRolloutLiveSession(...) with an API-key-authenticated RolloutLiveClient, so the CLI/TUI and browser page receive the same typed timeline, state, pause, and judging events.

Custom Runtime Shape

If you are not using the OpenClaw plugin or @trayn/agent-sdk, keep the same shape:

StepRequirement
Open sandboxUse the app-created sandboxRolloutUrl.
AuthenticateSend Authorization: Bearer ${TRAYN_API_KEY} to Trayn rollout APIs.
Load configRead /api/rollouts/{rolloutId}/config; treat the returned ids and flags as canonical.
Retrieve memoryUse HttpMemoryClient.retrieve(...) before choosing an action.
ActReturn one valid browser action for the current observation.
FinishCall POST /api/rollouts/{rolloutId}/finish with { "rolloutId": "..." }.
Save memoryUse HttpMemoryClient.save(...) with the same run IDs and step screenshot.

Memory Client

Use @trayn/memory when your own runtime needs the same memory route shape the OpenClaw plugin uses.

import {
  buildMemoryRetrievalRequest,
  HttpMemoryClient,
} from "@trayn/memory";

const client = new HttpMemoryClient({
  baseUrl: process.env.TRAYN_APP_URL!,
  token: process.env.TRAYN_API_KEY,
});

const result = await client.retrieve(
  buildMemoryRetrievalRequest({
    session: {
      agentId,
      experimentId,
      rolloutId,
      sessionId,
      host,
      goal,
      maxSteps,
      startUrl,
    },
    turn: {
      mode: "step",
      stepNum,
      currentUrl,
      recentActions,
      lastAction,
      lastError,
      focusedElement,
    },
    environment: {
      url: currentUrl,
      snapshot,
      screenshotBase64,
      elements,
      elementCount: elements.length,
    },
    config: { finalK: 3 },
  })
);

console.log(result.promptSection);

On this page