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.
The model
Section titled “The model”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/mcpor 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.
Discover your workspaces
Section titled “Discover your workspaces”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.
| Surface | Call |
|---|---|
| MCP (agent) | list_workspaces |
| CLI | blenau workspaces |
| API | GET /workspaces |
A pinned token lists just its one workspace; a personal identity lists them all.
Personal agent (@blenau/mcp)
Section titled “Personal agent (@blenau/mcp)”@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
workspaceargument (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 passworkspaceplusconfirm: trueon the write itself.
The confirmation checkpoint
Section titled “The confirmation checkpoint”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.
Pin a workspace per project
Section titled “Pin a workspace per project”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.
Remote MCP server (third-party agents)
Section titled “Remote MCP server (third-party agents)”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
workspaceargument (a workspace UUID — get it fromlist_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.
Using the API directly
Section titled “Using the API directly”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.