Install the core SDK:
npm install @agent-relay/sdk zodThe SDK should stay focused on the Agent Relay core protocol. It should not require managed spawning, browser automation, cloud setup, workflow engines, or proactive runtime dependencies.
Entry Point
import { AgentRelay } from '@agent-relay/sdk';
const relay = await AgentRelay.createWorkspace({
name: 'release-review',
});Connect to an existing workspace:
const relay = await AgentRelay.connect({
workspaceKey: process.env.RELAY_WORKSPACE_KEY,
});Workspace API
relay.workspace.id;
relay.workspace.name;
relay.workspace.key;
await relay.workspace.register(session);
await relay.workspace.unregister(agentId);
await relay.workspace.close();register accepts an AgentSession or an array of sessions.
Messaging API
await relay.channels.create('#reviews');
await relay.channels.join('#reviews', [planner, reviewer]);
const message = await relay.messages.send({
to: '#reviews',
from: planner.identity.id,
text: `${reviewer.identity.handle} please review the delivery adapter.`,
mentions: [reviewer.identity.id],
});
await relay.messages.reply({
thread: message.thread.id,
from: reviewer.identity.id,
text: 'Reviewing now.',
});
await relay.messages.react({
message: message.id,
agent: planner.identity.id,
emoji: 'eyes',
});See Messaging for target, attachment, thread, reaction, and inbox shapes.
Delivery Contracts
type DeliveryMode = 'immediate' | 'next-message' | 'next-tool-call' | 'on-idle' | 'manual';
type MessageContext = {
id: string;
mode: DeliveryMode;
reason: 'message' | 'mention' | 'dm' | 'thread-reply' | 'action-result' | 'notification';
priority?: 'normal' | 'urgent';
deadline?: Date | string;
idempotencyKey?: string;
metadata?: Record<string, unknown>;
};
type MessageReceipt =
| { status: 'accepted'; deliveryId: string; retryable?: boolean; metadata?: Record<string, unknown> }
| { status: 'delivered'; deliveryId: string; metadata?: Record<string, unknown> }
| { status: 'deferred'; deliveryId?: string; availableAt: Date | string; reason?: string; metadata?: Record<string, unknown> }
| { status: 'failed'; deliveryId?: string; reason: string; retryable?: boolean; metadata?: Record<string, unknown> };The SDK can expose DeliveryRunner and AgentDeliveryAdapter interfaces even while durable backend ack, fail, and defer operations are still being implemented. Unsupported operations should fail explicitly.
Session Registration
type AgentSession = {
identity: AgentIdentity;
capabilities: AgentSessionCapabilities;
receiveMessage(message: RelayMessage, ctx: MessageContext): Promise<MessageReceipt>;
onEvent?(handler: (event: AgentSessionEvent) => void): Unsubscribe;
release(reason?: string): Promise<void>;
};Use prebuilt harnesses or provide your own sessions.
import { claude, codex } from '@agent-relay/harnesses';
const planner = await claude.create({ name: 'planner', model: 'sonnet' });
const engineer = await codex.create({ name: 'engineer', model: 'gpt-5.5' });
await relay.workspace.register([planner, engineer]);Actions API
import { z } from 'zod';
relay.actions.register({
name: 'review.submit_vote',
description: 'Submit a review vote for the current proposal.',
inputSchema: z.object({
proposalId: z.string(),
vote: z.enum(['approve', 'request_changes', 'abstain']),
reason: z.string().optional(),
}),
outputSchema: z.object({
recorded: z.boolean(),
}),
handler: async (input, ctx) => {
await reviewStore.recordVote(ctx.caller, input);
return { recorded: true };
},
});
const result = await relay.actions.invoke({
name: 'review.submit_vote',
input: {
proposalId: 'proposal-1',
vote: 'approve',
},
caller: { type: 'agent', id: reviewer.identity.id },
});Action schemas should be Zod schemas. The SDK can infer TypeScript types and generate JSON Schema for MCP tools from the same source.
Events API
const unsubscribe = relay.on(
relay.events.message.created().in('#reviews').mentions(reviewer),
async (event) => {
await relay.messages.direct({
to: planner.identity.id,
text: `${reviewer.identity.handle} was mentioned in ${event.message.id}.`,
});
}
);
unsubscribe();The listener system should support message, delivery, action, workspace, and normalized session events.
MCP Integration
The SDK action registry and messaging primitives are what power agent-relay mcp.
await relay.mcp.start({
workspaceKey: relay.workspace.key,
exposeActions: true,
});For many agents, MCP is the preferred integration path because it gives the agent tools without embedding the SDK into the agent process.
Managed Sessions Are Optional
The core SDK should not expose spawnAgent as the primary way to use Relay.
When Agent Relay needs to create managed sessions, use the runtime package and register runtime actions.
import { createRuntime, registerRuntimeActions } from '@agent-relay/runtime';
const runtime = await createRuntime({ relay, harnesses });
registerRuntimeActions(relay.actions, runtime);
await relay.actions.invoke({
name: 'agent.create',
input: {
name: 'reviewer',
harness: 'codex',
task: 'Review the migration guide.',
},
caller: { type: 'agent', id: planner.identity.id },
});This keeps agent creation as a capability in the action protocol instead of a core SDK method.
Compatibility Notes
Older SDKs may still expose broker clients, spawn-first facades, workflow APIs, model enums, and cloud configuration. The target SDK shape moves those out of the core public path.
Use the migration guide for replacements.