Repository navigation
feat(browser): a browser's log of every agent action and tab event, across CDP, MCP tools and pixels (FD-4967) - #613
Open
earakely-scale wants to merge 12 commits into
Conversation
…cross CDP, MCP tools and pixels (FD-4967) M8.19. The browser's app server keeps one log, in /var/log/agentenv/browser-<name>.jsonl, numbered lines that last the boot: an entry for each CDP command through the relay, each op a driver makes for an agent's MCP tool call (the page driver passes the call in an AgentEnv-Tool-Call header), and each acting op agentenv makes; and an event each time a tab opens, navigates or closes, naming the command that caused it, agentenv, or the page after the latest action on its tab. Entries are marked acting or reading; acting ones keep their parameters with secrets taken out by shape. browser/v1 log reads it, and data/get exports it beside browser-state.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ace (FD-4967) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… a driver's own extension ops (FD-4967) ToolContext gains mcp, true only for an MCP tool call's context, so the page driver's calls for computer-ready/v1 status no longer carry the AgentEnv-Tool-Call header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tarts a new one (FD-4967) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…7-m819-the-action-log-and-tab-log # Conflicts: # packages/agentenv-protocol/src/agentenv_protocol/website_browser/environment.py
…ke, bodies withheld, entries always finished (FD-4967) - A relayed command that types is checked for a password field before it's sent, and page input before each event, so Tab into a password field is caught; a tool call's typed text or keys, in any shape, are withheld then. - URL fields at any depth are redacted (a batch of cookies' URLs too), and bodies and page content withheld. - A command whose client leaves before the browser answers is still written, and what it caused settled; a line held longer than STALLED_S no longer holds back reads. - A move within a document is credited to the command that asked for it, and uses up a pending history move. - Reads use an index of where each line is, off the event loop; an op body is joined once, and one past 1 MiB is logged by its length. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…check; a stalled action is stood in for, not skipped (FD-4967) - Each connection's commands hold a lock from when they arrive until they're sent, so a command waiting on its password check lets none after it reach the browser first; answers still come back as they're ready. - An action still going after STALLED_S is written by the next read as unfinished, in its place, and an outcome line names it when it ends, so a read's last never moves past a line it hasn't returned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…word check clears it (FD-4967) A typing command cancelled while it waited its turn, its connection gone, was logged with its text: it now starts withheld and is kept only once a check says no password field has focus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…7-m819-the-action-log-and-tab-log # Conflicts: # src/agent_env/browsers/README.md # tst/integration/computer/browser_computer_test.py
…e_browser, as cdp and log (FD-4967) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ing stays withheld, in the browser's log (FD-4967) - A tool call's URL is redacted before the driver cuts it, and a cut URL's kept part is redacted too. - URLs in an entry's error, as a failed navigation's names its URL, are redacted. - An op's typing is kept only once every check it made found no password field focused: one that fails, or never got to check (no tab open), keeps it withheld, as the relay already did. - A reload or move in history leaves its cause only once it's sent and answered: one with nowhere to go, or that fails, credits nothing after it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
M8.19 (FD-4967). A browser now keeps one log of every action agents take on it, whichever way in: CDP commands, MCP tool calls and pixel actions. Beside them are tab events (opened, navigated, closed), each naming what caused it. The browser's app server writes it in the browser computer, so it's the same whether an agent connects directly or through a gateway.
Design note, outcome and five decisions (all option a, Nov 10): M8.19 Action log. Not yet reviewed.
What changes
agentenv_protocol/website_browser/log.py(new):acts,ACTING_OPS);redacted_params,redacted_op,redacted_args,redact_url,cut);BrowserLog, the writer and reader;Causes, which ties a tab event to the command in flight that caused it.website_browser/cdp.py, moved frombrowser_cdp.py) logs every command. Each entry has its connection's user and number, the method, the tab its session is on (mapped fromTarget.attachedToTarget), and whether it worked. Also, when there is one, what the guard did.website_browser/control.py):ACTOR);ComputerAppEnvironment.served_asgi()hook, whichserve_appuses. The browser wraps its app with it, so eachbrowser/v1op becomes an entry: every op made for an agent's MCP tool call, and every acting op agentenv makes itself.browser/v1:log {after}op;data/getwritesbrowser-log.jsonlbesidebrowser-state.json, anddata/addpasses over it;data/resetwrites aresetline.AgentEnv-Tool-Call(tool, call id, arguments) and the caller'sAgentEnv-Roleon each call it makes for a tool.ToolContext.mcp(new, defaultFalse) is true only for an MCP tool call's context. Without it, the driver's own extension ops, such ascomputer-ready/v1status, were credited to a tool. The new integration test caught that.browsers/README.mdanddrivers/README.md.The log
/var/log/agentenv/browser-<name>.jsonl, or the app's own.agentenv/folder when that can't be written. Each line is one JSON object withseq,at, and one ofaction,taborreset.action.viacdp,mcp(an op for an agent's tool call) oragentenv(its own acting ops)action.whodefaultwithout one)action.method/tool,call,opaction.actsaction.tab,urlcreateTargettakes the tab it openedaction.params/argsaction.ok,error,guardtab.event,id,url,byopened,navigatedorclosed;byiscommand(withentry,via,who),agentenv,exit,stop, orpage(withafter, the latest acting entry on that tab, or its opener's)A line's number is taken when what it records begins, and the line is written when it ends. So
logreturns lines in order, up to the last one whose earlier lines are all written, and itslastnever moves back. A restarted app server carries on the numbering from the file.An action still going after 60 s is written by the next read as
unfinished, in its place, so it holds back nothing after it. When it ends, anoutcomeline names it (entry) with what it ended with.Decisions taken while building, for review
reset_envstarts a new log (you chose a, Nov 11). The chaos test showedreset_envreboots the computer into a fresh container, so the log lasts the boot. A task that needs the log from before a reset takes it withsnapshot_envfirst. Only the browser's owndata/resetwrites aresetline into the same file. Decision 3 in the note is updated.token,key,code,session,sig,X-Amz-*and the like), along with a password in the URL. The note said this would reusetransfers.py's redaction, but that drops the whole path and query, so it's a small new helper; the note is corrected.createTargetat a URL would show its own load as the page's.record,tabs/listand the rest, and thelogop itself. Its acting ops (sites/set, start tabs) are, asvia: "agentenv".unfinished, then gets anoutcomeline (Greptile). Without this, a command Chrome never answers would hold every later line back, or a poller would miss it.Test plan
test_browser_log.py(new):test_browser_cdp.py: every relayed command logged on its session's tab. The ops wrapper logs a tool call's ops and agentenv's acting ops, but not agentenv's reads.test_browser_data.py:data/getexports the log, anddata/addpasses over it.test_tool_context_injection.py: only an MCP tool call's context hasmcp.github_clonetests, which hang on a realgit cloneon this Mac's network.test_its_log_has_an_entry_for_every_action_over_cdp_page_tools_and_pixels_with_no_secrets, the "Done when":browser_computer_test,chromium_app_test,website_browser_testandbrowser_gateway_test, 40 passed. The two failures were in the tests and are fixed: a click before any frame, and a pinned list ofbrowser/v1methods withoutlog. Both pass on rerun.browser_computer_testis being rerun on the merged head.textandkeyswithheld in any shape;unfinishedandoutcomelines;backleaving no cause behind.browser_computer_test, 23 of 23 with nothing skipped. The "Done when" test and chaos pass again on46ebf7e4, and are being rerun onf7eca21c.reset_envstarts a new log;Not in this PR
🤖 Generated with Claude Code


Confidence Score: 5/5
The latest changes appear safe to merge; all four numbered previous findings are addressed.Summary
Adds a shared browser action log for CDP commands, MCP tools, and agentenv actions.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR CDP[CDP commands] --> Relay[Browser relay] MCP[MCP tools] --> Driver[Page driver] Driver --> Ops[Browser operations] Agentenv[Agentenv actions] --> Ops Relay --> Log[BrowserLog] Ops --> Log Tabs[Tab events] --> Log Log --> Read[Ordered reads] Log --> Export[Snapshot export]Reviews (6) · Last reviewed commit: "fix(browser): no credentials from long o..." · Reviewed by Greptile