Skip to content

v0.3.0 — Quota-aware failover & hang fixes

Choose a tag to compare

@sshahzaiib sshahzaiib released this 12 Jun 21:18
· 22 commits to main since this release

Fixes the indefinite-hang failure mode and adds dynamic, quota-aware model routing so delegations keep flowing when a model's quota runs out.

The bug

agy's print mode swallows RESOURCE_EXHAUSTED (code 429) errors — it silently retries every ~2s until --print-timeout, then exits 0 with empty output. With the old 1200s default timeout, a quota-hit delegation looked like a 20-minute hang that returned nothing, blocking the MCP client the whole time.

Added

  • Quota-aware failover — each run writes its own log (--log-file); the bridge polls it and reacts to a 429 within ~1 second: kills the run, parses the reset time (Resets in 4h24m), and retries the same prompt on the next model in the tool's chain
  • Cooldown registry — exhausted models are skipped on all subsequent calls until their quota resets, so routing is proactively quota-aware after the first 429
  • Per-tool timeouts — web_lookup 120s, deep_search 180s, analyze_files / adversarial_review / follow_up 300s, delegate 600s; setting AGY_TIMEOUT explicitly overrides all of them
  • MCP cancellation — aborting the tool call (e.g. Esc in Claude Code) now kills the agy process instead of orphaning it
  • Failover annotations — the response footer reports what happened: failover: Gemini 3.5 Flash (Medium): quota exhausted (resets in 4h24m)

Fixed

  • Empty agy output is reported as an error, never as a silent success
  • The whole process group is killed (SIGTERM → SIGKILL escalation), and the deadline fires even if agy's helper processes hold the output pipes open
  • ModelRegistry: concurrent first calls share a single agy models fetch, and transient listing failures are retried instead of being cached for the process lifetime
  • When every chain model is exhausted, the call fails in seconds with the reset times listed — instead of hanging

Verification

66 unit tests (31 new) plus a live e2e test (AGY_E2E=1) proving an exhausted model returns a QuotaError in ~6s instead of hanging.

Full diff: 1027c7e...v0.3.0