@agent-relay/sdk 2.3.13 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -838
- package/bin/agent-relay-broker +0 -0
- package/dist/__tests__/contract-fixtures.test.d.ts +2 -0
- package/dist/__tests__/contract-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/contract-fixtures.test.js +85 -0
- package/dist/__tests__/contract-fixtures.test.js.map +1 -0
- package/dist/__tests__/facade.test.d.ts +2 -0
- package/dist/__tests__/facade.test.d.ts.map +1 -0
- package/dist/__tests__/facade.test.js +257 -0
- package/dist/__tests__/facade.test.js.map +1 -0
- package/dist/__tests__/integration.test.d.ts +2 -0
- package/dist/__tests__/integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration.test.js +164 -0
- package/dist/__tests__/integration.test.js.map +1 -0
- package/dist/__tests__/pty.test.d.ts +2 -0
- package/dist/__tests__/pty.test.d.ts.map +1 -0
- package/dist/__tests__/pty.test.js +20 -0
- package/dist/__tests__/pty.test.js.map +1 -0
- package/dist/__tests__/quickstart.test.d.ts +2 -0
- package/dist/__tests__/quickstart.test.d.ts.map +1 -0
- package/dist/__tests__/quickstart.test.js +176 -0
- package/dist/__tests__/quickstart.test.js.map +1 -0
- package/dist/__tests__/spawn-from-env.test.d.ts +2 -0
- package/dist/__tests__/spawn-from-env.test.d.ts.map +1 -0
- package/dist/__tests__/spawn-from-env.test.js +206 -0
- package/dist/__tests__/spawn-from-env.test.js.map +1 -0
- package/dist/__tests__/unit.test.d.ts +2 -0
- package/dist/__tests__/unit.test.d.ts.map +1 -0
- package/dist/__tests__/unit.test.js +311 -0
- package/dist/__tests__/unit.test.js.map +1 -0
- package/dist/browser.d.ts +16 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +19 -0
- package/dist/browser.js.map +1 -0
- package/dist/client.d.ts +138 -526
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +407 -1509
- package/dist/client.js.map +1 -1
- package/dist/consensus-helpers.d.ts +103 -0
- package/dist/consensus-helpers.d.ts.map +1 -0
- package/dist/consensus-helpers.js +147 -0
- package/dist/consensus-helpers.js.map +1 -0
- package/dist/consensus.d.ts +72 -0
- package/dist/consensus.d.ts.map +1 -0
- package/dist/consensus.js +378 -0
- package/dist/consensus.js.map +1 -0
- package/dist/examples/demo.d.ts +2 -0
- package/dist/examples/demo.d.ts.map +1 -0
- package/dist/examples/demo.js +63 -0
- package/dist/examples/demo.js.map +1 -0
- package/dist/examples/example.d.ts +2 -0
- package/dist/examples/example.d.ts.map +1 -0
- package/dist/examples/example.js +80 -0
- package/dist/examples/example.js.map +1 -0
- package/dist/examples/quickstart.d.ts +2 -0
- package/dist/examples/quickstart.d.ts.map +1 -0
- package/dist/examples/quickstart.js +56 -0
- package/dist/examples/quickstart.js.map +1 -0
- package/dist/examples/ralph-loop.d.ts +2 -0
- package/dist/examples/ralph-loop.d.ts.map +1 -0
- package/dist/examples/ralph-loop.js +281 -0
- package/dist/examples/ralph-loop.js.map +1 -0
- package/dist/examples/workflow-superiority.d.ts +32 -0
- package/dist/examples/workflow-superiority.d.ts.map +1 -0
- package/dist/examples/workflow-superiority.js +1421 -0
- package/dist/examples/workflow-superiority.js.map +1 -0
- package/dist/index.d.ts +13 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -26
- package/dist/index.js.map +1 -1
- package/dist/logs.d.ts +70 -25
- package/dist/logs.d.ts.map +1 -1
- package/dist/logs.js +238 -42
- package/dist/logs.js.map +1 -1
- package/dist/models.d.ts +9 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +17 -0
- package/dist/models.js.map +1 -0
- package/dist/protocol.d.ts +366 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +2 -0
- package/dist/protocol.js.map +1 -0
- package/dist/pty.d.ts +8 -0
- package/dist/pty.d.ts.map +1 -0
- package/dist/pty.js +26 -0
- package/dist/pty.js.map +1 -0
- package/dist/relay-adapter.d.ts +139 -0
- package/dist/relay-adapter.d.ts.map +1 -0
- package/dist/relay-adapter.js +210 -0
- package/dist/relay-adapter.js.map +1 -0
- package/dist/relay.d.ts +277 -0
- package/dist/relay.d.ts.map +1 -0
- package/dist/relay.js +853 -0
- package/dist/relay.js.map +1 -0
- package/dist/shadow.d.ts +101 -0
- package/dist/shadow.d.ts.map +1 -0
- package/dist/shadow.js +174 -0
- package/dist/shadow.js.map +1 -0
- package/dist/spawn-from-env.d.ts +77 -0
- package/dist/spawn-from-env.d.ts.map +1 -0
- package/dist/spawn-from-env.js +172 -0
- package/dist/spawn-from-env.js.map +1 -0
- package/dist/workflows/barrier.d.ts +72 -0
- package/dist/workflows/barrier.d.ts.map +1 -0
- package/dist/workflows/barrier.js +162 -0
- package/dist/workflows/barrier.js.map +1 -0
- package/dist/workflows/builder.d.ts +114 -0
- package/dist/workflows/builder.d.ts.map +1 -0
- package/dist/workflows/builder.js +201 -0
- package/dist/workflows/builder.js.map +1 -0
- package/dist/workflows/cli.d.ts +11 -0
- package/dist/workflows/cli.d.ts.map +1 -0
- package/dist/workflows/cli.js +144 -0
- package/dist/workflows/cli.js.map +1 -0
- package/dist/workflows/coordinator.d.ts +73 -0
- package/dist/workflows/coordinator.d.ts.map +1 -0
- package/dist/workflows/coordinator.js +647 -0
- package/dist/workflows/coordinator.js.map +1 -0
- package/dist/workflows/custom-steps.d.ts +73 -0
- package/dist/workflows/custom-steps.d.ts.map +1 -0
- package/dist/workflows/custom-steps.js +321 -0
- package/dist/workflows/custom-steps.js.map +1 -0
- package/dist/workflows/dry-run-format.d.ts +6 -0
- package/dist/workflows/dry-run-format.d.ts.map +1 -0
- package/dist/workflows/dry-run-format.js +68 -0
- package/dist/workflows/dry-run-format.js.map +1 -0
- package/dist/workflows/file-db.d.ts +33 -0
- package/dist/workflows/file-db.d.ts.map +1 -0
- package/dist/workflows/file-db.js +108 -0
- package/dist/workflows/file-db.js.map +1 -0
- package/dist/workflows/index.d.ts +15 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +15 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/memory-db.d.ts +17 -0
- package/dist/workflows/memory-db.d.ts.map +1 -0
- package/dist/workflows/memory-db.js +33 -0
- package/dist/workflows/memory-db.js.map +1 -0
- package/dist/workflows/run.d.ts +38 -0
- package/dist/workflows/run.d.ts.map +1 -0
- package/dist/workflows/run.js +25 -0
- package/dist/workflows/run.js.map +1 -0
- package/dist/workflows/runner.d.ts +320 -0
- package/dist/workflows/runner.d.ts.map +1 -0
- package/dist/workflows/runner.js +2821 -0
- package/dist/workflows/runner.js.map +1 -0
- package/dist/workflows/state.d.ts +77 -0
- package/dist/workflows/state.d.ts.map +1 -0
- package/dist/workflows/state.js +140 -0
- package/dist/workflows/state.js.map +1 -0
- package/dist/workflows/templates.d.ts +47 -0
- package/dist/workflows/templates.d.ts.map +1 -0
- package/dist/workflows/templates.js +405 -0
- package/dist/workflows/templates.js.map +1 -0
- package/dist/workflows/trajectory.d.ts +87 -0
- package/dist/workflows/trajectory.d.ts.map +1 -0
- package/dist/workflows/trajectory.js +441 -0
- package/dist/workflows/trajectory.js.map +1 -0
- package/dist/workflows/types.d.ts +306 -0
- package/dist/workflows/types.d.ts.map +1 -0
- package/dist/workflows/types.js +23 -0
- package/dist/workflows/types.js.map +1 -0
- package/dist/workflows/validator.d.ts +11 -0
- package/dist/workflows/validator.d.ts.map +1 -0
- package/dist/workflows/validator.js +128 -0
- package/dist/workflows/validator.js.map +1 -0
- package/package.json +59 -53
- package/dist/discovery.d.ts +0 -10
- package/dist/discovery.d.ts.map +0 -1
- package/dist/discovery.js +0 -22
- package/dist/discovery.js.map +0 -1
- package/dist/errors.d.ts +0 -9
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -9
- package/dist/errors.js.map +0 -1
- package/dist/protocol/index.d.ts +0 -8
- package/dist/protocol/index.d.ts.map +0 -1
- package/dist/protocol/index.js +0 -8
- package/dist/protocol/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,867 +1,97 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@agent-relay/sdk`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript SDK for driving `agent-relay-broker init` over stdio.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Status
|
|
6
|
+
- Broker lifecycle + request/response protocol client implemented.
|
|
7
|
+
- Spawn/list/release/shutdown APIs implemented.
|
|
8
|
+
- Event subscription for broker `event` frames implemented.
|
|
9
|
+
- Agent idle detection — configurable silence threshold with `onAgentIdle` hook and `waitForIdle()`.
|
|
6
10
|
|
|
7
|
-
##
|
|
11
|
+
## Bundled binary
|
|
12
|
+
- The SDK package bundles `agent-relay-broker` inside `bin/` during `npm run build` and `npm pack`.
|
|
13
|
+
- By default, `AgentRelayClient` uses the bundled binary path when present.
|
|
14
|
+
- You can still override with `binaryPath` in `AgentRelayClient.start(...)`.
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
| Swarms.ai | Pre-built swarm types | Configuration-heavy |
|
|
13
|
-
| Strands | Self-organizing swarms | AWS ecosystem lock-in |
|
|
14
|
-
| **Agent Relay** | **Communication primitives** | **You design the orchestration** |
|
|
16
|
+
## Quick example
|
|
17
|
+
```ts
|
|
18
|
+
import { AgentRelayClient } from "@agent-relay/sdk";
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- **Parallel execution** - Fan-out to workers, fan-in results
|
|
20
|
-
- **Pipeline workflows** - Sequential processing across agents
|
|
21
|
-
- **Consensus decisions** - Group voting on critical choices
|
|
22
|
-
- **Self-organizing teams** - Dynamic task claiming via channels
|
|
23
|
-
- **Supervised agents** - Shadow monitoring for QA and oversight
|
|
24
|
-
|
|
25
|
-
See [examples/SWARM_PATTERNS.md](./examples/SWARM_PATTERNS.md) for detailed patterns and [examples/SWARM_CAPABILITIES.md](./examples/SWARM_CAPABILITIES.md) for how primitives map to swarm capabilities.
|
|
26
|
-
|
|
27
|
-
## Install
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
npm install @agent-relay/sdk
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
For standalone mode (in-process daemon), also install:
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
npm install @agent-relay/daemon
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Quick Start
|
|
40
|
-
|
|
41
|
-
### Standalone Mode (Zero Config)
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { createRelay } from '@agent-relay/sdk';
|
|
45
|
-
|
|
46
|
-
// Start a relay (in-process daemon - no setup required)
|
|
47
|
-
const relay = await createRelay();
|
|
48
|
-
|
|
49
|
-
// Create agents
|
|
50
|
-
const alice = await relay.client('Alice');
|
|
51
|
-
const bob = await relay.client('Bob');
|
|
52
|
-
|
|
53
|
-
// Bob listens for messages
|
|
54
|
-
bob.onMessage = (from, { body }) => {
|
|
55
|
-
console.log(`${from}: ${body}`);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Alice sends a message
|
|
59
|
-
alice.sendMessage('Bob', 'Hello!');
|
|
60
|
-
|
|
61
|
-
// When done
|
|
62
|
-
await relay.stop();
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Even Simpler: Two Agents
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
import { createPair } from '@agent-relay/sdk';
|
|
69
|
-
|
|
70
|
-
const { alice, bob, stop } = await createPair('alice', 'bob');
|
|
71
|
-
|
|
72
|
-
bob.onMessage = (from, { body }) => console.log(`${from}: ${body}`);
|
|
73
|
-
alice.sendMessage('bob', 'Hey!');
|
|
74
|
-
|
|
75
|
-
await stop();
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### External Daemon Mode
|
|
79
|
-
|
|
80
|
-
If you're running `agent-relay up` separately:
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
import { RelayClient } from '@agent-relay/sdk';
|
|
84
|
-
|
|
85
|
-
const client = new RelayClient({
|
|
86
|
-
agentName: 'MyAgent',
|
|
87
|
-
socketPath: '/tmp/agent-relay.sock', // optional, this is the default
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
await client.connect();
|
|
91
|
-
client.sendMessage('OtherAgent', 'Hello!');
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Features
|
|
95
|
-
|
|
96
|
-
| Feature | Description |
|
|
97
|
-
|---------|-------------|
|
|
98
|
-
| **Zero config** | Just import and go with standalone mode |
|
|
99
|
-
| **Auto-reconnect** | Handles disconnections automatically |
|
|
100
|
-
| **Message deduplication** | No duplicate deliveries |
|
|
101
|
-
| **Sync messaging** | Wait for acknowledgment with `sendAndWait()` |
|
|
102
|
-
| **Broadcast** | Send to all agents with `*` |
|
|
103
|
-
| **Channels** | Group messaging with `#channel` |
|
|
104
|
-
| **Pub/Sub** | Topic-based subscriptions |
|
|
105
|
-
| **Agent spawning** | Spawn, release, list, and send input to worker agents |
|
|
106
|
-
| **Shadow agents** | Monitor another agent's communication |
|
|
107
|
-
| **Consensus** | Distributed decision-making (external daemon only) |
|
|
108
|
-
| **Monitoring** | Health, metrics, agent discovery |
|
|
109
|
-
|
|
110
|
-
## API Reference
|
|
111
|
-
|
|
112
|
-
### Connection
|
|
113
|
-
|
|
114
|
-
#### connect()
|
|
115
|
-
|
|
116
|
-
Connect to the relay daemon. Returns a Promise that resolves when the connection is ready.
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
const client = new RelayClient({ agentName: 'MyAgent' });
|
|
120
|
-
await client.connect();
|
|
121
|
-
// Client is now ready to send/receive messages
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
#### disconnect()
|
|
125
|
-
|
|
126
|
-
Gracefully disconnect from the daemon. The client can reconnect later.
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
client.disconnect();
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
#### destroy()
|
|
133
|
-
|
|
134
|
-
Permanently destroy the client. Prevents automatic reconnection.
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
client.destroy();
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
#### Properties
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
client.state; // 'DISCONNECTED' | 'CONNECTING' | 'HANDSHAKING' | 'READY' | 'BACKOFF'
|
|
144
|
-
client.agentName; // The agent's name
|
|
145
|
-
client.currentSessionId; // Current session ID (undefined if not connected)
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Core Messaging
|
|
149
|
-
|
|
150
|
-
#### sendMessage(to, body, kind?, data?, thread?)
|
|
151
|
-
|
|
152
|
-
Send a message to another agent.
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
// Simple message
|
|
156
|
-
client.sendMessage('Bob', 'Hello!');
|
|
157
|
-
|
|
158
|
-
// With message kind and data
|
|
159
|
-
client.sendMessage('Bob', 'Task complete', 'action', { taskId: 123 });
|
|
160
|
-
|
|
161
|
-
// In a thread
|
|
162
|
-
client.sendMessage('Bob', 'Follow-up', 'message', undefined, 'thread-123');
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
#### sendAndWait(to, body, options?)
|
|
166
|
-
|
|
167
|
-
Send and wait for acknowledgment. Useful for ensuring delivery.
|
|
168
|
-
|
|
169
|
-
```typescript
|
|
170
|
-
const ack = await client.sendAndWait('Bob', 'Important message', {
|
|
171
|
-
timeoutMs: 5000, // default: 30000
|
|
172
|
-
});
|
|
173
|
-
console.log('Acknowledged:', ack);
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
#### broadcast(body, kind?, data?)
|
|
177
|
-
|
|
178
|
-
Send to all connected agents.
|
|
179
|
-
|
|
180
|
-
```typescript
|
|
181
|
-
client.broadcast('System notice to everyone');
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
#### request(to, body, options?)
|
|
185
|
-
|
|
186
|
-
Send a request and wait for a response from the target agent. This implements a request/response pattern where the target agent can respond with `respond()`.
|
|
187
|
-
|
|
188
|
-
```typescript
|
|
189
|
-
// Simple request
|
|
190
|
-
const response = await client.request('Worker', 'Process this task');
|
|
191
|
-
console.log(response.body); // Worker's response
|
|
192
|
-
console.log(response.from); // 'Worker'
|
|
193
|
-
|
|
194
|
-
// With options
|
|
195
|
-
const response = await client.request('Worker', 'Process task', {
|
|
196
|
-
timeout: 60000, // default: 30000ms
|
|
197
|
-
data: { taskId: '123', priority: 'high' },
|
|
198
|
-
thread: 'task-thread-1',
|
|
199
|
-
kind: 'action', // default: 'message'
|
|
200
|
-
});
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**RequestResponse type:**
|
|
204
|
-
```typescript
|
|
205
|
-
interface RequestResponse {
|
|
206
|
-
from: string; // sender of the response
|
|
207
|
-
body: string; // response text
|
|
208
|
-
data?: Record<string, unknown>;
|
|
209
|
-
correlationId: string;
|
|
210
|
-
thread?: string;
|
|
211
|
-
payload: SendPayload; // full payload for advanced use
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
#### respond(correlationId, to, body, data?)
|
|
216
|
-
|
|
217
|
-
Respond to a request from another agent. Use when you receive a message with a correlation ID.
|
|
218
|
-
|
|
219
|
-
```typescript
|
|
220
|
-
client.onMessage = (from, payload, messageId, meta) => {
|
|
221
|
-
const correlationId = meta?.replyTo || payload.data?._correlationId;
|
|
222
|
-
if (correlationId) {
|
|
223
|
-
// This is a request - send a response
|
|
224
|
-
client.respond(correlationId, from, 'Task completed!', { result: 42 });
|
|
225
|
-
}
|
|
226
|
-
};
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
#### sendAck(payload)
|
|
230
|
-
|
|
231
|
-
Send an ACK for a delivered message. Used internally, but available for custom acknowledgment flows.
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
client.sendAck({
|
|
235
|
-
ack_id: messageId,
|
|
236
|
-
seq: 123,
|
|
237
|
-
correlationId: 'optional-correlation-id',
|
|
238
|
-
});
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
#### onMessage
|
|
242
|
-
|
|
243
|
-
Callback for incoming messages.
|
|
244
|
-
|
|
245
|
-
```typescript
|
|
246
|
-
client.onMessage = (from, payload, messageId, meta, originalTo) => {
|
|
247
|
-
console.log(`${from}: ${payload.body}`);
|
|
248
|
-
|
|
249
|
-
// payload.kind: 'message' | 'action' | 'state' | 'thinking'
|
|
250
|
-
// payload.data: optional structured data
|
|
251
|
-
// payload.thread: optional thread ID
|
|
252
|
-
|
|
253
|
-
// Check if it was a broadcast
|
|
254
|
-
if (originalTo === '*') {
|
|
255
|
-
console.log('This was a broadcast');
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### Channels
|
|
261
|
-
|
|
262
|
-
#### joinChannel(channel, displayName?)
|
|
263
|
-
|
|
264
|
-
```typescript
|
|
265
|
-
client.joinChannel('#general');
|
|
266
|
-
client.joinChannel('#team', 'Alice (Lead)'); // with display name
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
#### leaveChannel(channel, reason?)
|
|
270
|
-
|
|
271
|
-
```typescript
|
|
272
|
-
client.leaveChannel('#general');
|
|
273
|
-
client.leaveChannel('#team', 'Signing off');
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
#### sendChannelMessage(channel, body, options?)
|
|
277
|
-
|
|
278
|
-
```typescript
|
|
279
|
-
// Simple message
|
|
280
|
-
client.sendChannelMessage('#general', 'Hello team!');
|
|
281
|
-
|
|
282
|
-
// With mentions and thread
|
|
283
|
-
client.sendChannelMessage('#general', 'Check this out', {
|
|
284
|
-
thread: 'discussion-123',
|
|
285
|
-
mentions: ['Bob', 'Charlie'],
|
|
286
|
-
attachments: [{ type: 'file', name: 'report.pdf', url: '...' }],
|
|
287
|
-
});
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
#### onChannelMessage
|
|
291
|
-
|
|
292
|
-
```typescript
|
|
293
|
-
client.onChannelMessage = (from, channel, body, envelope) => {
|
|
294
|
-
console.log(`[${channel}] ${from}: ${body}`);
|
|
295
|
-
// envelope contains full message details (thread, mentions, etc.)
|
|
296
|
-
};
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
#### Admin Channel Operations
|
|
300
|
-
|
|
301
|
-
```typescript
|
|
302
|
-
// Add a member to a channel (they don't need to be connected)
|
|
303
|
-
client.adminJoinChannel('#team', 'NewMember');
|
|
304
|
-
|
|
305
|
-
// Remove a member from a channel
|
|
306
|
-
client.adminRemoveMember('#team', 'FormerMember');
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
### Pub/Sub
|
|
310
|
-
|
|
311
|
-
Subscribe to topics for filtered message delivery.
|
|
312
|
-
|
|
313
|
-
```typescript
|
|
314
|
-
// Subscribe to a topic
|
|
315
|
-
client.subscribe('builds');
|
|
316
|
-
client.subscribe('deployments');
|
|
317
|
-
|
|
318
|
-
// Messages to that topic will be delivered via onMessage
|
|
319
|
-
client.onMessage = (from, payload) => {
|
|
320
|
-
if (payload.data?.topic === 'builds') {
|
|
321
|
-
console.log('Build notification:', payload.body);
|
|
322
|
-
}
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
// Unsubscribe
|
|
326
|
-
client.unsubscribe('builds');
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Agent Spawning
|
|
330
|
-
|
|
331
|
-
Spawn and manage worker agents programmatically.
|
|
332
|
-
|
|
333
|
-
```typescript
|
|
334
|
-
// Spawn a new agent
|
|
335
|
-
const result = await client.spawn({
|
|
336
|
-
name: 'Worker1',
|
|
337
|
-
cli: 'claude', // claude, codex, gemini, etc.
|
|
338
|
-
task: 'Process the data files',
|
|
339
|
-
cwd: '/path/to/workdir', // optional
|
|
20
|
+
const client = await AgentRelayClient.start({
|
|
21
|
+
binaryPath: "/absolute/path/to/agent-relay-broker",
|
|
22
|
+
env: process.env,
|
|
340
23
|
});
|
|
341
24
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const result = await client.spawn({
|
|
348
|
-
name: 'Worker2',
|
|
349
|
-
cli: 'claude',
|
|
350
|
-
task: 'Process data',
|
|
351
|
-
waitForReady: true, // wait for agent to connect
|
|
352
|
-
readyTimeoutMs: 60000, // timeout for ready (default: 60000)
|
|
25
|
+
await client.spawnPty({
|
|
26
|
+
name: "Worker1",
|
|
27
|
+
cli: "codex",
|
|
28
|
+
args: ["--model", "gpt-5"],
|
|
29
|
+
channels: ["general"],
|
|
353
30
|
});
|
|
354
31
|
|
|
355
|
-
if (result.ready) {
|
|
356
|
-
console.log('Worker is ready:', result.readyInfo);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// Release (terminate) an agent
|
|
360
|
-
const releaseResult = await client.release('Worker1');
|
|
361
|
-
const releaseWithReason = await client.release('Worker2', 'Task complete');
|
|
362
|
-
|
|
363
|
-
// Send input to a spawned agent's PTY
|
|
364
|
-
const inputResult = await client.sendWorkerInput('Worker1', 'yes\n');
|
|
365
|
-
console.log(inputResult.success); // true
|
|
366
|
-
|
|
367
|
-
// List active spawned workers
|
|
368
|
-
const workers = await client.listWorkers();
|
|
369
|
-
for (const w of workers.workers) {
|
|
370
|
-
console.log(`${w.name} (${w.cli}) spawned at ${new Date(w.spawnedAt)}`);
|
|
371
|
-
}
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
#### waitForAgentReady(name, timeoutMs?)
|
|
375
|
-
|
|
376
|
-
Wait for an agent to become ready (complete HELLO/WELCOME handshake). Useful when waiting for an agent spawned through another mechanism.
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
try {
|
|
380
|
-
const readyInfo = await client.waitForAgentReady('Worker', 30000);
|
|
381
|
-
console.log(`Worker is ready, using ${readyInfo.cli}`);
|
|
382
|
-
} catch (err) {
|
|
383
|
-
console.error('Worker did not become ready in time');
|
|
384
|
-
}
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
#### onAgentReady
|
|
388
|
-
|
|
389
|
-
Callback when any agent becomes ready (completes connection handshake).
|
|
390
|
-
|
|
391
|
-
```typescript
|
|
392
|
-
client.onAgentReady = (info) => {
|
|
393
|
-
console.log(`Agent ${info.name} is now ready (cli: ${info.cli})`);
|
|
394
|
-
};
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
#### sendWorkerInput(name, data, timeoutMs?)
|
|
398
|
-
|
|
399
|
-
Send input data to a spawned agent's PTY. Useful for answering prompts or sending commands to interactive agents.
|
|
400
|
-
|
|
401
|
-
```typescript
|
|
402
|
-
const result = await client.sendWorkerInput('Worker1', 'yes\n');
|
|
403
|
-
if (result.success) {
|
|
404
|
-
console.log('Input sent');
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
#### listWorkers(timeoutMs?)
|
|
409
|
-
|
|
410
|
-
List all active spawned workers managed by the daemon's SpawnManager.
|
|
411
|
-
|
|
412
|
-
```typescript
|
|
413
|
-
const result = await client.listWorkers();
|
|
414
|
-
for (const worker of result.workers) {
|
|
415
|
-
console.log(`${worker.name} (${worker.cli}) - team: ${worker.team || 'none'}`);
|
|
416
|
-
}
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
**ListWorkersResultPayload:**
|
|
420
|
-
```typescript
|
|
421
|
-
interface ListWorkersResultPayload {
|
|
422
|
-
replyTo: string;
|
|
423
|
-
workers: Array<{
|
|
424
|
-
name: string;
|
|
425
|
-
cli: string;
|
|
426
|
-
task: string;
|
|
427
|
-
team?: string;
|
|
428
|
-
spawnerName?: string;
|
|
429
|
-
spawnedAt: number;
|
|
430
|
-
pid?: number;
|
|
431
|
-
}>;
|
|
432
|
-
error?: string;
|
|
433
|
-
}
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
#### Spawn as Shadow
|
|
437
|
-
|
|
438
|
-
```typescript
|
|
439
|
-
// Spawn an agent that shadows another
|
|
440
|
-
await client.spawn({
|
|
441
|
-
name: 'Reviewer',
|
|
442
|
-
cli: 'claude',
|
|
443
|
-
task: 'Review code changes',
|
|
444
|
-
shadowOf: 'Developer',
|
|
445
|
-
shadowSpeakOn: ['error', 'complete'],
|
|
446
|
-
});
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
### Shadow Agents
|
|
450
|
-
|
|
451
|
-
Monitor another agent's communication without them knowing.
|
|
452
|
-
|
|
453
|
-
```typescript
|
|
454
|
-
// Bind as shadow to see all messages to/from PrimaryAgent
|
|
455
|
-
client.bindAsShadow('PrimaryAgent', {
|
|
456
|
-
receiveIncoming: true, // see messages sent TO the primary
|
|
457
|
-
receiveOutgoing: true, // see messages sent BY the primary
|
|
458
|
-
speakOn: ['error'], // triggers that allow shadow to speak
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
// Unbind
|
|
462
|
-
client.unbindAsShadow('PrimaryAgent');
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
### Logging
|
|
466
|
-
|
|
467
|
-
Stream logs to the daemon (for dashboard display).
|
|
468
|
-
|
|
469
|
-
```typescript
|
|
470
|
-
// Send log output
|
|
471
|
-
client.sendLog('Starting task...');
|
|
472
|
-
client.sendLog('Processing file 1 of 10');
|
|
473
|
-
client.sendLog('Error: File not found');
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
### Consensus (External Daemon Only)
|
|
477
|
-
|
|
478
|
-
Distributed decision-making across agents. **Note:** Consensus requires an external daemon - it's disabled in standalone mode.
|
|
479
|
-
|
|
480
|
-
#### Consensus Types
|
|
481
|
-
|
|
482
|
-
| Type | Description |
|
|
483
|
-
|------|-------------|
|
|
484
|
-
| `majority` | >50% agreement (default) |
|
|
485
|
-
| `supermajority` | >=2/3 agreement (configurable) |
|
|
486
|
-
| `unanimous` | 100% agreement required |
|
|
487
|
-
| `weighted` | Votes weighted by role/expertise |
|
|
488
|
-
| `quorum` | Minimum participation + majority |
|
|
489
|
-
|
|
490
|
-
#### Create a Proposal
|
|
491
|
-
|
|
492
|
-
```typescript
|
|
493
|
-
client.createProposal({
|
|
494
|
-
title: 'Approve API design',
|
|
495
|
-
description: 'Should we proceed with the REST API design?',
|
|
496
|
-
participants: ['Developer', 'Reviewer', 'Lead'],
|
|
497
|
-
consensusType: 'majority',
|
|
498
|
-
timeoutMs: 300000, // 5 minutes, optional
|
|
499
|
-
threshold: 0.67, // for supermajority, optional
|
|
500
|
-
quorum: 2, // minimum votes, optional
|
|
501
|
-
});
|
|
502
|
-
```
|
|
503
|
-
|
|
504
|
-
#### Vote on a Proposal
|
|
505
|
-
|
|
506
|
-
```typescript
|
|
507
|
-
client.vote({
|
|
508
|
-
proposalId: 'prop_123_abc',
|
|
509
|
-
value: 'approve', // or 'reject', 'abstain'
|
|
510
|
-
reason: 'Looks good to me', // optional
|
|
511
|
-
});
|
|
512
|
-
```
|
|
513
|
-
|
|
514
|
-
#### Receiving Proposals and Results
|
|
515
|
-
|
|
516
|
-
```typescript
|
|
517
|
-
client.onMessage = (from, payload) => {
|
|
518
|
-
if (payload.data?._isConsensusMessage) {
|
|
519
|
-
console.log('Consensus message:', payload.body);
|
|
520
|
-
}
|
|
521
|
-
};
|
|
522
|
-
```
|
|
523
|
-
|
|
524
|
-
### Monitoring & Discovery
|
|
525
|
-
|
|
526
|
-
#### List Online Agents
|
|
527
|
-
|
|
528
|
-
```typescript
|
|
529
32
|
const agents = await client.listAgents();
|
|
530
|
-
|
|
531
|
-
console.log(`${agent.name} (${agent.cli}) - ${agent.idle ? 'idle' : 'active'}`);
|
|
532
|
-
}
|
|
33
|
+
console.log(agents);
|
|
533
34
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
const projectAgents = await client.listAgents({ project: 'myproject' });
|
|
35
|
+
await client.release("Worker1");
|
|
36
|
+
await client.shutdown();
|
|
537
37
|
```
|
|
538
38
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const health = await client.getHealth();
|
|
543
|
-
console.log(`Health score: ${health.healthScore}/100`);
|
|
544
|
-
console.log(`Issues: ${health.issues.length}`);
|
|
545
|
-
console.log(`Recommendations:`, health.recommendations);
|
|
546
|
-
|
|
547
|
-
// Options
|
|
548
|
-
const health = await client.getHealth({
|
|
549
|
-
includeCrashes: true, // include crash history
|
|
550
|
-
includeAlerts: true, // include alerts
|
|
551
|
-
});
|
|
552
|
-
```
|
|
39
|
+
### High-level API with idle detection
|
|
40
|
+
```ts
|
|
41
|
+
import { AgentRelay } from "@agent-relay/sdk";
|
|
553
42
|
|
|
554
|
-
|
|
43
|
+
const relay = new AgentRelay();
|
|
555
44
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
// System overview
|
|
560
|
-
console.log(`Heap used: ${metrics.system.heapUsed}`);
|
|
561
|
-
console.log(`Free memory: ${metrics.system.freeMemory}`);
|
|
562
|
-
|
|
563
|
-
// Per-agent metrics
|
|
564
|
-
for (const agent of metrics.agents) {
|
|
565
|
-
console.log(`${agent.name}: ${agent.rssBytes} bytes, ${agent.cpuPercent}% CPU`);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// Filter to specific agent
|
|
569
|
-
const workerMetrics = await client.getMetrics({ agent: 'Worker1' });
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
#### Get Daemon Status
|
|
573
|
-
|
|
574
|
-
```typescript
|
|
575
|
-
const status = await client.getStatus();
|
|
576
|
-
console.log(`Version: ${status.version}`);
|
|
577
|
-
console.log(`Uptime: ${status.uptime}ms`);
|
|
578
|
-
console.log(`Agents: ${status.agentCount}`);
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
#### Get Inbox Messages
|
|
582
|
-
|
|
583
|
-
```typescript
|
|
584
|
-
const messages = await client.getInbox({ limit: 10 });
|
|
585
|
-
for (const msg of messages) {
|
|
586
|
-
console.log(`From ${msg.from}: ${msg.body}`);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
// Filter options
|
|
590
|
-
const unread = await client.getInbox({ unreadOnly: true });
|
|
591
|
-
const fromAlice = await client.getInbox({ from: 'Alice' });
|
|
592
|
-
const channelMsgs = await client.getInbox({ channel: '#general' });
|
|
593
|
-
```
|
|
594
|
-
|
|
595
|
-
#### Query All Messages
|
|
596
|
-
|
|
597
|
-
Query all messages (not filtered by recipient). Useful for dashboards or analytics.
|
|
598
|
-
|
|
599
|
-
```typescript
|
|
600
|
-
const messages = await client.queryMessages({
|
|
601
|
-
limit: 100, // default: 100
|
|
602
|
-
sinceTs: Date.now() - 3600000, // last hour
|
|
603
|
-
from: 'Alice', // filter by sender
|
|
604
|
-
to: 'Bob', // filter by recipient
|
|
605
|
-
thread: 'thread-123', // filter by thread
|
|
606
|
-
order: 'desc', // 'asc' or 'desc' (default: 'desc')
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
for (const msg of messages) {
|
|
610
|
-
console.log(`${msg.from} -> ${msg.to}: ${msg.body}`);
|
|
611
|
-
}
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
#### List Connected Agents Only
|
|
615
|
-
|
|
616
|
-
Unlike `listAgents()` which includes historical/registered agents, this only returns agents currently connected.
|
|
617
|
-
|
|
618
|
-
```typescript
|
|
619
|
-
const connected = await client.listConnectedAgents();
|
|
620
|
-
for (const agent of connected) {
|
|
621
|
-
console.log(`${agent.name} is connected right now`);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// Filter by project
|
|
625
|
-
const projectAgents = await client.listConnectedAgents({ project: 'myproject' });
|
|
626
|
-
```
|
|
627
|
-
|
|
628
|
-
#### Remove Agent
|
|
629
|
-
|
|
630
|
-
Remove a stale agent from the registry (sessions, agents.json). Use to clean up agents no longer needed.
|
|
631
|
-
|
|
632
|
-
```typescript
|
|
633
|
-
const result = await client.removeAgent('OldWorker');
|
|
634
|
-
if (result.success) {
|
|
635
|
-
console.log('Agent removed');
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
// Also remove all messages from/to this agent
|
|
639
|
-
await client.removeAgent('OldWorker', { removeMessages: true });
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
#### Read Agent Logs (File-based)
|
|
643
|
-
|
|
644
|
-
Logs are stored locally and can be read without a connection:
|
|
645
|
-
|
|
646
|
-
```typescript
|
|
647
|
-
import { getLogs, listLoggedAgents } from '@agent-relay/sdk';
|
|
648
|
-
|
|
649
|
-
// List agents with logs
|
|
650
|
-
const agents = await listLoggedAgents();
|
|
651
|
-
|
|
652
|
-
// Get last 100 lines of a specific agent's logs
|
|
653
|
-
const result = await getLogs('Worker1', { lines: 100 });
|
|
654
|
-
if (result.found) {
|
|
655
|
-
console.log(result.content);
|
|
656
|
-
}
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
### Connection Management
|
|
660
|
-
|
|
661
|
-
#### State Changes
|
|
662
|
-
|
|
663
|
-
```typescript
|
|
664
|
-
client.onStateChange = (state) => {
|
|
665
|
-
// 'DISCONNECTED' | 'CONNECTING' | 'HANDSHAKING' | 'READY' | 'BACKOFF'
|
|
666
|
-
console.log('State:', state);
|
|
45
|
+
// Listen for idle events
|
|
46
|
+
relay.onAgentIdle = ({ name, idleSecs }) => {
|
|
47
|
+
console.log(`${name} has been idle for ${idleSecs}s`);
|
|
667
48
|
};
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
#### Error Handling
|
|
671
|
-
|
|
672
|
-
```typescript
|
|
673
|
-
client.onError = (error) => {
|
|
674
|
-
console.error('Client error:', error.message);
|
|
675
|
-
};
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
#### Manual Connection Control
|
|
679
|
-
|
|
680
|
-
```typescript
|
|
681
|
-
// Disconnect gracefully
|
|
682
|
-
client.disconnect();
|
|
683
|
-
|
|
684
|
-
// Permanently destroy (prevents reconnection)
|
|
685
|
-
client.destroy();
|
|
686
|
-
|
|
687
|
-
// Check current state
|
|
688
|
-
console.log(client.state); // 'READY', 'DISCONNECTED', etc.
|
|
689
|
-
console.log(client.agentName);
|
|
690
|
-
console.log(client.currentSessionId);
|
|
691
|
-
```
|
|
692
49
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
| Consensus | No | Yes |
|
|
699
|
-
| Cloud sync | No | Yes |
|
|
700
|
-
| Dashboard | No | Yes |
|
|
701
|
-
| Best for | Testing, simple scripts | Production, multi-machine |
|
|
702
|
-
|
|
703
|
-
## Configuration Reference
|
|
704
|
-
|
|
705
|
-
### RelayClient Options
|
|
706
|
-
|
|
707
|
-
```typescript
|
|
708
|
-
const client = new RelayClient({
|
|
709
|
-
// Required
|
|
710
|
-
agentName: 'MyAgent',
|
|
711
|
-
|
|
712
|
-
// Optional
|
|
713
|
-
socketPath: '/tmp/agent-relay.sock', // default
|
|
714
|
-
entityType: 'agent', // 'agent' or 'user'
|
|
715
|
-
cli: 'claude', // CLI identifier
|
|
716
|
-
program: 'my-app', // program identifier
|
|
717
|
-
model: 'claude-3', // model identifier
|
|
718
|
-
task: 'My task', // task description
|
|
719
|
-
workingDirectory: '/path/to/work',
|
|
720
|
-
displayName: 'Alice', // for human users
|
|
721
|
-
avatarUrl: 'https://...',
|
|
722
|
-
quiet: false, // suppress console logs
|
|
723
|
-
reconnect: true, // auto-reconnect
|
|
724
|
-
maxReconnectAttempts: 10,
|
|
725
|
-
reconnectDelayMs: 1000,
|
|
726
|
-
reconnectMaxDelayMs: 30000,
|
|
50
|
+
const agent = await relay.spawnPty({
|
|
51
|
+
name: "Worker1",
|
|
52
|
+
cli: "claude",
|
|
53
|
+
channels: ["general"],
|
|
54
|
+
idleThresholdSecs: 30, // emit agent_idle after 30s of silence (default), 0 to disable
|
|
727
55
|
});
|
|
728
|
-
```
|
|
729
56
|
|
|
730
|
-
|
|
57
|
+
// Wait for the agent to go idle (e.g. after finishing its task)
|
|
58
|
+
const result = await agent.waitForIdle(120_000); // 2 min timeout
|
|
59
|
+
if (result === "idle") {
|
|
60
|
+
console.log("Agent finished work");
|
|
61
|
+
} else if (result === "exited") {
|
|
62
|
+
console.log("Agent exited");
|
|
63
|
+
} else {
|
|
64
|
+
console.log("Timed out waiting for idle");
|
|
65
|
+
}
|
|
731
66
|
|
|
732
|
-
|
|
733
|
-
const relay = await createRelay({
|
|
734
|
-
socketPath: '/tmp/my-relay.sock', // optional
|
|
735
|
-
quiet: true, // suppress logs (default: true)
|
|
736
|
-
});
|
|
67
|
+
await relay.shutdown();
|
|
737
68
|
```
|
|
738
69
|
|
|
739
|
-
##
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
```typescript
|
|
744
|
-
import type {
|
|
745
|
-
// Client
|
|
746
|
-
ClientState,
|
|
747
|
-
ClientConfig,
|
|
748
|
-
SyncOptions,
|
|
749
|
-
RequestOptions,
|
|
750
|
-
RequestResponse,
|
|
751
|
-
|
|
752
|
-
// Messages
|
|
753
|
-
SendPayload,
|
|
754
|
-
SendMeta,
|
|
755
|
-
PayloadKind,
|
|
756
|
-
AckPayload,
|
|
757
|
-
|
|
758
|
-
// Channels
|
|
759
|
-
ChannelMessagePayload,
|
|
760
|
-
MessageAttachment,
|
|
761
|
-
|
|
762
|
-
// Spawning
|
|
763
|
-
SpawnPayload,
|
|
764
|
-
SpawnResult,
|
|
765
|
-
SpawnResultPayload,
|
|
766
|
-
ReleaseResultPayload,
|
|
767
|
-
AgentReadyPayload,
|
|
768
|
-
|
|
769
|
-
// Worker Management
|
|
770
|
-
SendInputPayload,
|
|
771
|
-
SendInputResultPayload,
|
|
772
|
-
ListWorkersPayload,
|
|
773
|
-
ListWorkersResultPayload,
|
|
774
|
-
|
|
775
|
-
// Monitoring
|
|
776
|
-
AgentInfo,
|
|
777
|
-
AgentMetrics,
|
|
778
|
-
HealthResponsePayload,
|
|
779
|
-
MetricsResponsePayload,
|
|
780
|
-
StatusResponsePayload,
|
|
781
|
-
InboxMessage,
|
|
782
|
-
MessagesResponsePayload,
|
|
783
|
-
RemoveAgentResponsePayload,
|
|
784
|
-
|
|
785
|
-
// Consensus
|
|
786
|
-
ConsensusType,
|
|
787
|
-
VoteValue,
|
|
788
|
-
CreateProposalOptions,
|
|
789
|
-
VoteOptions,
|
|
790
|
-
} from '@agent-relay/sdk';
|
|
70
|
+
## Tic-tac-toe demo script
|
|
71
|
+
After build, run:
|
|
72
|
+
```bash
|
|
73
|
+
npm --prefix packages/sdk run example
|
|
791
74
|
```
|
|
792
75
|
|
|
793
|
-
|
|
76
|
+
Optional env:
|
|
77
|
+
- `CODEX_CMD` (default: `codex`)
|
|
78
|
+
- `CODEX_ARGS` (space-separated CLI args)
|
|
79
|
+
- `AGENT_X_NAME` / `AGENT_O_NAME`
|
|
80
|
+
- `RELAY_CHANNEL` (default: `general`)
|
|
81
|
+
- `AGENT_RELAY_BIN` (override bundled binary path)
|
|
794
82
|
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
| `getInbox()` + session resume | **Continuity** - Recover state across disconnections |
|
|
802
|
-
| `createProposal()` / `vote()` | **Consensus** - Group decision-making |
|
|
803
|
-
| `channels` + state payloads | **Shared memory** - Distributed state |
|
|
804
|
-
| `listAgents()` | **Discovery** - Find available workers |
|
|
805
|
-
| `getMetrics()` / `getHealth()` | **Monitoring** - Auto-scaling decisions |
|
|
806
|
-
| `bindAsShadow()` | **Observation** - QA and oversight |
|
|
807
|
-
| `spawn()` / `release()` | **Dynamic teams** - Scale workers on demand |
|
|
808
|
-
| `sendWorkerInput()` | **Interactive control** - Send input to agent PTYs |
|
|
809
|
-
| `listWorkers()` | **Fleet visibility** - Enumerate active workers |
|
|
810
|
-
|
|
811
|
-
### Example: Hierarchical Swarm
|
|
812
|
-
|
|
813
|
-
```typescript
|
|
814
|
-
const lead = new RelayClient({ agentName: 'Lead' });
|
|
815
|
-
await lead.connect();
|
|
816
|
-
|
|
817
|
-
// Spawn specialized workers
|
|
818
|
-
for (const role of ['Frontend', 'Backend', 'Tests']) {
|
|
819
|
-
await lead.spawn({
|
|
820
|
-
name: `${role}Worker`,
|
|
821
|
-
cli: 'claude',
|
|
822
|
-
task: `You are a ${role} specialist. Wait for tasks from Lead.`,
|
|
823
|
-
});
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
// Delegate work
|
|
827
|
-
lead.sendMessage('FrontendWorker', 'Build the login page UI');
|
|
828
|
-
lead.sendMessage('BackendWorker', 'Create the /auth API endpoint');
|
|
829
|
-
lead.sendMessage('TestsWorker', 'Write integration tests for auth');
|
|
830
|
-
|
|
831
|
-
// Collect results
|
|
832
|
-
const results = new Map();
|
|
833
|
-
lead.onMessage = (from, { body }) => {
|
|
834
|
-
results.set(from, body);
|
|
835
|
-
if (results.size === 3) console.log('All workers complete!');
|
|
836
|
-
};
|
|
83
|
+
## Integration test
|
|
84
|
+
```bash
|
|
85
|
+
cargo build
|
|
86
|
+
npm --prefix packages/sdk install
|
|
87
|
+
npm --prefix packages/sdk run build
|
|
88
|
+
AGENT_RELAY_BIN="$(pwd)/target/debug/agent-relay-broker" npm --prefix packages/sdk run test:integration
|
|
837
89
|
```
|
|
838
90
|
|
|
839
|
-
|
|
91
|
+
Integration tests require Relaycast credentials in environment (`RELAY_API_KEY`).
|
|
840
92
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
title: 'API Design Choice',
|
|
845
|
-
description: 'Should we use GraphQL or REST?',
|
|
846
|
-
participants: ['Architect', 'FrontendLead', 'BackendLead'],
|
|
847
|
-
consensusType: 'majority',
|
|
848
|
-
timeoutMs: 300000,
|
|
849
|
-
});
|
|
850
|
-
|
|
851
|
-
// Participants vote
|
|
852
|
-
client.vote({
|
|
853
|
-
proposalId: 'prop_123',
|
|
854
|
-
value: 'approve',
|
|
855
|
-
reason: 'GraphQL fits our needs better',
|
|
856
|
-
});
|
|
93
|
+
## Package tarball
|
|
94
|
+
```bash
|
|
95
|
+
npm --prefix packages/sdk pack
|
|
857
96
|
```
|
|
858
|
-
|
|
859
|
-
### Learn More
|
|
860
|
-
|
|
861
|
-
- **[Swarm Patterns](./examples/SWARM_PATTERNS.md)** - 8 detailed patterns with code
|
|
862
|
-
- **[Swarm Capabilities](./examples/SWARM_CAPABILITIES.md)** - How primitives enable swarm features
|
|
863
|
-
- **[AgentSwarm](https://github.com/AgentWorkforce/agentswarm)** - Production orchestrator built on Agent Relay
|
|
864
|
-
|
|
865
|
-
## License
|
|
866
|
-
|
|
867
|
-
MIT
|
|
97
|
+
The generated tarball includes `dist/` and `bin/agent-relay-broker` (or `bin/agent-relay-broker.exe` on Windows).
|