Skip to content

Tell a built-in Bot about its computer - #79

Open
rhlsthrm wants to merge 1 commit into
CopilotKit:mainfrom
rhlsthrm:a-built-in-bot-knows-its-computer
Open

Tell a built-in Bot about its computer#79
rhlsthrm wants to merge 1 commit into
CopilotKit:mainfrom
rhlsthrm:a-built-in-bot-knows-its-computer

Conversation

@rhlsthrm

Copy link
Copy Markdown

What this changes

shared/bot-prompt.ts holds what a Bot knows about its own hands: navigate rather than claiming you cannot browse, snapshot before acting so refs are real, workspace files, and the sign-in protocol —

Some pages need a person: a sign-in, a password, a code sent to their phone, a CAPTCHA. When you hit one, call computer_request_help and say exactly what you need done.

Two files imported it, and both are shipped Bots: agent-bot and agent-langgraph. A built-in agent knew only the role its package gives it — for the example package, "You are a helpful general assistant. Give clear, concise, and accurate answers." Meanwhile <ComputerTools /> is mounted for every Bot alike, so the tools were on offer to it the whole time; nothing had told it what they were for.

Asked to file an issue on GitHub, General Assistant browsed to the issues page, said it could not do it while signed out, and never called computer_request_help — so nobody was ever offered the wheel, on a deployment whose take-the-wheel path works. That is not a Bot declining a task, it is a Bot that was never told the task was possible.

SYSTEM_PROMPT becomes COMPUTER_GUIDANCE, because instructions about the computer belong to the computer rather than to one implementation, and builtInAgentConfiguration appends it to the package role. Both shipped Bots keep the identical text as their whole prompt, so their behaviour does not change.

Threaded from mountCopilotRuntime, which passes it only when config.computer is set. A deployment with no computer has the browser routes unmounted, and a Bot told it has a browser there would be a Bot promising something that does not exist.

Where it runs

  • New state that outlives a request? None. The prompt is composed per agent as the agent map is built, which is already per request.
  • What happens on the second replica? Identical behaviour. The guidance is derived from DeploymentConfig and a module constant, both of which every replica has; nothing is cached or coordinated.
  • Anything serialised? Nothing new.
  • Anything fanned out to a browser? No.
  • New listener, port, or schedule? None.

Boundary and audit

  • Every acting call still goes through the gateway. This grants nothing: the computer tools were already registered by the surface for every Bot, and each call is resolved, decided and audited exactly as before. What changes is that the Bot knows how to use what it already had, and asks for a takeover instead of giving up.
  • New refusals and new failures each write a row. No new class of either. A Bot now reaches computer.help_requested/control_taken/control_released, which are existing events that a built-in agent previously never triggered.
  • Nothing new is trusted from the client. The prompt is assembled server-side from the tenant package and a module constant.

Changelog

  • A line under UnreleasedFixed.

Proof

bun test server/tests/copilot.test.ts → 16 pass. bun run typecheck clean in server. Biome clean on all four files.

Before, on the running stack: "File an issue on github.com/CopilotKit/openbot titled ..." to General Assistant. audit_events shows exactly one action —

07:40:32 | computer.action_allowed | general-assistant | computer_navigate | https://github.com/CopilotKit/openbot/issues

— and then prose saying it could not. No computer_request_help, no help event, no takeover offered.

After, same request, same Bot: it navigates to GitHub's sign-in page, reports the wall, and offers to have a person sign in. Asked to hand over, it calls the tool and the banner appears — "The assistant needs you. Please sign in to GitHub so I can file an issue on your behalf." with Take control — and taking control shows the real login inside that Bot's own Chromium with "You have control. Click and type on the page as you normally would." The events land in order:

08:05:48 | computer.help_requested    | general-assistant
08:08:08 | computer.control_taken     | general-assistant
08:08:49 | computer.control_released  | general-assistant

One thing this does not fix, worth saying plainly: with the guidance attached, the model still asked in prose on first hitting the sign-in wall rather than calling computer_request_help straight away, and offered the wheel when asked. The instruction is explicit, so that looks like model judgment (gpt-5.5) rather than missing wiring, and the prompt text is unchanged here.

The instructions that make the computer usable live in
shared/bot-prompt.ts: navigate rather than claiming you cannot browse,
snapshot before acting, and at a sign-in call computer_request_help so a
person can take the wheel rather than reporting the task as impossible.

Two files imported it, both of them shipped Bots. A built-in agent knew
only the role its package gave it, while the surface offered it the same
computer tools as everything else. Asked to file an issue on a site it
was not signed in to, General Assistant browsed to the page, said it
could not, and never asked for help, so the wheel was never offered.
That is not a Bot declining; it is a Bot that was never told.

Renamed to COMPUTER_GUIDANCE, because instructions about the computer
belong to the computer rather than to one implementation, and appended to
the package role for built-in agents. Only where a computer is
configured: a deployment with the browser routes unmounted should not
promise a Bot hands it has not got.
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