Triggers & runs

What starts work, and what a single execution looks like

A trigger is what starts a run. A run is a single execution of a Task or an agent. Triggers are the front door; runs are the record of what happened. Together they’re how Rightbrain moves from “a thing I built” to “a thing that operates.”

Triggers

Anything that can fire an event can start a run. A trigger targets a Task or an agent.

TriggerHow it fires
API callA direct POST .../run request.
WebhookAn inbound HTTP call to a public endpoint.
ScheduleA cron expression runs it on a timer.
Gmail inboxA new email in a connected inbox.
SlackA message in a connected workspace.

Webhook triggers

A webhook trigger has a public invoke endpoint:

POST /api/v1/public/webhook/{project_id}/{endpoint_id}

Authentication is either hmac_sha256 (the caller signs the payload with a shared secret, sent in the configured signature header) or bearer_token (a bearer token). The auth method is fixed at creation — to switch methods, create a new trigger. Webhook triggers support optional payload mapping and idempotency, and you can rotate the secret or regenerate the endpoint.

HMAC authentication supports prefix, timestamp_kv, plain, and standard_webhooks signature formats. Standard Webhooks v1 uses a Base64-encoded HMAC over the message ID, timestamp, and raw body. Its default headers are webhook-signature, webhook-timestamp, and webhook-id, with a default timestamp tolerance of 300 seconds. The message ID also becomes the idempotency key when no payload path supplies one.

Configure idempotency_key_path when the sender may retry deliveries. Rightbrain remembers the extracted key for idempotency_ttl_seconds, preventing the same event from starting duplicate work during that window. Keep the same event ID when retrying.

For a task target, a duplicate returns 409 with error.code: "DUPLICATE_REQUEST" and error.original_task_run_id. For an agent target, a duplicate returns 202 with is_duplicate: true and the original event_id. These responses do not start another run. A bad signature returns 401 with error.code: "AUTH_FAILED".

Response behavior depends on the target. A task-targeted webhook runs synchronously and returns 200 with the run result in the body. An agent-targeted webhook returns 202 with the trigger event ID and processes the run in the background. Either way the invocation is recorded as a trigger event you can list and inspect.

Schedule and inbox triggers

  • Schedule — a cron trigger that fires on a recurring timer.
  • Gmail inbox — fires an agent (or Task) when mail arrives in a connected Gmail inbox, passing the message through as input.

Each trigger type records its own events, so you can see every firing and its outcome.

Runs

A run captures one execution end to end: inputs, tool calls, output, token counts, timing, and credits.

Statuses

Agent runs move through runningwaiting_for_human (paused for an approval) → completed or failed. Task runs are request/response — they return the TaskRun directly.

Streaming (agents)

Agent runs stream Server-Sent Events so you can render progress live — incremental text, each tool call and its result, approval pauses, and a terminal done event. See Run agents via API for the full event reference and how to handle the stream.

Files in and out

Runs handle files through a runtime file registry. Agents accept uploaded input files (multipart or base64), pass them between tools within a single run, and track generated files with provenance (whether a file was an input or was generated, and by which Task). A paused run resumes with its file manager intact. Files are retrievable per run:

GET .../task-agent/{agent_id}/run/{run_id}/file/{file_name}

Observability and usage

Every run is recorded for observability. Run and event endpoints expose the execution source, failure metadata, and per-model telemetry. Runs are metered in credits, and token, credit, timing, and usage reports are available per Task, per agent, and project-wide. Sensitive audit events are recorded in the tamper-evident audit log.

Signed webhook example

This creates an agent webhook, maps the incoming message, and sends one event. Set RB_API_KEY, ORG_ID, PROJECT_ID, and AGENT_ID in your environment. The management API uses your API key; the public invoke endpoint uses the separate webhook secret returned at creation.

  1. Create the webhook

    Run node webhook.mjs with Node.js 22+. The script creates an agent-targeted webhook, then signs and sends one event. The management request uses your API key; the response provides the webhook’s own secret and invoke URL.

    payload_mapping takes message from the incoming JSON. idempotency_key_path identifies retries of the same event. Store the returned auth_secret securely for future deliveries; do not log it.

  2. Sign the exact request bytes

    Serialize the payload once, then compute its HMAC-SHA256 using the webhook secret. The configured plain format expects lowercase hex with no prefix.

    Re-serializing the JSON, or adding whitespace or a newline after signing, changes the signature. For retries, preserve the event ID and body. Running this whole script again creates a new trigger and event.

  3. Send the event

    Send the signed body to endpoint_url with the signature in X-Signature. An agent webhook returns 202 with an event ID: this acknowledges receipt, not completed execution.

    The script prints the trigger and event IDs for inspection. A task-targeted webhook behaves differently: it returns the run result synchronously.

  4. Inspect the execution

    Set TRIGGER_ID and EVENT_ID to the printed IDs, then poll the event. Inspect status, error_code and error_message. A completed agent event includes task_agent_run_id for the agent run API.

    request_data.mapped_input lets you check the mapping. Store request data according to your application’s privacy requirements. When testing is finished, disable the temporary trigger with POST …/trigger/webhook/{trigger_id} and { "status": "disabled" }.

import { createHmac, randomUUID } from "node:crypto";
const base = "https://app.rightbrain.ai/api/v1";
const projectPath = `/org/${process.env.ORG_ID}/project/${process.env.PROJECT_ID}`;
const authorization = `Bearer ${process.env.RB_API_KEY}`;
const created = await fetch(`${base}${projectPath}/trigger/webhook`, {
method: "POST",
headers: { Authorization: authorization, "Content-Type": "application/json" },
body: JSON.stringify({
name: "Signed agent webhook",
target_type: "task_agent",
target_id: process.env.AGENT_ID,
auth_method: "hmac_sha256",
auth_config: {
signature_header: "X-Signature",
signature_format: "plain",
encoding: "hex",
},
payload_mapping: { message: "$.message" },
idempotency_key_path: "$.event_id",
}),
});
if (!created.ok) throw new Error(`Create webhook: HTTP ${created.status}`);
const trigger = await created.json();
// Store auth_secret in your secret manager for later deliveries; do not log it.
const body = JSON.stringify({
event_id: randomUUID(), // Reuse this ID when retrying this event.
message: "Create a product listing for headphones.",
});
const signature = createHmac("sha256", trigger.auth_secret)
.update(body, "utf8")
.digest("hex");
const invoked = await fetch(trigger.endpoint_url, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Signature": signature },
body, // Send exactly the bytes that were signed.
});
if (!invoked.ok) throw new Error(`Invoke webhook: HTTP ${invoked.status}`);
const accepted = await invoked.json();
console.log({ triggerId: trigger.id, eventId: accepted.event_id, status: accepted.status });

With signature_format: "prefix", configure the matching signature_prefix (for example sha256=) and include it in the signature header. This example explicitly selects plain so the signing and verification rules match.