Every timeout in your stack assumes a client that eventually gives up. A browser tab gets closed. A CI job hits its wall clock. A human walks away. The defaults you inherited from your load balancer, your gateway and your HTTP library were tuned for a caller whose patience is measured in seconds.
Anthropic says Claude Opus 5.5 stays on task 18 or more hours.
That is not a claim about one very long HTTP request. It is a claim about coherence: the model works a single objective across a session far longer than anything your API has served. When one of those sessions points at your endpoints, it outlives your access tokens, your idempotency window, your deploy cycle and most of your retry budgets. And unlike a human, it will not notice it should stop.
This is an API design problem, not a model problem. Here is what breaks, and what to change.
What Anthropic actually published
The vendor numbers for the new model, so we are arguing from the same sheet:
| Property | Claude Opus 5.5 |
|---|---|
| API model id | claude-opus-5-5 |
| Input / output | $4 / $20 per million tokens |
| Cached input read | $0.20 per million (cache write $5) |
| Context window | 1M |
| Max output | 128k |
| Fast mode | $8 / $40 per million |
| Cost to run vs Opus 5 | 40% less |
| Output speed vs Opus 5 | 30% faster |
| Sustained on-task duration | 18+ hours |
| Availability | Claude Platform, AWS, GCP, Azure |
Benchmarks from the same announcement: Terminal-Bench 4.0 66.4%, OSWorld 2.0 81.8%, AutomationBench 40.0%, FrontierCode v1.1 54.4%, CursorBench 4.0 57.8%, Humanity’s Last Exam 67.7% with tools, Chartography 89.0%, GDPval-AA v2.1 at 1846 Elo, and 85% fewer successful boundary-circumvention attempts.
The 18-hour figure is the one that lands on your infrastructure. Benchmark scores change which model you pick. Sustained duration changes what your API has to survive.
Six assumptions that stop holding
| Assumption | Why it used to hold | What an 18-hour agent does to it |
|---|---|---|
| A call finishes or fails inside one timeout | Callers were interactive | The work is longer than any idle timeout you can safely set |
| Retrying is cheap because the window is short | Duplicates arrived seconds apart | Duplicates arrive hours apart, after your dedupe window closed |
| The credential at the start is valid at the end | Sessions were shorter than token TTL | Tokens rotate two or three times inside one task |
| A stream is a connection | Streams lasted a response | The connection will drop, and the work has not |
| The client remembers what it was doing | State lived in one process | The agent compacts context, restarts, and needs you to remind it |
| The client can tell it is making progress | A human watched a spinner | Without progress, the agent either restarts the job or waits forever |
Each has a fix that is boring, well understood, and usually skipped because nothing forced the issue. Something is forcing it now.
Return handles, not work
The highest-value change: any operation that can exceed a few seconds returns a job resource immediately instead of holding the connection.
POST /v1/reports HTTP/1.1
Host: api.example.com
Idempotency-Key: 01J9Z4KCQ7M3XN2YB8V6H0
Content-Type: application/json
{"dataset": "orders_2026_q3", "format": "parquet"}
HTTP/1.1 202 Accepted
Location: /v1/jobs/job_01J9Z4KD
Retry-After: 5
Content-Type: application/json
{
"id": "job_01J9Z4KD",
"status": "queued",
"created_at": "2026-09-23T04:12:09Z",
"api_version": "2026-08-01"
}
Then the status resource carries everything the agent needs to decide what to do next:
{
"id": "job_01J9Z4KD",
"status": "running",
"progress": { "completed": 41200, "total": 180000, "unit": "rows" },
"started_at": "2026-09-23T04:12:11Z",
"updated_at": "2026-09-23T05:47:02Z",
"expires_at": "2026-09-24T04:12:09Z",
"retry_after_seconds": 15,
"result_url": null,
"error": null
}
Four fields do the real work. progress with an explicit unit lets the model reason about whether waiting is rational instead of guessing from elapsed time. retry_after_seconds puts polling cadence under server control, which matters when the caller has no instinct for politeness. expires_at tells the agent how long the handle is good for, so it can checkpoint before losing it. api_version pins the job to the contract it was created under, the only thing standing between your 3pm deploy and a run that started at dawn.
Webhooks are the better completion signal when you can offer them, and polling is the fallback when the agent has no callable address. Our walkthrough of polling versus webhooks for long-running agent calls covers the tradeoff. What changes at an 18-hour horizon is that you need both, because a webhook delivered at hour three to an agent that has since compacted its context reaches a caller that no longer remembers asking.
Make idempotency outlive the task
Most idempotency implementations store the key for a day or less, and that was always enough. An agent that retries a failed provisioning call late in a long run lands outside the original dedupe window, at which point your API cheerfully does the work twice.
Three changes cost very little:
- Publish the window. Return the expiry in the response so the caller can reason about it, rather than documenting it once and hoping.
- Say when you replayed. An
Idempotency-Replayed: trueheader turns a silent no-op into something the agent can act on. - Reject mismatches loudly. Same key, different body means the caller has lost track of its own state. Return
409with the original request fingerprint instead of serving a stale result.
HTTP/1.1 200 OK
Idempotency-Replayed: true
Idempotency-Expires: 2026-09-24T04:12:09Z
Where the operation is genuinely dangerous, prefer a client-supplied natural key over an opaque one. A transfer_id derived from the business fact survives an agent’s memory compaction in a way a random UUID it generated eleven hours ago does not. Our primer on agent idempotency has the failure modes.
Assume the credential expires mid-task
An 18-hour run outlives almost every short-lived access token. That is the correct security posture, but only if your API makes the distinction legible.
Return 401 with a WWW-Authenticate: Bearer error="invalid_token" challenge when the token has expired, and reserve 403 for a principal that lacks permission. Agents treat these very differently: one means refresh and continue, the other means stop and report. Collapsing them into a generic failure is how you get an agent that burns four hours retrying something it will never be allowed to do.
Bind jobs to the principal, not to the token instance. A job started under a token that has since rotated must remain readable by the same identity, or every credential refresh orphans work in flight.
Treat a stream as resumable, not as a connection
Long streams drop. Assume it, and design the reconnect rather than the connection.
For server-sent events that means giving every event a monotonic id, honouring the Last-Event-ID request header on reconnect, and emitting a keepalive comment on an interval shorter than the tightest idle timeout between you and the client. Name the config keys in your own docs, because the reader has to go change them: idle_timeout.timeout_seconds on an AWS load balancer, proxy_read_timeout in nginx, timeout on a Cloud Run service. The point is not a specific value. It is that the value exists, is shorter than the work, and nobody has looked at it since the service was created. Our SSE streaming guide covers the wire format; the agent-specific part is resumption.
Rate limit headers matter more than usual too. RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset let a model pace itself across a long run, and a Retry-After on every 429 removes the guesswork. An agent given a number respects it. An agent given nothing invents a backoff, and its invention will not be better than yours.
The cost side is a design decision
Look again at the pricing row. Input costs $4 per million tokens and a cached read costs $0.20, a twentyfold difference on the part of the payload an agent resends most often, and on a 1M context window the absolute numbers get large fast. Cache writes at $5 mean the first pass costs slightly more than a plain read, so caching pays only when the prefix is genuinely reused. Over eighteen hours, it is.
This is where your API surface becomes a cost input on someone else’s bill. If your OpenAPI spec, your tool definitions or your error catalogue sit at the front of an agent’s context, byte stability is a feature. Serialize deterministically. Keep key ordering stable. Version tool definitions instead of editing them in place. A cosmetic reordering of your spec invalidates a cached prefix and re-bills the whole thing at full input price, and the customer paying for that will never know it was you.
The scale is not hypothetical. OpenAI disclosed that its median researcher spends over $600 per day on coding agents, with the 90th percentile above $7,000 per day. That is what continuous agentic work costs when nobody optimizes for it, and part of why three model launches in two days all led with cost per task rather than cost per token. The arithmetic of when caching pays back is in our Opus 5.5 caching cost breakdown.
Test the long path before an agent finds it
None of this is verifiable by clicking send once and reading a 200. The failures live in hour nine.
In Apidog, model the whole lifecycle as a test scenario rather than a single request: assert that the create call returns 202 with a Location and a Retry-After, loop the status endpoint until a terminal state, and assert that progress.completed never moves backwards. That last assertion catches more real bugs than any status code check, because non-monotonic progress is what convinces an agent to start over.
Then break it deliberately with a mock server. Serve a job that stays running for twenty polls and then fails. Serve a 429 with no Retry-After and watch what your client does. Serve a 401 halfway through to confirm the refresh path works while a job is in flight. Apidog’s SSE testing holds a streaming connection open and asserts on individual events, the only practical way to check that Last-Event-ID resumption returns the right cursor instead of replaying from zero. Wire the scenario into CI so a future timeout change fails a test instead of a customer’s overnight run. Apidog is free to start, and the scenario you build once covers every long-running endpoint you own.
The short checklist
- Long operations return
202with a job handle, never a held connection - Status responses carry progress, a unit, a server-chosen poll interval and an expiry
- Jobs pin the API version they were created with
- Idempotency windows are published, replays are labelled, key reuse with a changed body returns
409 401for expired tokens is distinguishable from403for denied ones- Jobs belong to a principal, not a token instance
- Streams carry event ids, honour
Last-Event-ID, and send keepalives inside the shortest idle timeout on the path - Every
429carriesRetry-After, and rate limit headers are always present - Spec and tool definitions serialize byte-stable so client-side caches stay warm
Opus 5.5 did not invent any of these requirements. It removed the last excuse for skipping them, because the client that used to give up before finding the cracks now works straight through them for eighteen hours.



