agent-relay-client
v0.4.17
Published
TypeScript client for Agent Relay — register agents, send messages, poll inbox, claim tasks
Maintainers
Readme
agent-relay-client
TypeScript client for Agent Relay. Implements the provider spec so you can build custom provider integrations without writing raw HTTP calls.
Install
bun add agent-relay-client
# or
npm install agent-relay-clientUsage
import { RelayClient } from "agent-relay-client";
const relay = new RelayClient({
baseUrl: "http://localhost:4850",
token: process.env.AGENT_RELAY_TOKEN,
});
// Register
const instanceId = crypto.randomUUID();
const agent = await relay.register({
id: "my-agent-id",
name: "my-project (my-rig @ my-machine)",
machine: "my-machine",
tags: ["my-rig", "my-project"],
capabilities: ["chat"],
instanceId,
meta: { cwd: process.cwd(), approvalMode: "open" },
});
const session = { instanceId, epoch: agent.epoch };
// Poll loop
let sinceId = await relay.cursor();
const messages = await relay.poll("my-agent-id", sinceId);
for (const msg of messages) {
if (msg.claimable) {
const claimed = await relay.claim(msg.id, "my-agent-id", session);
if (!claimed) continue; // another agent got it
}
// deliver to your AI session...
console.log(`[msg:${msg.id}] ${msg.from}: ${msg.body}`);
await relay.markRead(msg.id, "my-agent-id");
sinceId = msg.id;
}
// Send
await relay.send({
from: "my-agent-id",
to: "cap:review",
kind: "task",
body: "Can someone review PR #42?",
claimable: true,
payload: { title: "Review PR #42" },
idempotencyKey: "review-pr-42",
});
// Lifecycle
await relay.heartbeat("my-agent-id", session);
await relay.setReady("my-agent-id", true, session);
await relay.setStatus("my-agent-id", "busy", session);
await relay.setLabel("my-agent-id", "backend fixing");
const health = await relay.health();API
| Method | Purpose |
|--------|---------|
| register(agent) | Register or update an agent; returns the agent card with epoch |
| heartbeat(agentId, session?) | Keep-alive (returns false if agent was pruned or superseded) |
| setStatus(agentId, status, session?) | Update status: online, busy, idle, offline |
| setReady(agentId, ready, session?) | Signal initialization complete |
| setLabel(agentId, label) | Set human-friendly name (null to clear) |
| cursor() | Get latest message ID for poll bootstrap |
| poll(agentId, sinceId) | Fetch new unread messages |
| send(options) | Send a message |
| claim(messageId, agentId, session?) | Claim a claimable task (returns false on conflict) |
| renewClaim(messageId, agentId, session?) | Extend a claim lease while work is still running |
| markRead(messageId, agentId) | Mark a message as read |
| stats() | Get server stats |
| health() | Get relay health checks and degraded-state diagnostics |
See the provider spec for the full integration lifecycle.
