Skip to content

Working across workspaces

A single Blenau identity can belong to several workspaces — your own, plus any you’ve been invited to. One credential reaches all of them, and every call is still isolated to exactly one workspace (tenant). This page explains how that works for agents and how to make sure a write lands where you meant it.

A workspace is a tenant: one GitHub-backed knowledge brain, with its own repos, documents and members. You reach Blenau with one of two kinds of credential:

  • A pinned token (blenau_tk_…) — scoped to a single workspace. Everything you do with it, reads and writes, stays in that one workspace. This is the simplest model and the one we recommend for automation and for any agent that writes.
  • Your personal identity (device-flow login, via @blenau/mcp or the CLI) — the same login you use in the dashboard, which may span several workspaces, with a real role in each (admin, member or reader).

The rule that keeps writes safe is simple:

Reads roam. Writes go to one workspace.

Reading across workspaces is harmless — you either find something or you don’t. A misrouted write commits to the wrong repo, so writing always targets one explicit workspace, with a checkpoint when you change it.

Before pointing at a workspace, list the ones you can reach. The response gives each workspace’s id (UUID), slug, name, your role, and whether you can_write there.

SurfaceCall
MCP (agent)list_workspaces
CLIblenau workspaces
APIGET /workspaces

A pinned token lists just its one workspace; a personal identity lists them all.

@blenau/mcp connects an agent (Claude Code, Cursor, Claude Desktop, …) to Blenau over stdio, with your login stored in the OS keychain. Register it once:

// ~/.claude.json (or via `claude mcp add`) — no secrets in this file
"mcpServers": {
"blenau": { "type": "stdio", "command": "npx", "args": ["-y", "@blenau/mcp"] }
}

Then log in once (device flow): npx -y @blenau/mcp login.

Once your identity spans more than one workspace, two extra tools appear:

  • list_workspaces — see where you can read and write.
  • set_active_workspace — choose the workspace that writes go to.

How the two operations behave:

  • Reads accept an optional workspace argument (slug or id) to look in a specific workspace. Omit it to read the active one.
  • Writes go to the active workspace. To write somewhere else, either switch deliberately with set_active_workspace (a visible, deliberate checkpoint), or pass workspace plus confirm: true on the write itself.

Switching to a workspace other than the current one, or aiming a single write at a different workspace, returns confirmation_required without doing anything:

{ "status": "confirmation_required",
"from": "acme", "to": "globex",
"message": "About to write to \"Globex\" but the active workspace is \"Acme\"." }

Re-call with the confirmation (confirm: true) to proceed. Don’t retry blindly — surface it to the user. This is what stops a write from silently landing in the wrong repo. Every write response also echoes the workspace it landed in, and the client verifies it matched what you intended.

If a repo or project should always use one workspace, set BLENAU_WORKSPACE (slug or id) in that project’s .mcp.json (or the host environment):

"blenau": {
"type": "stdio", "command": "npx", "args": ["-y", "@blenau/mcp"],
"env": { "BLENAU_WORKSPACE": "acme" }
}

The pin is an immutable anchor for that project: it becomes the active workspace at startup, and set_active_workspace to anywhere else will always ask to confirm and never move the anchor. This is the safe way to keep a project-local agent glued to one workspace.

The remote MCP server (api.blenau.com/mcp/http/) is a relay for third-party agents authenticated with a blenau_tk_ token. Because it is stateless and has no interactive confirmation, it applies the roam rule strictly:

  • Reads accept an optional workspace argument (a workspace UUID — get it from list_workspaces) to read across the workspaces your credential can reach.
  • Writes are pinned to the token’s workspace. They cannot name another workspace. To write in a different workspace, use a token pinned to that workspace.

This is deliberate: a stateless relay can’t offer the confirmation checkpoint the personal agent does, so it removes the ability to misroute a write entirely.

The wire selector is the header X-Blenau-Workspace: <uuid> (a workspace UUID — never a slug). Pinned tokens (blenau_tk_, dashboard cookie, magic-link) carry their own workspace; sending a header that disagrees is a 409.

Every write response includes a top-level workspace object — verify it matches the workspace you targeted. Errors use a stable envelope you can branch on by error.code:

{ "error": {
"code": "workspace_required | invalid_workspace_id | not_a_member | read_only_here | workspace_conflict",
"message": "<human-readable>",
"writable_workspaces": [ { "id": "", "slug": "", "name": "" } ] } }

Discovery endpoints (GET /workspaces, GET /health) never require a selector, so a multi-workspace identity can always list where it belongs. Call GET /workspaces without the X-Blenau-Workspace header.