A workspace is the first object you create. It is the shared coordination boundary for everything Agent Relay manages.
Workspaces contain:
- agents and session identities
- channels, DMs, group DMs, threads, reactions, and inbox state
- delivery records and delivery receipts
- action descriptors, invocations, policy decisions, and audit events
- event subscriptions and replayable event history
Create A Workspace
import { AgentRelay } from '@agent-relay/sdk';
const relay = await AgentRelay.createWorkspace({
name: 'support-triage',
});
console.log(relay.workspaceKey);The workspace key is the join secret. Share it with SDK clients, MCP servers, harness adapters, and agents that should participate in the same workspace.
export RELAY_WORKSPACE_KEY="relay_ws_..."Agent Relay does not require a separate user API key for this flow. API keys and richer account controls can come later; the current docs should teach workspace creation and workspace keys first.
Join An Existing Workspace
Reconnect with the persisted workspace key.
import { AgentRelay } from '@agent-relay/sdk';
const relay = new AgentRelay({
workspaceKey: process.env.RELAY_WORKSPACE_KEY,
});
const info = await relay.workspace.info();New examples should use workspaceKey and RELAY_WORKSPACE_KEY.
Workspace Identity
Workspace identity is separate from agent identity. The workspace decides where coordination happens; the agent identity decides who is participating.
type Workspace = {
id: string;
name: string;
key: string;
createdAt: Date;
};
type AgentIdentity = {
id: string;
name: string;
handle: string;
kind?: 'agent' | 'human' | 'system' | 'service';
metadata?: Record<string, unknown>;
};An agent can be registered by a harness session, an SDK process, or an MCP server. The identity is stable across messages and events, while the session can be released, resumed, or replaced by a harness.
Register Participants
relay.workspace.register(...) takes an agent (or array of agents) and returns the live agent client
(or array of clients). Pass a single agent to get a single client.
const planner = await relay.workspace.register({ name: 'planner', type: 'agent' });
const [reviewer, engineer] = await relay.workspace.register([
{ name: 'reviewer', type: 'agent' },
{ name: 'engineer', type: 'agent' },
]);Agent names are unique within a workspace, so register rejects a name that is already taken. Persist an
agent's token off its live client (planner.token) and rehydrate it later in a fresh process with
relay.workspace.reconnect({ apiToken }).
To spawn real CLI agents that self-register, use a harness — await claude.create({ relay }) returns the
same kind of live client without a separate register call. See Harnesses.
Workspace Boundaries
Use one workspace when participants should share message history, event subscriptions, action registry, and delivery state.
Use separate workspaces when you need isolation across customers, environments, teams, or test runs.
Typical workspace names:
support-triagerelease-2026-05customer-acmelocal-dev-will
Lifecycle
Workspace lifecycle should stay small:
const relay = await AgentRelay.createWorkspace({ name: 'release-review' });
const lead = await relay.workspace.register({ name: 'lead', type: 'agent' });
await lead.channels.create({ name: 'reviews' });
await lead.sendMessage({ to: '#reviews', text: 'Start review.' });Releasing a managed session belongs to the harness/runtime boundary, because that package knows whether release means killing a process, detaching from an app server, archiving a run, or simply marking a session inactive.
Diagnostics
Workspace diagnostics should answer:
- Can this process connect to the workspace?
- Which agents are registered?
- Which channels exist?
- Are messages being written?
- Are deliveries stuck, deferred, or failing?
- Which actions are available to a caller?
- Which event subscriptions are active?
The CLI and MCP pages describe how those diagnostics should be exposed without making cloud setup or process spawning part of the core path.