AgentOS 2026.8.23
A release about reaching past the model's own text: the agent can drive a real browser, failover stops paying for a dead provider once per turn, a skill's dependencies install whatever kind they declare, and a chart downloads as the chart you were looking at.
The agent can drive a real browser
A browser built-in, backed by the agent-browser CLI (Vercel Labs, Apache-2.0): navigate, read a page as an accessibility snapshot with element refs, click, type, fill, wait, run JavaScript, answer native dialogs, and screenshot. Managed and headless by default; attach mode drives the operator's own browser when they opt in.
Policy is enforced in AgentOS rather than delegated to the engine, because an engine that owns its own guardrails is an engine whose guardrails ship on someone else's schedule. SSRF is checked on navigate and again on the post-redirect URL, and reads carry a private-page guard so a JavaScript redirect cannot leak an intranet page into a later snapshot. data: and about: pass — no host, no network — and file: is refused. eval is SSRF-pre-scanned in both modes: the managed browser is not exempt, because it runs on the operator's host and reaches loopback, the LAN, and the cloud-metadata endpoint exactly as their own browser does. It also carries an opt-in restrict_evaluate denylist, off by default, and a post-eval page-URL recheck.
Everything the engine returns — snapshots, eval results, tab titles and URLs, every action payload — crosses into the transcript inside the untrusted envelope and through credential redaction, and type and fill refuse credential-shaped text. The engine subprocess starts from a minimal environment, never os.environ, so the gateway token and the provider keys are unreachable from the browser process. An optional allowed_domains bounds navigation in AgentOS and, when set, at the engine layer too, and the tool sits in group:web, so denying web denies it. (#346)
Failover notices a provider is down
A circuit breaker counts consecutive provider-health failures — overload and gateway 5xx, transport errors, rate limits — per configured provider id. After llm.circuit_breaker.failure_threshold failures (default 3) the provider is skipped for a cooldown window: 60 seconds by default, doubling per consecutive trip up to max_cooldown_seconds, with one half-open probe per window that re-closes the breaker when the provider recovers.
Failover was purely reactive and per-request. ModelSelector reset to the primary each turn, so every turn during an outage paid the full timeout on the dead primary before falling back — the fallback worked, and it worked once per turn, forever. Breaker state is now shared across per-turn selector clones, so detection is paid once per outage instead of once per turn.
Request-shaped failures — unknown model, bad request, context overflow, auth, billing — never trip the breaker, because they say something about the request rather than about the provider. If every link in the chain is in cooldown the primary is still used, since refusing to answer is worse than a slow answer. The state is visible where the decision is: a circuit column in agentos providers status, provider.circuit.open and provider.circuit.half_open in agentos doctor, and circuitBreaker / circuitBreakers on GET /api/system/status. (#365, #394)
Skill dependencies install what they declare
Three code paths each carried their own idea of what install.kind meant. The Skills page executor knew brew, uv, and download; the install_skill_deps tool knew brew, node, go, and uv; the install hints rendered a third set. The seven bundled gmgn skills declare kind: npm, which no executor recognized — "Unsupported install kind: npm" from both — and apt failed the same way.
All three now read one canonical vocabulary and one command builder in agentos/skills/install_kinds.py: brew, npm, go, uv, download, and apt, with node kept working as an alias for npm. The command shown as an install hint is now literally the command that runs. apt needs root and download needs a fetch plus a chmod, so both stay hint-only — and say so, instead of reading as unsupported.
A uv spec that declares bins installs with uv tool install; one that doesn't — a library like openpyxl — keeps using uv pip install, which the agent tool used to get wrong. Pinned versions (gmgn-cli@1.2.3, openpyxl>=3.1) survive the value allowlists instead of silently losing their install hint, an apt package can no longer end in the - that turns an install line into a removal, and the download hint validates and quotes its URL rather than interpolating it raw. (#358, #395)
Changed
- A chart artifact in the Web UI downloads as a rendered screenshot image instead of a raw JSON link, so the button hands over the chart you were looking at. (#247, #375)
Fixed
- A pinned turn no longer shows another turn's router-fx strip. The
route_pinnedearly-return swept only live strips from the dock, so a settled strip from an earlier turn —data-liveabsent — survived and lingered above the composer, reading as this turn's selection while the composer pill showed the pinned model. Every router-fx strip for the current session is now swept on the pinned path, live and settled alike; strips belonging to other sessions are left untouched. (#345, #399)
Docs
- Troubleshooting gains Windows, browser, router, memory, and Docker sections. (#348)
- The CLI and configuration docs catch up with the code on prompt caching, safety, audio, and images, and
agentos.toml.examplestops advertising sections that were never read. (#371, #387)
Install
uv tool install --python 3.12 "use-agent-os[recommended]==2026.8.23"Full changelog: https://github.com/use-agent-os/agent-os/blob/v2026.8.23/CHANGELOG.md