Skip to content Documentation index for agents (llms.txt)
Glotto Beta
Get started

Polling

For long-running, asynchronous operations — a job you kick off and then wait on — the SDKs give you two complementary surfaces: a generated poll<Method>() companion beside each operation your spec marks pollable, and a generic waiter for any custom predicate.

import { Client } from 'glotto-sdk';

const client = new Client({ token: '<token>' });
const result = await client.pets.pollGetPet('string');

regenerated + byte-diffed in CI a0f8af4b462c

The generated poll<Method>() companion

When the spec marks an operation as pollable, the engine emits a companion beside it that re-fetches on an interval until the resource reaches its terminal state, then returns the typed result. It honors a deadline and (where idiomatic) an AbortSignal / context so a poll loop never runs unbounded.

Because the companion owns the fetch, it sees the HTTP response — so it also honors the server’s Retry-After cadence hint between attempts, clamped to your maxDelayMs so a large hint can never stall a wait past the budget you set. That is the one thing the generic waiter below cannot do: you hand it a predicate over an already-decoded value, so the headers are gone by the time it runs. If your API advertises a poll cadence, the companion is the surface that follows it.

The companion is named for the method it waits on, spelled the way that language spells names — a method key get emits pollGet in TypeScript, React Native, Swift and Dart; PollGet in Go and C#, whose methods are exported or PascalCased; poll_get in Python, Ruby, Rust, PHP and Elixir; and get_job likewise emits pollGetJob / PollGetJob / poll_get_job. It is never a bare poll(). Its return follows the language’s own convention too: TypeScript resolves the typed result and throws on timeout, while Elixir returns {:ok, result} / {:error, :timeout} like every other call in that SDK. It ships in every SDK we generate — the generic waiter below remains available for any predicate the spec does not model.

A few per-language shapes worth knowing:

  • Swiftasync throws, taking a trailing poll: WaitForOptions = WaitForOptions() after the usual request options, and waiting with Task.sleep, so cancelling the surrounding task cancels the wait (there is no AbortSignal to pass).
  • Java — an overload pair beside the operation: client.jobs().pollGet(id) for the defaults, or pollGet(id, intervalMs, maxAttempts, timeoutMs, maxDelayMs) to set the budget — plus a pollGetAsync twin returning a CompletableFuture, matching the async twin every other Java method carries.

The generic waiter

For anything the spec doesn’t model, every SDK also exports a generic waiter — waitFor(predicate, options) (TypeScript), wait_until(fetch, predicate, …) / await_until (Python), WaitUntil(ctx, fetch, predicate, …opts) (Go), and the equivalent elsewhere. You supply the predicate; it polls with the configured intervalMs, timeoutMs, and maxAttempts, returning when the predicate is satisfied and raising a typed timeout error (PollingTimeoutError) when it isn’t.

Tuning

Both surfaces take the same knobs — poll interval, overall timeout, and max attempts — so you can bound how long a wait runs. Exceeding the timeout or attempt cap raises a typed error rather than hanging. In Go the overall budget is your context.WithTimeout rather than a timeoutMs option; in the C#, Java, Kotlin, PHP, and Ruby SDKs timeoutMs is opt-in — passing it adds a wall-clock deadline on top of the attempt cap, and leaving it off keeps the wait attempt-bounded.

Backing off between polls

By default the wait polls on a fixed interval. Set maxDelayMs (max_delay_ms in the snake_case SDKs, WithPollMaxDelay in Go) to switch to capped exponential backoff: the delay starts at intervalMs and doubles each attempt up to the cap — min(maxDelayMs, intervalMs * 2^(attempt-1)). The schedule is deterministic (no jitter), so a wait is reproducible run-to-run. Python and Go poll with this backoff curve out of the box; for the generic waiter everywhere else it turns on when you pass the cap. The companion always has a cap — it defaults maxDelayMs to 30 seconds even where the generic waiter leaves it off — because the cap is also what bounds a Retry-After hint, so there is always something for a large hint to be clamped against.