trickroom / Docs
Sign in

SDK cheatsheet

This page maps the two things most backends do with Trickroom, running a task for a user and letting it use their accounts, to TypeScript SDK calls, followed by quick-reference examples for the rest of the client. Each call is described in full in the SDK reference.

Run a task for a user

A job is one task, run by an agent, for one of your users:

  1. Create a client: one per backend, with an application key
  2. Register the user: your ID becomes their external_id
  3. Submit a job: a task, and whether it needs the user’s computer
  4. Wait for the result, then read its output and files

Let it use their accounts

Jobs act in a user’s Gmail, GitHub or Slack only with a connection:

  1. Connect an account: a link for Google, a token for GitHub, Slack and Figma
  2. Pass it to a job in connection_ids; the job can use no others
  3. Decide approvals: writes wait for a person unless the integration allows them

Create a client

Install @trickroom/client and create one client per backend process. Keep the key on your server.

TypeScript
import { Trickroom } from "@trickroom/client";

const client = new Trickroom({
  baseUrl: process.env.TRICKROOM_API_URL!, // your deployment, with or without /v1
  apiKey: process.env.TRICKROOM_API_KEY!,  // tak_… from Settings → API keys
});

Register users

Safe on every sign-in: the same external_id returns the same user.

TypeScript
const user = await client.users.create({ external_id: "customer_123" });

// Computer jobs run on the user's own computer; assign it once.
await client.users.assignComputer(user.id);

Submit jobs

Pass a key so a retried request returns the first job instead of starting another.

TypeScript
const job = await client.jobs.create(
  {
    user_id: user.id,
    task: "Find this month's invoices and list their totals.",
    execution_mode: "tools",        // or "computer"
    connection_ids: [gmail.id],     // accounts it may use
  },
  "invoices-2026-09",
);

Wait for results

jobs.wait polls until the job completes, fails, is cancelled or times out.

TypeScript
const done = await client.jobs.wait(job.id);
if (done.status === "completed") {
  console.log(done.result_json);
  const { data: files } = await client.jobs.artifacts(job.id);
}
console.log(done.cost_nano?.total); // billed so far, in nanodollars

Follow progress

Read what the job did so far; page with the last cursor.

TypeScript
let after = 0;
const page = await client.jobs.events(job.id, { after });
for (const event of page.data) console.log(event.type, event.payload_json);
after = page.next_cursor ?? after;

Use their accounts

Google accounts connect through a link the user follows; the others take a token.

TypeScript
// Gmail, Google Drive, Google Calendar: redirect the user to link.url.
const link = await client.connections.createLink(user.id, {
  provider: "gmail",
  return_url: "https://your-app.example/settings/integrations",
});

// GitHub, Slack, Figma: send the user's token.
const github = await client.connections.connectToken("github", {
  user_id: user.id,
  token: githubToken,
});

const { data: accounts } = await client.connections.list(user.id);

Run flows

A flow is a task you define once and run with inputs.

TypeScript
const flow = await client.flows.get("flow_weekly_digest");
const run = await client.flows.run(
  flow.id,
  { user_id: user.id, version: flow.version as number, inputs: { week_of: "2026-09-28" } },
  "digest-2026-09-28",
);

Decide approvals

Use a separate key with approvals:decide, ideally where a person reviews the request.

TypeScript
const { data: waiting } = await client.approvals.list();
for (const approval of waiting) {
  await client.approvals.approve(approval.id); // or .reject(approval.id)
}

Handle errors

Every method throws TrickroomError when the API refuses a call. Check code; quote requestId to support.

TypeScript
import { TrickroomError } from "@trickroom/client";

try {
  await client.jobs.create({ user_id: user.id, task }, key);
} catch (error) {
  if (error instanceof TrickroomError && error.code === "idempotency_conflict") {
    // The key was used for different input: choose a new key.
  }
  throw error;
}