Stagehand on BCTRL

View as Markdown

Where a full agent decides its own steps, Stagehand actions let you own the control flow and spend AI only on the fuzzy parts: one natural-language action, one observation, one extraction at a time. Each runs as a hosted invocation - sequence them like ordinary async calls.

1import { Bctrl } from "@bctrl/sdk";
2import { z } from "zod";
3
4const bctrl = new Bctrl({ apiKey: process.env.BCTRL_API_KEY! });
5
6const runtime = await bctrl.runtimes.create({ type: "browser", name: "stagehand-recipe" });
7await bctrl.runtimes.start(runtime.id);
8
9await bctrl.runtimes.targets.create(runtime.id, {
10 uri: "https://github.com/trending",
11 activate: true,
12});
13
14// One natural-language action...
15await bctrl.runtimes.invocations.createAndWait(runtime.id, {
16 action: "act",
17 instruction: "Switch the trending language filter to Python.",
18});
19
20// ...one structured read.
21const result = await bctrl.runtimes.invocations.createAndWait(runtime.id, {
22 action: "extract",
23 instruction: "Extract the top 3 trending repositories.",
24 schema: z.object({
25 repos: z.array(
26 z.object({
27 name: z.string(),
28 description: z.string(),
29 starsToday: z.number(),
30 })
31 ),
32 }),
33});
34
35console.log(result.output);
36
37await bctrl.runtimes.stop(runtime.id);

Use action: "observe" between steps when the next move depends on what the page offers (“What filters are available?”). The stagehand.act / .observe / .extract / .agent helpers on bctrl.runtimes.invocations expose the same actions with richer options and return immediately - reach for them when you want to dispatch without blocking.

When the flow gets long

If you’re chaining more than a handful of steps with retries and branches, flip it around: hand the whole task to a multi-step agent and keep your code out of the loop.

1await bctrl.runtimes.invocations.createAndWait(
2 runtime.id,
3 {
4 action: "stagehandAgent",
5 instruction: "Download every invoice from the last quarter.",
6 maxSteps: 30,
7 },
8 { timeoutMs: 600_000 }
9);

Next