codai docs
Resolve

Pricing and limits

Flat quotes of $7, $19 or $49 billed only on a verified fix; three free fixes; how a charge reaches your Stripe invoice; per-user caps and timeouts.

Resolve prices the outcome, not the tokens. Triage quotes one of three flat tiers; you pay that amount if — and only if — the job ends resolved with an attestation. Declines, failures and infrastructure errors are always $0.

Tiers

TierPriceTypical shape
t7$7Small, well-scoped bug: single file, clear repro.
t19$19Moderate: multi-file, needs investigation.
t49$49Hard but plausible: subtle, cross-cutting.
free$0Your first 3 verified fixes, whatever their difficulty.

Every money field on the wire is an integer of USD micros — quote_micro_usd: 19000000 is $19.00. There is no conversion anywhere in the pipeline.

Prices are in USD because that is the currency of the underlying model spend. Your Stripe invoice is issued in your account's billing currency; Stripe converts at invoice time.

The free tier

3 verified fixes per user, across all your keys. It is claimed atomically when a quotable job arrives: the job is created already accepted with tier: "free" and quote_micro_usd: 0, and free_tier_remaining tells you what is left afterwards. A free job that ends failed or error returns its slot. Once the three are used, quotable jobs come back as quoted and wait for your accept.

Free jobs run a single fix candidate (greedy); paid jobs may fan out up to four — see How it works.

How a charge reaches your invoice

Attestation first

When a job resolves, the worker writes the attestation row and then a resolve_charges row for the quoted amount, status due. The order is enforced in code: no attestation, no charge row. Free jobs get a $0 row with source free_tier for bookkeeping.

Hourly settlement

A scheduled job (resolve-settle, every hour at :15) drains due charges and reports each one to Stripe as a meter event with identifier resolve_<chargeId>. That identifier makes the report idempotent — Stripe ignores a duplicate — and the row flips to settled only after Stripe acknowledged it.

Your Stripe invoice

Meter events land on your Stripe customer under the verified-success meter and appear on the next invoice for your plan. If your account has no Stripe customer yet (you have never subscribed or added a payment method), the charge stays due and is retried on the next run — it does not disappear, and it is not billed to anyone else.

You can see the upstream model cost per job (not what you pay — what Resolve spent) as cost_micro_usd on GET /v1/resolve/jobs/{id}; it is the sum of gateway usage under the job's session ids.

Limits

All limits are per user, counted across every key you own.

LimitValueWhat you see when you hit it
Submissions6 per minute429 rate limited: too many resolve submissions, retry in a minute
Jobs in flight (accepted / running)2429 too many resolve jobs in flight, wait for one to finish
Jobs per day10429 daily resolve job cap reached, retry tomorrow
Free verified fixes3, lifetimeQuotes come back quoted instead of accepted
Issue text50 000 characters (the Action truncates)—

Caps are checked before triage, so a rejected submission costs neither a slot nor a triage call.

Timeouts

BudgetValueEffect
Whole job30 minutesPast it the job ends failed (no verified fix within budget) — $0.
One sandbox run (setup + tests)15 minutesA slow suite ends the candidate; the job may try the next one.
Agent turns per candidate4Edits beyond that are not attempted.
Fix candidates1 (free) / 4 (paid)First verified pass wins; the rest are skipped.
Orphan watchdogjob budget + 15 minutesA job whose worker died is marked error (watchdog: worker lost — not billed, safe to resubmit) and a free slot is returned.
GitHub Action polling25 minutesThe Action stops waiting and comments the last status; the job itself continues to its own budget.

Triage runs inline in your POST and is bounded by the gateway's request timeout; a slow triage returns declined with triage unavailable, please retry rather than hanging.

Supported repositories

  • Public https://github.com/<owner>/<repo> only. Private repos, other hosts and monorepo sub-paths are rejected at submission with a 400.
  • Python with pytest, or JavaScript/TypeScript with vitest, jest or node:test (detected from package.json).
  • The repo's suite must run from a clean clone plus its committed dependency manifest. Tests that need secrets, running services or system packages beyond the runner image usually end in declined or error.

On this page