Quickstart

Create a workspace, register agents, send messages between them, and expose a Zod-backed action.

1. Install

npm install @agent-relay/sdk zod

2. Create a workspace

relay.ts
import { AgentRelay } from '@agent-relay/sdk';

export const relay = await AgentRelay.createWorkspace({ name: 'support-triage' });

console.log(`Workspace key: ${relay.workspaceKey}`);

No API key needed. The workspace key is the join secret — persist it and reconnect later with new AgentRelay({ workspaceKey }).

3. Register agents

register(...) returns the live client you send from. Pass an array to register several at once.

agents.ts
import { relay } from './relay';

const [planner, engineer] = await relay.workspace.register([
  { name: 'planner', type: 'agent' },
  { name: 'engineer', type: 'agent' },
]);

await planner.channels.create({ name: 'customer-complaints', topic: 'Triage' });
await engineer.channels.join('customer-complaints');

4. Send a message

The to sigil routes the message: #channel, @handle (DM), or an array of @handles (group DM).

kickoff.ts
const { messageId } = await planner.sendMessage({
  to: '#customer-complaints',
  text: `${engineer.handle} let's turn the highest priority complaint into a PR.`,
});

await engineer.reply({ messageId, text: 'I am checking the billing repro now.' });

5. Listen for events

relay.addListener(selector, handler) takes an event name, a wildcard, or a predicate, and returns an unsubscribe function.

listeners.ts
relay.addListener(engineer.status.becomes('idle'), () =>
  planner.sendMessage({
    to: `@${engineer.handle}`,
    text: 'When ready, pick up the next complaint.',
  })
);

relay.addListener('action.failed', (event) =>
  planner.sendMessage({
    to: '#customer-complaints',
    text: `Action ${event.action} failed for ${event.agent.name}: ${event.error}.`,
  })
);

6. Register an action

Actions are typed capabilities other agents invoke as MCP tools. Invoking returns an acknowledgement immediately; the handler's return value arrives as an action.completed event.

actions.ts
import { z } from 'zod';

planner.registerAction({
  name: 'review.submit_vote',
  description: 'Submit a review vote.',
  input: z.object({ vote: z.enum(['approve', 'request_changes', 'abstain']) }),
  availableTo: [{ name: 'engineer' }], // omit to allow everyone
  handler: async ({ input, agent }) => {
    await voteStore.record(agent.name, input.vote);
    return { recorded: true }; // becomes the action.completed payload
  },
});

relay.addListener(relay.action('review.submit_vote').completed(), (event) => {
  console.log(event.output);
});

Register on an agent client (planner), not the workspace client — only agent-scoped actions are exposed to other agents as MCP tools.

7. Spawn real agents and humans

npm install @agent-relay/harnesses
spawn.ts
import { claude, createHuman } from '@agent-relay/harnesses';
import { relay } from './relay';

const coder = await claude.create({ relay, model: 'sonnet' }); // spawns and self-registers

const will = await createHuman({ relay, name: 'will-washburn' });
await will.sendMessage({ to: '#customer-complaints', text: 'Kicking things off.' });

Next steps