Polling and recovery
Keep one durable operation through retries, process restarts, and long-running work.
A reliable integration treats submission and observation as separate activities. Submission establishes the job. Observation reads the same job until its outcome is known. A browser refresh or an impatient caller should not create a second model operation.
Store the intent before sending
Create an application operation record with an idempotency key, subject, kind, and the exact payload or a secure reference to it. Persist it before making the POST. When admission returns, add the job ID and status URL to that same record.
Application intent
operation_key stable before first POST
payload_ref authorized storage for the original input
job_id saved as soon as admission returns
last_status most recent observation
next_check_at when the application should read againThis record is your recovery boundary. Keep private source content in appropriate storage rather than copying it into an ordinary task log. Idempotency keys should also be opaque, not encoded user messages.
Observe with bounded backoff
Read the job immediately after admission, then increase the delay between reads. One second growing to 15 seconds is suitable for the current asynchronous workflow. Add jitter if many application workers might poll together. Use a maximum observation window so a request handler is not held open indefinitely.
If your hosting environment has short request deadlines, return the application operation ID to the caller and schedule later reads in your own durable worker. There is no requirement to keep the original HTTP connection open, and no public callback registration exists yet.
Decide from the full state
When billing.settled is true, inspect the terminal status and result. succeeded is an inference result. ready is a validated candidate and still needs an activation check. failed and rejected are known completed outcomes, not exceptions that automatically justify resubmission.
When reconciliation_required appears, stop the automatic paid workflow and preserve the job. You may continue occasional read-only observation, but do not release your own notion of the operation and start another one as a substitute.
Recover each interruption
| Interruption | Recovery |
|---|---|
| POST timed out before receipt | Repeat the original key and body to recover admission |
| Polling GET failed | Back off and read the same job |
| SDK polling deadline elapsed | Save the ID and resume observation later |
| User closed the browser | Resume from your server's operation record |
| Application worker restarted | Load the saved intent and receipt |
| Candidate activation conflicted | Read the subject and make an explicit release decision |
| Provider outcome is ambiguous | Keep the reservation and request reconciliation |
Cancellation and user-facing status
The API has no cancellation endpoint. An AbortSignal only stops the client from waiting. If a user dismisses a loading panel, label that action as closing or stopping observation rather than cancelling the model job.
Expose useful distinctions in your own UI: queued, running, completed, learning ready but not active, and needs investigation. Show a recoverable operation ID so a user can return later. Avoid a generic timeout message that encourages them to click a button that starts the same paid work again.
Retry ceilings
Bound transport retries by both count and elapsed time. After persistent failures, retain the intent and mark it for later inspection. Do not change payloads in-place under an existing key; corrections are deliberate new operations with new identities.
For manual adapter activation, use read-after-write recovery instead of the model-job idempotency pattern. Read Activate an adapter for that distinct contract.