Skip to content

feat(browser): cut the Browser instruction section to routing rules - #2288

Merged
chuks-qua merged 4 commits into
mainfrom
feat/issue-2220
Oct 23, 2026
Merged

chuks-qua merged 4 commits into
mainfrom
feat/issue-2220

Conversation

@chuks-qua

@chuks-qua chuks-qua commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

What

Before this change, the runtime Browser section was 302 words. It repeated every operating rule from the Browser tool descriptions and included a call-shape example (s3e12). It also said "use only" Mcode's Browser, so an agent had no sanctioned way out after repeated failures.

The section is now 141 words of routing rules only. Operating rules stay in the tool descriptions, which the model loads after it has picked a tool.

 Mcode Browser
-- Boundary / Open / Inspect / Target / Verify / Interruptions / Recover / Evidence / Finish / Evaluate rules
+- Prefer the mcode MCP browser_* tools for any browser work.
+- Check status with browser_inspect and open a tab before concluding the Browser is unavailable.
+- When the user means the page they have open, read their tab.
+- After a first failure, follow the error's recovery instruction. Do not switch.
+- Switch only after two failures on the same step, or when the user asks. Quote the raw error.
+- A user hold, Stop or do_not_retry is not a failure: yield instead of switching.

The tool descriptions now agree with the section:

  • browser_open states the same switch rule. It no longer says to use only Mcode's Browser.
  • browser_open and browser_inspect both say to call browser_tabs finalize before replying, because a flow may never load browser_tabs.

Verification

Tests:

  • thread-orchestration: 21 passed. A new test checks that the section is under 200 words, contains no call shapes, and states the prefer and switch rules.
  • providers: the full package suite passed (112 files, 1,707 tests). The adapter tests now expect the new "Prefer" wording. The Claude factory tests detect the Browser section by browser_inspect, because the section no longer names browser_tabs.
  • server: 35 passed (browser-toolkit, mcp-conformance, mcode-instruction-boundaries). A new test checks the finalize rule on browser_open and browser_inspect.
  • Typecheck is clean for server, providers, and thread-orchestration. Lint shows only the 2 existing warnings.

Live runs in the Electron app against a local fixture page (an order form with a Name input and a Save button). Each agent had only the new section and the tool descriptions:

Provider Result
Codex (GPT-5.6 Luna) Passed. Its first browser_open failed with "Browser became unavailable". It retried in Mcode's Browser, then inspected, typed, clicked, inspected again, finalized, and answered "Saved order for Ada". It ran no shell commands and opened no other browser.
Claude Passed. It loaded the Browser tools through ToolSearch, used only Browser tools, closed its tab, and answered "Saved order for Ada".
Claude, forced failure The prompt asked it to click ref s1e1 before inspecting. The server refused with STALE_TARGET_GENERATION. Claude inspected, completed the form in Mcode's Browser, quoted the error, and answered "Saved order for Ada".
Copilot Not verified. The account returns 403 "not authorized to use this Copilot feature".
Cursor Not verified. The Cursor CLI is not installed on the test machine.

Why

Agents choose a browser before any Browser tool description loads. The section must win that choice, and it should not repeat rules the model will read in the tool descriptions anyway. A shorter section also leaves more room in each provider's context. The explicit switch rule gives agents a bounded exit after two failures on the same step, so they neither give up after one failure nor loop on a broken Browser.

Closes #2220

Review Notes

  • Docs: docs/internals/providers/mcode-agent-instructions.md now explains the split between routing rules and operating rules. browser_open repeats the switch rule, so both places need editing when the rule changes.
  • User's tab: The "read their tab" rule pairs with browser_inspect taking a tabId from feat(browser): let the agent read the user's own Browser tab #2287. Merging main kept feat(browser): let the agent read the user's own Browser tab #2287's tab-reading sentences in the browser_inspect description and dropped its "Use only mcode MCP browser tools" clause, which contradicts the switch rule.
  • Known gaps: Copilot and Cursor were not verified live, for the reasons in the table. Their instruction delivery uses the same shared builder, and their adapter tests pass.
  • Risk: Easy to revert. The change touches only instruction text and tool description text, with no schema, database, or config changes.

The runtime Browser section now says which browser to use, how to confirm it
is unavailable, and when to switch after failures. The Browser tool
descriptions own the operating rules. browser_open and browser_inspect now
carry "finalize before replying", because a flow may never load browser_tabs.
They also allow a switch after two failures on the same step instead of
forbidding other browsers outright.

Closes #2220
The open, inspect and evaluate descriptions still said to use only Mcode's Browser, which contradicted the section's switch after two failures. The section now also says a user hold, Stop or do_not_retry is not a failure to retry around.
# Conflicts:
#	apps/server/src/features/mcode-mcp/toolkits/browser-tool-schemas.ts
@chuks-qua
chuks-qua merged commit 9d71c12 into main Oct 23, 2026
11 checks passed
@chuks-qua
chuks-qua deleted the feat/issue-2220 branch October 23, 2026 16:16
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.

feat: cut the Browser instruction section to routing rules

1 participant