Chat Add-on
Persistent multi-room messaging inside sapix-agent: strand-backed messages, real-time SSE delivery, and agent-to-human async workflows.
What you'll learn
- ✓SAPIX_CHAT_ENABLED=true — no additional dependencies
- ✓POST /v1/chat/rooms — create a named room with creator_id
- ✓POST /v1/chat/rooms/:id/messages — send a message (written to strand + broadcast)
- ✓GET /v1/chat/rooms/:id/messages?limit=N — retrieve history
- ✓GET /v1/chat/rooms/:id/stream — SSE stream of new messages
- ✓Messages are immutable strand records — no editing or deletion
- ✓No per-room access control — any valid API key can read/write any room
- ✓Broadcast capacity: 1024 in-flight events; strand records all messages
Create a room called ops-alerts. Subscribe to its SSE stream in one terminal. Send a message from another terminal and verify it appears in the stream within 100ms.
## Chat Add-on
The Chat add-on provides persistent, real-time multi-room messaging inside sapix-agent. Messages are strand records — cryptographically signed, append-only, and part of the same tamper-evident chain as all other agent data.
Enable
SAPIX_CHAT_ENABLED=trueNo additional dependencies required.
Create a room
curl -X POST http://localhost:7475/v1/chat/rooms \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "ops-alerts",
"description": "DBA Agent operational alerts",
"creator_id": "dba-agent"
}'Response: { "room_id": "room_a3f9...", "name": "ops-alerts", ... }
Send a message
curl -X POST http://localhost:7475/v1/chat/rooms/room_a3f9.../messages \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"sender_id": "dba-agent",
"content": "Chain integrity verified. No anomalies detected."
}'Get recent messages
curl "http://localhost:7475/v1/chat/rooms/room_a3f9.../messages?limit=50" \
-H "Authorization: Bearer $KEY"Subscribe to live messages (SSE)
`typescript
const evtSource = new EventSource(
"http://localhost:7475/v1/chat/rooms/room_a3f9.../stream",
{ headers: { Authorization: Bearer ${apiKey} } }
);
evtSource.onmessage = (ev) => {
const msg = JSON.parse(ev.data);
console.log([${msg.sender_id}] ${msg.content});
};
`
Full API reference
| Method | Path | Description |
|---|---|---|
| POST | /v1/chat/rooms | Create a room |
| GET | /v1/chat/rooms | List all rooms |
| GET | /v1/chat/rooms/:id | Get room details |
| DELETE | /v1/chat/rooms/:id | Delete room (strand tombstone written) |
| POST | /v1/chat/rooms/:id/members | Add a member |
| DELETE | /v1/chat/rooms/:id/members/:user_id | Remove a member |
| POST | /v1/chat/rooms/:id/messages | Send a message |
| GET | /v1/chat/rooms/:id/messages?limit=N | Get recent messages |
| GET | /v1/chat/rooms/:id/stream | SSE — live messages for this room |
Important constraints
- No message editing or deletion — messages are strand records (immutable). Deleting a room writes a tombstone on the strand.
- No per-room access control — any valid API key can read and write any room.
- SSE only, not WebSocket — compatible with all browsers and reverse proxies without special handling.
- Broadcast capacity — 1 024 in-flight events before the channel drops. The strand records all messages regardless.
---
Use the Chat add-on for agent-to-human communication, real-time ops dashboards, and async approval workflows. See also: Lesson 54 (Mail Add-on).