Connect Your Agent
Connect OpenClaw or a custom SDK agent to a Trayn run.
Before You Connect
Create the API key and training run in the Trayn app first. Your runtime needs:
| Value | Source |
|---|---|
TRAYN_API_KEY | API Keys page in the Trayn app. |
TRAYN_APP_URL | Usually https://app.trayn.ai. |
agentId | Required for direct harness() use. The CLI can resolve it from the run config. |
experimentId | Created when the app starts a run. |
trainingRunId | The active child run. |
sandboxTrainingRunUrl | Sandbox URL with sandbox_overlay=training_run and training_run_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 trainingRunId for task config, step capture, memory
retrieval, and grading.
{
"apiBaseUrl": "https://app.trayn.ai",
"sandboxOrigin": "https://app.trayn.ai",
"apiKey": "<api-key-from-trayn>",
"gatewayToken": "..."
}| Field | Purpose |
|---|---|
apiBaseUrl | Trayn app API origin. Defaults to TRAYN_APP_URL. |
sandboxOrigin | Origin used for sandbox and grading URLs. Defaults to TRAYN_APP_URL. |
apiKey | Trayn API key sent as Bearer to Trayn training APIs. |
gatewayToken | OpenClaw 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 chromiumImplement Agent and pass the run IDs from the app:
import { harness } from "@trayn/agent-sdk";
await harness({
agent_id: "{agentId}",
experiment_id: "{experimentId}",
training_run_id: "{trainingRunId}",
url_override: "{sandboxTrainingRunUrl}",
max_steps: 15,
agentargs: {
agent_name: "support-agent",
make_agent: () => ({
async init_session(params) {
console.log(params.agentId, params.trainingRunId, 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: GradingResult): Promise<void>;
init_session?(params: {
agentId: string;
sessionId: string;
experimentId: string;
trainingRunId: 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 grading, and writes validated results back through the training APIs.
CLI
The packaged CLI is a control/viewer for that same app-owned OpenClaw run. It
resolves agentId and trainingRunId from Trayn, starts or resumes the stored
run through the app endpoint, and renders timeline, state, pause, and grading
events from the same SDK live-session stream as the browser UI.
TRAYN_APP_URL=https://app.trayn.ai TRAYN_API_KEY=... trayn \
--url "{sandboxTrainingRunUrl}" \
--experiment-id "{experimentId}" \
--training-run-id "{trainingRunId}" \
--session-id "{sessionId}"Local repo installs expose the same CLI as trayn after just install.
The CLI calls
GET /api/training/training-runs/{trainingRunId}/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
openTrainingRunLiveSession(...) with an API-key-authenticated
TrainingRunLiveClient, so the CLI/TUI and browser page receive the same typed
timeline, state, pause, and grading events.
Custom Runtime Shape
If you are not using the OpenClaw plugin or @trayn/agent-sdk, keep the same
shape:
| Step | Requirement |
|---|---|
| Open sandbox | Use the app-created sandboxTrainingRunUrl. |
| Authenticate | Send Authorization: Bearer ${TRAYN_API_KEY} to Trayn training APIs. |
| Load config | Read /api/training/training-runs/{trainingRunId}/config; treat the returned ids and flags as canonical. |
| Retrieve memory | Use HttpTrainingMemoryClient.retrieve(...) before choosing an action. |
| Act | Return one valid browser action for the current observation. |
| Finish | Call POST /api/training/training-runs/{trainingRunId}/finish with { "trainingRunId": "..." }. |
| Save memory | Use HttpTrainingMemoryClient.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,
HttpTrainingMemoryClient,
} from "@trayn/memory";
const client = new HttpTrainingMemoryClient({
baseUrl: process.env.TRAYN_APP_URL!,
token: process.env.TRAYN_API_KEY,
});
const result = await client.retrieve(
buildMemoryRetrievalRequest({
session: {
agentId,
experimentId,
trainingRunId,
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);