Polling Transport

Use polling instead of SSE for environments that can't maintain long-lived HTTP connections.


When to Use Polling

Some environments cannot hold open Server-Sent Events (SSE) connections:

  • Convex actions — HTTP requests must complete within a timeout
  • Cloudflare Workers — no long-lived inbound connections
  • Restricted edge runtimes — firewalls or proxies that drop idle connections
  • Serverless functions — Lambda, Cloud Functions with short timeouts

In these cases, set stream: false to switch from SSE to lightweight polling. The SDK automatically polls a status endpoint and only fetches full data when the status changes.


Client-Level Default

Set polling as the default transport for all operations:

typescript
1import { inference } from '@inferencesh/sdk';23const client = inference({4  apiKey: 'inf_your_key',5  stream: false,          // Use polling instead of SSE6  pollIntervalMs: 2000,   // Poll every 2 seconds (default)7});

All client.run(), agent.sendMessage(), and AgentChatProvider calls will use polling unless overridden.


Task Polling

Override the transport per-call with stream: false on run():

typescript
1const result = await client.run(2  { app: 'infsh/flux', input: { prompt: 'A sunset' } },3  {4    stream: false,5    pollIntervalMs: 3000,  // Optional: override interval6    onUpdate: (task) => {7      console.log('Status:', task.status);8    },9  }10);1112console.log('Output:', result.output);

How it works:

  1. Task is created via POST /apps/run (same as streaming)
  2. SDK polls GET /tasks/{id}/status every pollIntervalMs
  3. When the status changes, it fetches the full task via GET /tasks/{id}
  4. onUpdate fires with the full task data
  5. Promise resolves on completion, rejects on failure or cancellation (the error message comes from the task's error field when present)

When status polling cannot recover (for example repeated network errors), set maxReconnects on run() options (default 5) to control retry behavior.


Agent Polling

Imperative SDK

typescript
1const client = inference({ apiKey: 'inf_your_key' });23const agent = client.agent('my-team/support-agent@latest');45const response = await agent.sendMessage('Hello!', {6  stream: false,7  pollIntervalMs: 2000,8  onMessage: (message) => {9    console.log('Message:', message.content);10  },11  onChat: (chat) => {12    console.log('Chat status:', chat.status);13  },14  onToolCall: (invocation) => {15    console.log('Tool call:', invocation.name);16  },17});

How it works:

  1. Message is sent via POST /agents/run (same as streaming)
  2. SDK polls GET /chats/{id}/status every pollIntervalMs
  3. When the status changes, it fetches the full chat via GET /chats/{id}
  4. New and updated messages are dispatched to onMessage
  5. Client tool invocations (in_progress, or awaiting_input for backwards compatibility) are dispatched to onToolCall
  6. Promise resolves when the chat becomes idle

Transient status poll failures (for example a single network error on GET /chats/{id}/status) log a [Agent] Poll error: warning and polling continues — sendMessage does not reject until the chat reaches a terminal state or the initial send fails. Use onError on AgentChatProvider to surface persistent transport failures to your UI.

React Provider

tsx
1import { AgentChatProvider, useAgentChat } from '@inferencesh/sdk/agent';23function App() {4  return (5    <AgentChatProvider6      client={client}7      agentConfig={{ agent: 'my-team/support-agent@latest' }}8      stream={false}9      pollIntervalMs={2000}10    >11      <ChatUI />12    </AgentChatProvider>13  );14}

The provider uses the same polling mechanism internally. All hooks (useAgentChat, useAgentActions) work identically regardless of transport.

Optional lifecycle callbacks (available on AgentChatProvider with both SSE and polling):

PropWhen it fires
onChatCreatedA new chat ID is assigned after the first message
onStatusChangeConnection status changes (connecting, streaming, idle)
onTurnEndThe agent's turn ends — chat status transitions from busy to idle, completed, or another non-busy state. Receives the full ChatDTO. Use to refetch host data after agent tool actions without polling or window-focus workarounds.
onErrorStream or poll transport errors, failed sends, or tool submission failures
tsx
1<AgentChatProvider2  client={client}3  agentConfig={{ agent: 'my-team/support-agent@latest' }}4  stream={false}5  onError={(error) => console.error('Agent error:', error)}6  onStatusChange={(status) => console.log('Status:', status)}7  onTurnEnd={(chat) => refetchDashboard(chat.id)}8>9  <ChatUI />10</AgentChatProvider>

onError on the provider is separate from the client-level onError in inference({ onError }), which handles REST and initial SSE handshake failures.


Configuration Reference

OptionTypeDefaultScope
streambooleantrueClient, run(), sendMessage(), Provider
pollIntervalMsnumber2000Client, run(), sendMessage(), Provider
maxReconnectsnumber5run() when stream: false

Precedence: Per-call options override provider props, which override client defaults.


Comparison: Streaming vs Polling

SSE (default)Polling
LatencyReal-timeUp to pollIntervalMs delay
Partial updatesYes (onPartialUpdate)No (full fetch only)
ConnectionLong-lived HTTPShort-lived requests
Edge compatibleNoYes
BandwidthLower (deltas only)Higher (status checks + full fetches)

Use SSE when you can. Use polling when you must.

we use cookies

we use cookies to ensure you get the best experience on our website. for more information on how we use cookies, please see our cookie policy.

by clicking "accept", you agree to our use of cookies.
learn more.