Skip to content

Limits

Everything on this page is a limit the server actually enforces. Where a limit you might expect does not exist, this page says so rather than guessing, because a plausible invented number is worse than an honest gap.

Requests are metered with a token bucket per durable authority, not per IP, per key, or per connection. Rotating a credential does not get you a fresh bucket.

Bucket Partition Burst Sustained per minute
Authenticated /v1 Your installation (or membership) within one organization 120 600
Pre-authentication edge Client IP 600 3000
Token issuance Client IP 60 60

Those are the shipped defaults, and an operator can tune every one of them. Do not hardcode them. Every authenticated response tells you where you stand:

RateLimit-Policy: "wamp-cloud";q=600;w=60;wamp-burst=120
RateLimit: "wamp-cloud";r=117;t=59

q is the sustained quota, w the window in seconds, wamp-burst the bucket capacity, r your remaining tokens, t seconds until refill. One request costs one token regardless of what it does.

When the bucket is empty you get 429 with Retry-After, Cache-Control: no-store, and retryAfterSeconds in the body. If the limiter itself faults, the API fails closed with 503 cloud_rate_limit_unavailable and Retry-After: 1 rather than becoming unmetered.

The two discovery endpoints — GET /v1/openapi.json and GET /v1/docs — are unauthenticated and are not metered by either bucket.

This is operational flow control, not a commercial entitlement or an SLA.

Quota Limit Enforcement
Active (non-archived) sessions per organization 100 Counted at session creation; 429 cloud_session_limit_reached
Webhook endpoints per app installation 5 Checked at registration; 409 endpoint_limit_reached
Event families per webhook endpoint 1–4 Request validation; 400 invalid_event_families

The session quota counts every session that has not been archived, whatever its state. Archiving is a soft delete (DELETE /v1/sessions/{sessionId}204), and it is how you free quota. Discovery reports the current value as capabilities.limits.maxActiveSessions, so read it rather than assuming 100.

There is no quota on turns per session, on runs over time, on artifacts per session, or on events per session.

Input Limit On violation
Any JSON request body 1 MB 413 (with a non-standard body shape — see Errors)
task on session creation 100 000 characters 400 invalid_request
message on a turn 100 000 characters 400 invalid_request
title on a session 160 characters 400 invalid_request
model 128 characters 400 invalid_request
runtime 64 characters, ^[a-z0-9][a-z0-9-]*$ 400 invalid_request
Publication title 256 characters, no CR or LF 400 invalid_request
Publication body 65 536 characters 400 invalid_request
Merge commitTitle 256 characters, no CR or LF 400 invalid_request
Merge commitMessage 65 536 characters 400 invalid_request
Any HTTPS URL in a request 2048 characters 400 invalid_request
origin.tenantKey 128 characters 400 invalid_request
origin.objectType 64 characters 400 invalid_request
origin.objectId 256 characters 400 invalid_request
origin.endUserId 128 characters 400 invalid_request
origin.label 256 characters 400 invalid_request
replyTo.interactionId 255 characters 400 invalid_request
Opaque paging cursor 1024 characters 400 invalid_request

Two limits interact and both apply: a task of 100 000 characters is legal by character count, but if it is heavily multibyte or heavily escaped the encoded JSON can still exceed the 1 MB body cap and fail with 413 before validation ever runs. capabilities.limits.maxMessageCharacters reports the character cap.

Endpoint limit range Default
GET /v1/sessions 1–100 50
GET …/publications 1–100 50
GET …/events 1–100 100
GET …/turns 1–100 100
GET …/artifacts 1–100 100

limit=0, limit=101 and a non-numeric limit are each 400 invalid_request, not clamped. GET …/interactions is not paged and returns the whole open set. Discovery reports the ceiling as capabilities.limits.maxPageSize.

These are enforced when the server retains an artifact, so exceeding them does not fail your API call — it means the artifact is not kept, and you receive a wamp.artifact.omitted event instead.

Artifact Limit
Presented file, each 32 MiB (33 554 432 bytes)
Presented files, total per run 64 MiB (67 108 864 bytes)
Presented files, count per run 24
Run summary (result.summary) 100 000 bytes
Conversation checkpoint 16 MiB, with a 16 KiB manifest
Workspace checkpoint 256 MiB (268 435 456 bytes), with a 64 KiB manifest

The two checkpoint figures are reported by discovery as capabilities.artifacts.conversationCheckpointMaxBytes and capabilities.artifacts.workspaceCheckpointMaxBytes; the workspace figure also appears as capabilities.environments[0].workspace.maxCheckpointBytes. The presented-file caps are not advertised anywhere in the API, which is why they are worth reading here: a run that writes a 40 MiB build output produces an omission event rather than an artifact, and nothing about the API call tells you that in advance.

A workspace checkpoint over its cap is the difference between a session that can continue after its sandbox ends and one that cannot — see continuation on the session resource.

Limit Value
Maximum lifetime of one sandbox lease 3600 seconds (1 hour)
Extension beyond that ceiling Not possible

One hour is a hard constant, not a configurable policy and not something a caller can raise — a keepalive can push a lease’s deadline forward only up to the ceiling measured from when the lease started. A session that outlives it rolls onto a new lease rather than extending the old one.

You observe this through the session’s workspace object, which has exactly three states:

workspace.state Meaning
unavailable No sandbox is attached
attached A sandbox is attached; expiresAt is its deadline
expired The lease deadline has passed

An expired workspace does not destroy the session. Read continuation to find out whether another turn can resume the work, and at what fidelity.

There is no configurable per-run wall-clock limit, no per-turn timeout, and no idle timeout you can set. An agent that stops on a budget reports it as stopReason on the terminal run event (time_budget, cost_budget, turn_budget, max_turns).

These are enforced by database constraints, which means they hold under concurrent requests from any number of your processes — not just per process.

Ceiling Value Result of exceeding
Non-terminal runs per session 1 409 cloud_run_in_progress
Non-terminal publications per session 1 409 cloud_publication_in_progress
Active merges per publication 1 409
Successful merges per publication, ever 1 409
Turns resolving one interaction 1 409 cloud_interaction_conflict

The first is the one that shapes your architecture: one run at a time per session means one session per concurrent task. Do not multiplex unrelated work into a single session to save quota — with a 100-session cap per organization, that cap is also your concurrency ceiling, and the honest way to raise throughput is to finish and archive sessions.

There is no documented cap on concurrent sessions executing at once beyond the 100 active-session quota, and no per-organization sandbox count you can query.

Command Attempts Backoff
Run dispatch to a sandbox 10, then the run fails with dispatch_attempts_exhausted 2 s doubling, capped at 5 minutes
Webhook delivery 6, then permanently failed 1, 2, 4, 8, 16, 32 minutes (capped at 6 hours)
Publication Not capped Server-managed
Merge (mode: when_ready) Not capped Re-attempted about every 30 seconds while the pull request stays open and unchanged

A run exposes attempts so you can see retries happening without doing anything. Publications and merges expose attempts too, and because neither is capped, your side owns the timeout for a when_ready merge. Decide how long you are willing to wait and stop polling when it elapses; the server will keep waiting indefinitely.

Webhook deliveries time out after 10 seconds measured on your response, which is why a receiver should acknowledge before doing work.

Credential Lifetime
App assertion (the JWT you sign) Up to 600 seconds. A longer one is rejected
Installation access token 600 seconds
Clock skew tolerated on an assertion 30 seconds
Webhook signature replay window 300 seconds

Cache an installation token for its lifetime minus a margin — a minute is comfortable — and re-mint on 401. Do not mint one per request.

GET /v1/sessions/{sessionId}/repository/review is bounded, and it tells you when it hit a bound rather than silently shortening the diff.

Budget Value
Files in one review 500
Total path bytes 128 KiB
Total patch bytes 1 MiB

When the patch budget is exhausted, patchTruncated is true and individual files lose their patch field; the file list stays complete. Exceeding the file budget is 413 review_too_large.

Budget Value
Transcript facts captured per run 10 000
wamp.message.created text 16 384 characters
Activity or runtime name 128 characters

Beyond the fact budget you receive one wamp.timeline.truncated event carrying the count that was dropped. Text over its cap arrives with truncated: true.

This is where the honest answer is “not documented”:

Data What is verifiable
Sessions Archiving is a soft delete. Nothing in the API purges an archived session, and no retention window is published
Events There is no retention field on an event and no documented expiry. A cursor therefore stays valid across long outages, but no guaranteed window is published
Artifact bytes Bytes can be reclaimed. The manifest survives, state becomes pruned, and the content endpoint answers 410 cloud_artifact_pruned. The window before that happens is not documented
Conversation and workspace checkpoints Can be reclaimed, which is reflected in the session’s continuation
Webhook deliveries Permanently failed after 6 attempts

Do not design around any particular retention duration, in either direction. The two robust patterns:

  • If you need artifact bytes durably, copy them. Fetch the content while state is available and store it yourself; verify with the manifest’s sha256.
  • If you need transcripts durably, page events into your own store. Treat the API’s log as a repair channel for recent state, not as your archive.

Conversely, do not assume anything is deleted on a schedule either. If you have a data-retention obligation, archive the session and confirm the deployment’s actual policy with your operator — it is an operational property, not an API guarantee.