June 22, 2026

One timeout to rule every provider call

A single 300-second ceiling now caps every provider call, the browser tool learns to read computed CSS, and boot stops hanging on a missing dependency.

Today was about closing gaps that only show up under real-world conditions: a provider that hangs, a browser tool that can’t see the page it’s driving, a boot sequence that silently wedges itself. None of these are glamorous. All are the difference between a tool you trust and one you babysit.

The provider timeout was the biggest one. Every LLM provider Chalie talks to shipped with its own SDK-level timeout — 120 seconds for Anthropic and OpenAI, 60 for Ollama — and none reliably capped a stalled stream, so a provider could hang past its own ceiling and wedge the entire turn with nothing forcing it to give up. The fix: stop trusting per-platform guarantees and own the boundary myself. Every provider call now runs on a daemon thread joined against one uniform 300-second wall clock; if it doesn’t return in time, the call is abandoned and surfaces as a clean, catchable error instead of a silent stall. One rule, applied everywhere, instead of three vendors’ promises. The exception is Ollama’s lightweight pre-flight probe that checks model metadata before a real call starts — it keeps its own short timeout because it’s not the thing that hangs.

The browser tool got sharper eyes too, picking up a tenth verb, style, which resolves an element by the same visible-text locator click already uses and reads back its exact computed CSS — color, background, border, font, as concrete rgb() values from the browser’s own rendering. Before this, answering “what colour is this button” meant guessing from a screenshot or digging through page source. Now it just asks directly.

The other half of that thread was making sure the browsing agent isn’t flying blind. Screenshots taken mid-browse were previously just a document ID and a note to call the vision tool separately — the pixels never reached the model driving the session, so it looped, acting on a page it couldn’t see. Screenshots now flow through the same ingest pipeline that already describes chat image attachments, so that description surfaces inline as part of the screenshot result: no redundant round-trip, no blind loop. The delegate’s own instructions got leaner too — drive the browser in the fewest steps possible, bail with a clear error rather than grind, and give it one narrow, concrete goal per call instead of one sprawling instruction, firing several in parallel when there’s more than one thing to check on a site.

Then the boot bug: every container restart hung the startup screen for two minutes because a runtime dependency was only ever pulled in transitively, never declared outright, and the first self-heal attempt failed instantly because the network wasn’t up yet — permanently marking that dependency broken for the process’s whole lifetime. Declaring it an explicit base dependency and giving the self-heal install three retries with backoff turns a permanent failure into a transient one that recovers on its own.

None of this changes what Chalie can do so much as how reliably it does it — and reliability compounds. A provider timeout that fires turns a hung call into a retry instead of a dead turn. A browsing agent that can see and query the page it’s on makes fewer wrong moves per task. A boot sequence that heals itself means fewer stuck moments before anyone even uses it. Less time explaining Chalie’s failure modes, more time using it.

  • Single 300-second wall-clock ceiling replaces every per-provider SDK timeout; a stalled call now surfaces as a clean error instead of wedging the turn

  • Browser tool gains a style verb — resolves an element by visible text and reads back exact computed CSS (colors as rgb(), fonts, borders) via the browser’s own rendering

  • Screenshots now self-describe through the existing document-ingest pipeline, so the browsing agent sees the page inline instead of looping blind

  • Browsing delegate prompt rewritten to finish in fewer steps and bail on failure, with guidance to fire narrow, parallel goals instead of one broad instruction

  • Boot dependency pinned explicitly with a 3-attempt retry-with-backoff self-heal, fixing a permanent 503 caused by a one-shot install racing the container’s network