Skip to content

Make an upgrade reach a Bot's computer - #155

Merged
davidmckayv merged 1 commit into
mainfrom
fix/an-upgrade-reaches-the-computers
Aug 22, 2026
Merged

Make an upgrade reach a Bot's computer#155
davidmckayv merged 1 commit into
mainfrom
fix/an-upgrade-reaches-the-computers

Conversation

@davidmckayv

Copy link
Copy Markdown
Contributor

Found during the from-scratch release validation, by rebuilding every image, tearing the stack down, starting it back up, and watching a Bot answer with in-memory state from an hour earlier.

What was wrong

A Bot's computer is a container the supervisor makes, not compose. ensure reused any container with the right name, whatever image it was built from — there was no comparison at all:

const existing = await inspectOwned(names);
if (!existing) { /* create */ }
// existing → reused, whatever it is running

So once a Bot had a computer, rebuilding the image moved the tag and the container went on running the old one indefinitely, with nothing to say so. docker compose down does not touch these either, because compose did not make them, so even a full teardown left them behind.

That is worse than stale code. agent-computer is the browser, the workspace, and the confinement around both. A fix to any of them silently did not apply to a Bot that already had a computer.

How it showed up

A Bot in a brand new chat displayed an amber "The assistant needs you — GitHub is asking you to sign in" banner with a Take control button, about a page from a conversation an hour earlier. Someone could hand over their browser believing it related to what they had just asked.

The banner was the symptom. The cause:

openbot-computer-risk-analyst   Up 4 hours   image a6911afaec2f
openbot-agent-computer:latest                image b1cf3522d97c

Four hours old, on an image two builds behind, after a full docker compose down + rebuild + restart. Removing the containers by hand cleared the banner, which confirmed it.

The fix

A computer built from a different image is replaced on next use.

  • Compared by resolved id, not by tag. Both sides are the same tag; the whole question is whether it has moved.
  • Unanswerable counts as current. If the image cannot be inspected — never pulled, unreachable registry, a daemon that will not say — the existing computer is kept. Destroying a Bot's working browser over a failed inspect is a worse answer than running a version behind.

Replacing is safe, and that is what makes it automatic. The profile and the workspace are named volumes and are not removed, so a Bot comes back on the new image still signed in to what it was signed in to, with its files where it left them. That is the difference between this and reset, which is asked for deliberately and does take the profile. What is lost is what the old computer held in memory — an open page, an outstanding handover — which belongs to a run the upgrade has already ended.

scripts/start.sh now also says that stopping the compose services leaves the computers running, and how to stop them.

Driven on the real deployment

Rebuilt agent-computer so the tag moved to a new id while both computers still ran the old one. Restarted through scripts/start.sh — the same procedure that had left them stale earlier in the evening:

before   openbot-computer-general-assistant  b1cf3522d97c   (tag had moved to fa5372c72270)
after    openbot-computer-general-assistant  288c200d441c   = current tag, container 11 seconds old

Both replaced. Volumes kept — openbot-profile-general-assistant and openbot-workspace-general-assistant both still dated 01:55:20Z, hours older than the container mounting them.

Then drove it in Chrome: the Bot opened example.com on the new computer, the render appeared on screen, and it answered with the heading Example Domain and cited https://example.com/. No stale banner.

Tests

Two added to supervisor/tests/docker.integration.test.ts, against a real daemon:

  • is replaced, and keeps its profile and workspace — different container id, image equal to the resolved id of the tag asked for, and both volumes identical by CreatedAt.
  • is left alone when it is already the image asked for — same container id. This is the half that keeps the fix from restarting every computer on every request: ensure is called whenever a computer is needed, so a comparison that ever reported stale for a current container would throw away a Bot's browser mid-task.

Both proven against the unfixed code: with the replacement disabled, the first fails on expect(after.Id).not.toBe(before.Id) — the container is not replaced.

Neither asserts container status or start time. The placeholder test image has no long-running command, so it exits and Docker restarts it; those are facts about that image, not about ensure.

Not closed

Drift in the container's configuration rather than its image. An operator tightening the confinement — a pids limit, a memory cap, a gVisor runtime — still does not reach a computer that already exists. That deserves its own change and its own thought about when it is safe to act on.

A computer is a container the supervisor makes, and `ensure` reused any
container with the right name whatever image it was built from. So once a
Bot had a computer, rebuilding the image moved the tag and the container
went on running the old one indefinitely, with nothing to say so.
`docker compose down` does not touch these either, because compose did
not make them, so even a full teardown left them behind.

That is worse than stale code. agent-computer is the browser, the
workspace and the confinement around both, so a fix to any of them
silently did not apply to a Bot that already had a computer.

Found by rebuilding every image, tearing the stack down, starting it back
up, and watching a Bot answer with in-memory state from an hour earlier:
a handover prompt about a page from a previous conversation, offered on a
new one. The prompt was the symptom; the container was four hours old on
an image two builds behind.

A computer built from a different image is now replaced on next use.
Compared by resolved id rather than by tag, because both sides are the
same tag and the question is whether it has moved. An image that cannot
be inspected counts as current: destroying a working browser over a
failed inspect is a worse answer than running a version behind.

Replacing is safe, and that is what makes it automatic. The profile and
the workspace are named volumes and are not removed, so a Bot comes back
on the new image still signed in to what it was signed in to with its
files where it left them. That is the difference between this and reset,
which is asked for deliberately and does take the profile.

What is lost is what the old computer held in memory, which belongs to a
run the upgrade has already ended.

start.sh now also says that stopping the compose services leaves the
computers running, and how to stop them.

Not closed: drift in the container's configuration rather than its image.
An operator tightening the confinement, a pids limit or a gVisor runtime,
still does not reach a computer that already exists.
@davidmckayv
davidmckayv merged commit f1d7feb into main Aug 22, 2026
8 checks passed
@davidmckayv
davidmckayv deleted the fix/an-upgrade-reaches-the-computers branch August 22, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant