simple_acp 0.0.1
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.
- checksums.yaml +7 -0
- data/.envrc +1 -0
- data/CHANGELOG.md +5 -0
- data/COMMITS.md +196 -0
- data/LICENSE.txt +21 -0
- data/README.md +385 -0
- data/Rakefile +13 -0
- data/docs/api/client-base.md +383 -0
- data/docs/api/index.md +159 -0
- data/docs/api/models.md +286 -0
- data/docs/api/server-base.md +379 -0
- data/docs/api/storage.md +347 -0
- data/docs/assets/images/simple_acp.jpg +0 -0
- data/docs/client/index.md +279 -0
- data/docs/client/sessions.md +324 -0
- data/docs/client/streaming.md +345 -0
- data/docs/client/sync-async.md +308 -0
- data/docs/core-concepts/agents.md +253 -0
- data/docs/core-concepts/events.md +337 -0
- data/docs/core-concepts/index.md +147 -0
- data/docs/core-concepts/messages.md +211 -0
- data/docs/core-concepts/runs.md +278 -0
- data/docs/core-concepts/sessions.md +281 -0
- data/docs/examples.md +659 -0
- data/docs/getting-started/configuration.md +166 -0
- data/docs/getting-started/index.md +62 -0
- data/docs/getting-started/installation.md +95 -0
- data/docs/getting-started/quick-start.md +189 -0
- data/docs/index.md +119 -0
- data/docs/server/creating-agents.md +360 -0
- data/docs/server/http-endpoints.md +411 -0
- data/docs/server/index.md +218 -0
- data/docs/server/multi-turn.md +329 -0
- data/docs/server/streaming.md +315 -0
- data/docs/storage/custom.md +414 -0
- data/docs/storage/index.md +176 -0
- data/docs/storage/memory.md +198 -0
- data/docs/storage/postgresql.md +350 -0
- data/docs/storage/redis.md +287 -0
- data/examples/01_basic/client.rb +88 -0
- data/examples/01_basic/server.rb +100 -0
- data/examples/02_async_execution/client.rb +107 -0
- data/examples/02_async_execution/server.rb +56 -0
- data/examples/03_run_management/client.rb +115 -0
- data/examples/03_run_management/server.rb +84 -0
- data/examples/04_rich_messages/client.rb +160 -0
- data/examples/04_rich_messages/server.rb +180 -0
- data/examples/05_await_resume/client.rb +164 -0
- data/examples/05_await_resume/server.rb +114 -0
- data/examples/06_agent_metadata/client.rb +188 -0
- data/examples/06_agent_metadata/server.rb +192 -0
- data/examples/README.md +252 -0
- data/examples/run_demo.sh +137 -0
- data/lib/simple_acp/client/base.rb +448 -0
- data/lib/simple_acp/client/sse.rb +141 -0
- data/lib/simple_acp/models/agent_manifest.rb +129 -0
- data/lib/simple_acp/models/await.rb +123 -0
- data/lib/simple_acp/models/base.rb +147 -0
- data/lib/simple_acp/models/errors.rb +102 -0
- data/lib/simple_acp/models/events.rb +256 -0
- data/lib/simple_acp/models/message.rb +235 -0
- data/lib/simple_acp/models/message_part.rb +225 -0
- data/lib/simple_acp/models/metadata.rb +161 -0
- data/lib/simple_acp/models/run.rb +298 -0
- data/lib/simple_acp/models/session.rb +137 -0
- data/lib/simple_acp/models/types.rb +210 -0
- data/lib/simple_acp/server/agent.rb +116 -0
- data/lib/simple_acp/server/app.rb +264 -0
- data/lib/simple_acp/server/base.rb +510 -0
- data/lib/simple_acp/server/context.rb +210 -0
- data/lib/simple_acp/server/falcon_runner.rb +61 -0
- data/lib/simple_acp/storage/base.rb +129 -0
- data/lib/simple_acp/storage/memory.rb +108 -0
- data/lib/simple_acp/storage/postgresql.rb +233 -0
- data/lib/simple_acp/storage/redis.rb +178 -0
- data/lib/simple_acp/version.rb +5 -0
- data/lib/simple_acp.rb +91 -0
- data/mkdocs.yml +152 -0
- data/sig/simple_acp.rbs +4 -0
- metadata +418 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# HTTP Endpoints
|
|
2
|
+
|
|
3
|
+
The SimpleAcp server exposes HTTP endpoints for agent discovery, run management, and session handling.
|
|
4
|
+
|
|
5
|
+
## Endpoint Overview
|
|
6
|
+
|
|
7
|
+
| Method | Path | Description |
|
|
8
|
+
|--------|------|-------------|
|
|
9
|
+
| `GET` | `/ping` | Health check |
|
|
10
|
+
| `GET` | `/agents` | List all agents |
|
|
11
|
+
| `GET` | `/agents/:name` | Get agent manifest |
|
|
12
|
+
| `POST` | `/runs` | Create a run |
|
|
13
|
+
| `GET` | `/runs/:id` | Get run status |
|
|
14
|
+
| `POST` | `/runs/:id` | Resume awaited run |
|
|
15
|
+
| `POST` | `/runs/:id/cancel` | Cancel a run |
|
|
16
|
+
| `GET` | `/runs/:id/events` | Get run events |
|
|
17
|
+
| `GET` | `/session/:id` | Get session info |
|
|
18
|
+
|
|
19
|
+
## Health Check
|
|
20
|
+
|
|
21
|
+
### GET /ping
|
|
22
|
+
|
|
23
|
+
Check server health.
|
|
24
|
+
|
|
25
|
+
**Request:**
|
|
26
|
+
```bash
|
|
27
|
+
curl http://localhost:8000/ping
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Response:**
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"status": "ok"
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Agent Discovery
|
|
38
|
+
|
|
39
|
+
### GET /agents
|
|
40
|
+
|
|
41
|
+
List all registered agents.
|
|
42
|
+
|
|
43
|
+
**Request:**
|
|
44
|
+
```bash
|
|
45
|
+
curl http://localhost:8000/agents
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Response:**
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"agents": [
|
|
52
|
+
{
|
|
53
|
+
"name": "echo",
|
|
54
|
+
"description": "Echoes input back",
|
|
55
|
+
"input_content_types": ["text/plain"],
|
|
56
|
+
"output_content_types": ["text/plain"],
|
|
57
|
+
"metadata": {}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "analyzer",
|
|
61
|
+
"description": "Analyzes JSON data",
|
|
62
|
+
"input_content_types": ["application/json"],
|
|
63
|
+
"output_content_types": ["application/json"],
|
|
64
|
+
"metadata": {"version": "1.0"}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### GET /agents/:name
|
|
71
|
+
|
|
72
|
+
Get a specific agent's manifest.
|
|
73
|
+
|
|
74
|
+
**Request:**
|
|
75
|
+
```bash
|
|
76
|
+
curl http://localhost:8000/agents/echo
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Response:**
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"name": "echo",
|
|
83
|
+
"description": "Echoes input back",
|
|
84
|
+
"input_content_types": ["text/plain"],
|
|
85
|
+
"output_content_types": ["text/plain"],
|
|
86
|
+
"metadata": {}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Error (404):**
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"error": {
|
|
94
|
+
"code": "agent_not_found",
|
|
95
|
+
"message": "Agent 'unknown' not found"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Run Management
|
|
101
|
+
|
|
102
|
+
### POST /runs
|
|
103
|
+
|
|
104
|
+
Create and execute a run.
|
|
105
|
+
|
|
106
|
+
**Request (Synchronous):**
|
|
107
|
+
```bash
|
|
108
|
+
curl -X POST http://localhost:8000/runs \
|
|
109
|
+
-H "Content-Type: application/json" \
|
|
110
|
+
-d '{
|
|
111
|
+
"agent_name": "echo",
|
|
112
|
+
"input": [
|
|
113
|
+
{
|
|
114
|
+
"role": "user",
|
|
115
|
+
"parts": [
|
|
116
|
+
{"content_type": "text/plain", "content": "Hello!"}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
**Response:**
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"run_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
127
|
+
"agent_name": "echo",
|
|
128
|
+
"status": "completed",
|
|
129
|
+
"output": [
|
|
130
|
+
{
|
|
131
|
+
"role": "agent",
|
|
132
|
+
"parts": [
|
|
133
|
+
{"content_type": "text/plain", "content": "Echo: Hello!"}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"created_at": "2025-01-21T10:30:00Z",
|
|
138
|
+
"finished_at": "2025-01-21T10:30:01Z"
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Request (Streaming):**
|
|
143
|
+
```bash
|
|
144
|
+
curl -X POST http://localhost:8000/runs \
|
|
145
|
+
-H "Content-Type: application/json" \
|
|
146
|
+
-H "Accept: text/event-stream" \
|
|
147
|
+
-d '{"agent_name": "chat", "input": [...]}'
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Response (SSE Stream):**
|
|
151
|
+
```
|
|
152
|
+
event: run_started
|
|
153
|
+
data: {"run_id":"550e8400-..."}
|
|
154
|
+
|
|
155
|
+
event: message_created
|
|
156
|
+
data: {"message":{"role":"agent","parts":[]}}
|
|
157
|
+
|
|
158
|
+
event: message_part
|
|
159
|
+
data: {"part":{"content_type":"text/plain","content":"Hello"}}
|
|
160
|
+
|
|
161
|
+
event: message_completed
|
|
162
|
+
data: {"message":{"role":"agent","parts":[...]}}
|
|
163
|
+
|
|
164
|
+
event: run_completed
|
|
165
|
+
data: {"run":{...}}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Request with Session:**
|
|
169
|
+
```bash
|
|
170
|
+
curl -X POST http://localhost:8000/runs \
|
|
171
|
+
-H "Content-Type: application/json" \
|
|
172
|
+
-d '{
|
|
173
|
+
"agent_name": "chat",
|
|
174
|
+
"session_id": "conversation-123",
|
|
175
|
+
"input": [...]
|
|
176
|
+
}'
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### GET /runs/:id
|
|
180
|
+
|
|
181
|
+
Get run status.
|
|
182
|
+
|
|
183
|
+
**Request:**
|
|
184
|
+
```bash
|
|
185
|
+
curl http://localhost:8000/runs/550e8400-e29b-41d4-a716-446655440000
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Response:**
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"run_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
192
|
+
"agent_name": "processor",
|
|
193
|
+
"status": "in_progress",
|
|
194
|
+
"output": [],
|
|
195
|
+
"created_at": "2025-01-21T10:30:00Z"
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Status Values:**
|
|
200
|
+
- `created` - Run created, not started
|
|
201
|
+
- `in_progress` - Currently executing
|
|
202
|
+
- `completed` - Finished successfully
|
|
203
|
+
- `failed` - Encountered error
|
|
204
|
+
- `awaiting` - Waiting for input
|
|
205
|
+
- `cancelled` - Cancelled by request
|
|
206
|
+
|
|
207
|
+
### POST /runs/:id
|
|
208
|
+
|
|
209
|
+
Resume an awaited run.
|
|
210
|
+
|
|
211
|
+
**Request:**
|
|
212
|
+
```bash
|
|
213
|
+
curl -X POST http://localhost:8000/runs/550e8400-... \
|
|
214
|
+
-H "Content-Type: application/json" \
|
|
215
|
+
-d '{
|
|
216
|
+
"await_resume": {
|
|
217
|
+
"type": "message",
|
|
218
|
+
"message": {
|
|
219
|
+
"role": "user",
|
|
220
|
+
"parts": [
|
|
221
|
+
{"content_type": "text/plain", "content": "My response"}
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}'
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Response:**
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"run_id": "550e8400-...",
|
|
232
|
+
"status": "completed",
|
|
233
|
+
"output": [...]
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### POST /runs/:id/cancel
|
|
238
|
+
|
|
239
|
+
Cancel a running execution.
|
|
240
|
+
|
|
241
|
+
**Request:**
|
|
242
|
+
```bash
|
|
243
|
+
curl -X POST http://localhost:8000/runs/550e8400-.../cancel
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Response:**
|
|
247
|
+
```json
|
|
248
|
+
{
|
|
249
|
+
"run_id": "550e8400-...",
|
|
250
|
+
"status": "cancelled"
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### GET /runs/:id/events
|
|
255
|
+
|
|
256
|
+
Get events for a run.
|
|
257
|
+
|
|
258
|
+
**Request:**
|
|
259
|
+
```bash
|
|
260
|
+
curl "http://localhost:8000/runs/550e8400-.../events?limit=100&offset=0"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Response:**
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"events": [
|
|
267
|
+
{
|
|
268
|
+
"type": "run_started",
|
|
269
|
+
"run_id": "550e8400-..."
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"type": "message_part",
|
|
273
|
+
"part": {"content_type": "text/plain", "content": "Hello"}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
"type": "run_completed",
|
|
277
|
+
"run": {...}
|
|
278
|
+
}
|
|
279
|
+
]
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Session Management
|
|
284
|
+
|
|
285
|
+
### GET /session/:id
|
|
286
|
+
|
|
287
|
+
Get session information.
|
|
288
|
+
|
|
289
|
+
**Request:**
|
|
290
|
+
```bash
|
|
291
|
+
curl http://localhost:8000/session/conversation-123
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Response:**
|
|
295
|
+
```json
|
|
296
|
+
{
|
|
297
|
+
"id": "conversation-123",
|
|
298
|
+
"history": [
|
|
299
|
+
{"role": "user", "parts": [...]},
|
|
300
|
+
{"role": "agent", "parts": [...]}
|
|
301
|
+
],
|
|
302
|
+
"state": {"step": 2, "data": {"name": "Alice"}}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Error Responses
|
|
307
|
+
|
|
308
|
+
All errors follow a consistent format:
|
|
309
|
+
|
|
310
|
+
```json
|
|
311
|
+
{
|
|
312
|
+
"error": {
|
|
313
|
+
"code": "error_code",
|
|
314
|
+
"message": "Human-readable message"
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Error Codes
|
|
320
|
+
|
|
321
|
+
| Code | HTTP Status | Description |
|
|
322
|
+
|------|-------------|-------------|
|
|
323
|
+
| `agent_not_found` | 404 | Agent doesn't exist |
|
|
324
|
+
| `run_not_found` | 404 | Run doesn't exist |
|
|
325
|
+
| `session_not_found` | 404 | Session doesn't exist |
|
|
326
|
+
| `invalid_input` | 400 | Malformed request |
|
|
327
|
+
| `run_not_awaiting` | 400 | Resume on non-awaiting run |
|
|
328
|
+
| `internal_error` | 500 | Server error |
|
|
329
|
+
|
|
330
|
+
## Request Headers
|
|
331
|
+
|
|
332
|
+
| Header | Purpose |
|
|
333
|
+
|--------|---------|
|
|
334
|
+
| `Content-Type: application/json` | Required for POST requests |
|
|
335
|
+
| `Accept: text/event-stream` | Request SSE streaming |
|
|
336
|
+
|
|
337
|
+
## Query Parameters
|
|
338
|
+
|
|
339
|
+
### /runs/:id/events
|
|
340
|
+
|
|
341
|
+
| Parameter | Type | Default | Description |
|
|
342
|
+
|-----------|------|---------|-------------|
|
|
343
|
+
| `limit` | integer | 100 | Max events to return |
|
|
344
|
+
| `offset` | integer | 0 | Events to skip |
|
|
345
|
+
|
|
346
|
+
## Authentication
|
|
347
|
+
|
|
348
|
+
SimpleAcp doesn't include built-in authentication. Add it via middleware:
|
|
349
|
+
|
|
350
|
+
```ruby
|
|
351
|
+
# config.ru
|
|
352
|
+
require 'simple_acp'
|
|
353
|
+
|
|
354
|
+
server = SimpleAcp::Server::Base.new
|
|
355
|
+
# ... register agents
|
|
356
|
+
|
|
357
|
+
# Add auth middleware
|
|
358
|
+
use Rack::Auth::Basic do |username, password|
|
|
359
|
+
username == ENV['API_USER'] && password == ENV['API_PASS']
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
run server.to_app
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## CORS
|
|
366
|
+
|
|
367
|
+
For browser access, add CORS headers:
|
|
368
|
+
|
|
369
|
+
```ruby
|
|
370
|
+
# config.ru
|
|
371
|
+
require 'rack/cors'
|
|
372
|
+
|
|
373
|
+
use Rack::Cors do
|
|
374
|
+
allow do
|
|
375
|
+
origins '*'
|
|
376
|
+
resource '*',
|
|
377
|
+
headers: :any,
|
|
378
|
+
methods: [:get, :post, :options],
|
|
379
|
+
expose: ['Content-Type']
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
run server.to_app
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Testing Endpoints
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
# Health check
|
|
390
|
+
curl http://localhost:8000/ping | jq
|
|
391
|
+
|
|
392
|
+
# List agents
|
|
393
|
+
curl http://localhost:8000/agents | jq
|
|
394
|
+
|
|
395
|
+
# Run agent
|
|
396
|
+
curl -X POST http://localhost:8000/runs \
|
|
397
|
+
-H "Content-Type: application/json" \
|
|
398
|
+
-d '{"agent_name":"echo","input":[{"role":"user","parts":[{"content_type":"text/plain","content":"test"}]}]}' | jq
|
|
399
|
+
|
|
400
|
+
# Stream run
|
|
401
|
+
curl -X POST http://localhost:8000/runs \
|
|
402
|
+
-H "Content-Type: application/json" \
|
|
403
|
+
-H "Accept: text/event-stream" \
|
|
404
|
+
-d '{"agent_name":"chat","input":[...]}'
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Next Steps
|
|
408
|
+
|
|
409
|
+
- See [Client Guide](../client/index.md) for using these endpoints
|
|
410
|
+
- Review [API Reference](../api/server-base.md) for programmatic usage
|
|
411
|
+
- Explore [Storage](../storage/index.md) for data persistence
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Server Guide
|
|
2
|
+
|
|
3
|
+
The SimpleAcp server hosts agents and handles HTTP requests from clients. This guide covers everything you need to build robust agent servers.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
graph TB
|
|
9
|
+
subgraph Server
|
|
10
|
+
S[Server::Base]
|
|
11
|
+
A[App - Roda]
|
|
12
|
+
AG1[Agent 1]
|
|
13
|
+
AG2[Agent 2]
|
|
14
|
+
ST[(Storage)]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
C1[Client 1] -->|HTTP| A
|
|
18
|
+
C2[Client 2] -->|HTTP| A
|
|
19
|
+
A --> S
|
|
20
|
+
S --> AG1
|
|
21
|
+
S --> AG2
|
|
22
|
+
S --> ST
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
require 'simple_acp'
|
|
29
|
+
|
|
30
|
+
server = SimpleAcp::Server::Base.new
|
|
31
|
+
|
|
32
|
+
server.agent("hello") do |context|
|
|
33
|
+
SimpleAcp::Models::Message.agent("Hello from SimpleAcp!")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
server.run(port: 8000)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## In This Section
|
|
40
|
+
|
|
41
|
+
<div class="grid cards" markdown>
|
|
42
|
+
|
|
43
|
+
- :material-robot:{ .lg .middle } **Creating Agents**
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
Learn patterns for building effective agents
|
|
48
|
+
|
|
49
|
+
[:octicons-arrow-right-24: Creating Agents](creating-agents.md)
|
|
50
|
+
|
|
51
|
+
- :material-play-speed:{ .lg .middle } **Streaming Responses**
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
Implement real-time streaming with SSE
|
|
56
|
+
|
|
57
|
+
[:octicons-arrow-right-24: Streaming](streaming.md)
|
|
58
|
+
|
|
59
|
+
- :material-chat-processing:{ .lg .middle } **Multi-Turn Conversations**
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
Build stateful, context-aware agents
|
|
64
|
+
|
|
65
|
+
[:octicons-arrow-right-24: Multi-Turn](multi-turn.md)
|
|
66
|
+
|
|
67
|
+
- :material-api:{ .lg .middle } **HTTP Endpoints**
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
Reference for all server endpoints
|
|
72
|
+
|
|
73
|
+
[:octicons-arrow-right-24: HTTP Endpoints](http-endpoints.md)
|
|
74
|
+
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
## Server Architecture
|
|
78
|
+
|
|
79
|
+
### Components
|
|
80
|
+
|
|
81
|
+
| Component | Purpose |
|
|
82
|
+
|-----------|---------|
|
|
83
|
+
| `Server::Base` | Core server managing agents and runs |
|
|
84
|
+
| `Server::App` | Roda HTTP application |
|
|
85
|
+
| `Server::Context` | Execution context passed to agents |
|
|
86
|
+
| `Server::Agent` | Agent wrapper with metadata |
|
|
87
|
+
|
|
88
|
+
### Server Lifecycle
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
# 1. Create server with optional storage
|
|
92
|
+
server = SimpleAcp::Server::Base.new(
|
|
93
|
+
storage: SimpleAcp::Storage::Memory.new
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# 2. Register agents
|
|
97
|
+
server.agent("name", description: "...") do |context|
|
|
98
|
+
# Handler logic
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# 3. Start HTTP server (uses Falcon)
|
|
102
|
+
server.run(port: 8000)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Programmatic Usage
|
|
106
|
+
|
|
107
|
+
Use the server without HTTP:
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
# Create runs directly
|
|
111
|
+
run = server.run_sync(
|
|
112
|
+
agent_name: "processor",
|
|
113
|
+
input: [SimpleAcp::Models::Message.user("Data")]
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Stream events
|
|
117
|
+
server.run_stream(agent_name: "streamer", input: messages) do |event|
|
|
118
|
+
# Handle events
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Configuration
|
|
123
|
+
|
|
124
|
+
### Storage
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
# Memory (default)
|
|
128
|
+
server = SimpleAcp::Server::Base.new
|
|
129
|
+
|
|
130
|
+
# Redis
|
|
131
|
+
server = SimpleAcp::Server::Base.new(
|
|
132
|
+
storage: SimpleAcp::Storage::Redis.new(url: ENV['REDIS_URL'])
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# PostgreSQL
|
|
136
|
+
server = SimpleAcp::Server::Base.new(
|
|
137
|
+
storage: SimpleAcp::Storage::PostgreSQL.new(url: ENV['DATABASE_URL'])
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### HTTP Server Options
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
server.run(
|
|
145
|
+
port: 8000,
|
|
146
|
+
host: '0.0.0.0'
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Falcon uses fiber-based concurrency, efficiently handling thousands of concurrent connections without the need for thread pool configuration.
|
|
151
|
+
|
|
152
|
+
## Best Practices
|
|
153
|
+
|
|
154
|
+
### Agent Organization
|
|
155
|
+
|
|
156
|
+
```ruby
|
|
157
|
+
# Group related agents
|
|
158
|
+
class MyServer
|
|
159
|
+
def initialize
|
|
160
|
+
@server = SimpleAcp::Server::Base.new
|
|
161
|
+
register_chat_agents
|
|
162
|
+
register_utility_agents
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
def register_chat_agents
|
|
168
|
+
@server.agent("chat") { |ctx| ... }
|
|
169
|
+
@server.agent("summarize") { |ctx| ... }
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def register_utility_agents
|
|
173
|
+
@server.agent("ping") { |ctx| ... }
|
|
174
|
+
@server.agent("echo") { |ctx| ... }
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Error Handling
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
server.agent("safe") do |context|
|
|
183
|
+
begin
|
|
184
|
+
risky_operation(context.input)
|
|
185
|
+
rescue ValidationError => e
|
|
186
|
+
SimpleAcp::Models::Message.agent("Invalid input: #{e.message}")
|
|
187
|
+
rescue ExternalServiceError => e
|
|
188
|
+
# Log and return friendly error
|
|
189
|
+
logger.error("External service failed: #{e}")
|
|
190
|
+
SimpleAcp::Models::Message.agent("Service temporarily unavailable")
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Logging
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
server.agent("logged") do |context|
|
|
199
|
+
logger.info("Processing request", {
|
|
200
|
+
run_id: context.run_id,
|
|
201
|
+
agent: context.agent_name,
|
|
202
|
+
input_count: context.input.length
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
result = process(context.input)
|
|
206
|
+
|
|
207
|
+
logger.info("Request completed", {
|
|
208
|
+
run_id: context.run_id,
|
|
209
|
+
output_count: result.length
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
result
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Next Steps
|
|
217
|
+
|
|
218
|
+
Start with [Creating Agents](creating-agents.md) to learn agent development patterns.
|