React to Run Events

View as Markdown

Every run emits a structured event stream - navigations, network failures, console errors. Subscribe over server-sent events and turn the ones you care about into alerts or interventions, while the run is still going.

1import { Bctrl } from "@bctrl/sdk";
2
3const bctrl = new Bctrl({ apiKey: process.env.BCTRL_API_KEY! });
4
5// streamUrl mints a ready-to-use SSE endpoint for the run.
6const url = bctrl.runs.events.streamUrl(runId);
7
8let networkFailures = 0;
9
10const source = new EventSource(url);
11source.onmessage = (message) => {
12 const event = JSON.parse(message.data);
13
14 switch (event.type) {
15 case "network.failed":
16 if (++networkFailures >= 5) {
17 notify(`run ${runId}: ${networkFailures} failed requests`); // your alerting
18 }
19 break;
20 case "console.message":
21 // surface page-side errors in your own logs
22 break;
23 case "navigation":
24 console.log("now at", event.time);
25 break;
26 }
27};

Filter at the source instead of in your handler when you only want one kind of event:

1const url = bctrl.runs.events.streamUrl(runId, { type: "console.message" });

Reacting, not just watching

The stream pairs with the rest of the API. A burst of network.failed events might mean the proxy exit went bad - stop the runtime and restart on a fresh sticky key. A page that’s clearly stuck is a good moment to mint a takeover link and page a human, with the URL right in the alert.

For a after-the-fact version of the same data - paged, filterable, no connection to hold - use bctrl.runs.events.list(runId) instead. And if you want the human-readable rollup rather than the firehose, that’s activity.

Next