Pick the right client for the runtime
ApolloMessagingClient
Publishable key. Safe in browsers and mobile webviews — that’s what makes
the key “publishable”. Use it for anything an end user drives.
ApolloManagementClient
Organization API key. Server-side only — backend services, CI, cron.
Never ship this key in client code.
Reuse one client instance
The messaging client caches its access token and refreshes it before expiry. Constructing a new client per request throws that away and forces a token exchange every time:Error handling
All failures throw typed errors.ApolloError and ApolloTimeoutError are
exported at the top level; per-status classes live under the Apollo
namespace (BadRequestError, UnauthorizedError, ForbiddenError,
NotFoundError, ConflictError, UnprocessableEntityError,
InternalServerError, BadGatewayError).
error.body carries the API’s error envelope — branch on the
stable error.code, and log error.request_id for support.
Timeouts and retries
There is no client-wide timeout — set one per call where it matters, and tune retries (default: 2) for the operation’s cost:Filter your thread lists
An emptyfilters object sorts every thread in the organization and can be
slow. Scope by project_id, agent_id, or a created range, and paginate
with the returned cursors:
WebSocket resilience
- Track
seqand resume — keep the highestseqprocessed; on reconnect send{ type: 'resume', resume_after: lastSeq }instead of re-submitting the turn (see WebSocket). - One handler per event —
socket.on()replaces the previous handler for the same event; route inside one handler rather than registering several. - Persist
thread_id— keep it across reconnects (and page reloads, if the conversation should survive them) to stay in the same conversation. - Prefer REST for one-shot turns — if you don’t need live tokens or
bidirectional traffic,
sendMessage/streamMessageare simpler to operate.
Troubleshooting
WebSocket closes immediately with code 1008
WebSocket closes immediately with code 1008
1008 is an authentication failure on the upgrade — the key exchange
failed or the token was rejected. Verify the publishable key; 1011
signals a server-side error instead.streamMessage type error: 'body' is missing
streamMessage type error: 'body' is missing
Unlike
sendMessage, the stream request wraps the payload:
streamMessage({ body: { user_id, text } }) — the top level also accepts
the Last-Event-ID resume header.Thread lists time out
Thread lists time out
Add filters (
project_id, created range) and raise the per-call timeout:
listThreads({ filters }, { timeoutInSeconds: 120 }).Migrating from v2 (ia-controller)
v3 is a full rewrite against the Apollo API; the v2 surface is gone. The
short version: every task_id becomes a thread_id, every
client.controllerApi.X moves onto one of the two new clients, and the
agent is now encoded in your key instead of passed per call.
Migration guide (v2 → v3)
The exact before/after for every call and response — method map, signature
changes, WebSocket rewrite, response shapes, and a step-by-step checklist.