Workspaces

View as Markdown

A workspace is an isolated container for an AI agent’s resources. When you create a workspace, you define what the agent has access to — AI credentials, secrets, storage — and then launch runtimes inside it.

Creating a workspace

1import { Bctrl } from "@bctrl/sdk";
2
3const bctrl = new Bctrl({ apiKey: process.env.BCTRL_API_KEY! });
4
5const workspace = await bctrl.workspaces.create({
6 name: "sales-automation",
7});

The name identifies this workspace. You get back a WorkspaceClient that you use to launch runtimes, execute steps, and manage the workspace’s lifecycle.

Mounting resources

Most workspaces need access to AI providers, a secret vault, or shared storage. You attach these at creation time via mounts:

1const workspace = await bctrl.workspaces.create({
2 name: "sales-automation",
3 mounts: {
4 ai: {
5 allow: ["openai-prod", "anthropic-prod"],
6 defaults: {
7 openai: "openai-prod",
8 anthropic: "anthropic-prod",
9 },
10 },
11 vault: {
12 allow: ["prod/crm/", "prod/email/"],
13 deny: ["prod/admin/"],
14 allowRawReads: true,
15 },
16 storage: {
17 workspace: "shared-exports",
18 },
19 },
20});

Controls which AI provider credentials the workspace can use. allow is a list of credential IDs (managed via bctrl.aiCredentials). defaults sets the default credential per provider — runtimes and agents will use these unless overridden.

Controls which secrets from your vault the workspace can access. Scoped by key prefix — allow: ["prod/crm/"] means the workspace can read any secret under prod/crm/ but nothing else. deny explicitly blocks prefixes. allowRawReads controls whether plaintext secret values can be read directly.

Connects a storage namespace to the workspace. Files uploaded by runtimes (screenshots, downloads, exports) are stored here. Multiple workspaces can share the same storage namespace.

All runtimes launched inside the workspace inherit these mounts. See Scopes & Inheritance for how narrowing works.

Opening an existing workspace

If you already have a workspace ID:

1const workspace = await bctrl.workspaces.open("ws_abc123");

Listing workspaces

1const workspaces = await bctrl.workspaces.list();

Workspace state

Query the current state of a workspace — its active runtimes, mounted resources, and configuration:

1const state = await workspace.state();

Execute

For low-level control, you can execute structured automation steps directly on the workspace without going through a driver:

1const result = await workspace.execute({
2 steps: [
3 { call: "browser.newContext" },
4 { call: "context.newPage", bind: "p" },
5 { call: "page.goto", ref: "p", args: ["https://example.com"] },
6 { call: "page.content", ref: "p" },
7 ],
8});

This is the HTTP-equivalent execution model. Most users should prefer the fluent driver APIs instead.