All communication over the WebSocket uses JSON events with a common structure.
Sending events (client → server)
When sending events, include only type and payload. The server assigns id, sequence, and timestamp — do not include them.
You can optionally include a metadata field with custom key-value pairs. The server echoes these back, useful for correlating sent messages with their echoes:
Receiving events (server → client)
Events from the server include additional fields:
Echo behavior
When you send certain events, the server echoes them back with the server-assigned id, sequence, and timestamp added. This confirms the server received and processed your event. The following events are echoed:
EVENT_TYPE_USER_MESSAGE — the echo includes a server-assigned message_id in the payload
EVENT_TYPE_USER_END_SESSION
EVENT_TYPE_HEARTBEAT
EVENT_TYPE_REQUEST_POLY_AGENT_JOIN
Since your client receives both its own echoed events and server-originated events on the same WebSocket, use the id field to deduplicate.
Using echoes as delivery receipts
Echoes act as server-side acknowledgements — when you receive the echo of a message you sent, the server has received and processed it. Use this to build delivery confirmation and retry logic.
Add a unique client_event_id to metadata.custom when sending. The server echoes this value back, letting you match the echo to the original message:
This pattern gives you optimistic delivery tracking (show “sending…” → “sent” → “failed”) without additional server-side support. Last modified on May 18, 2026