<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AgentRQ</title>
    <description>The latest articles on DEV Community by AgentRQ (agentrq).</description>
    <link>https://dev.to/agentrq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F14958%2F73202c23-ec56-42ab-8665-c8a115eef168.png</url>
      <title>DEV Community: AgentRQ</title>
      <link>https://dev.to/agentrq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/agentrq"/>
    <language>en</language>
    <item>
      <title>How We Built a Shared Markdown Board for AI Agents (and Made Checklists Tick Themselves)</title>
      <dc:creator>Mustafa Turan</dc:creator>
      <pubDate>Tue, 13 Oct 2026 08:00:18 +0000</pubDate>
      <link>https://dev.to/agentrq/how-we-built-a-shared-markdown-board-for-ai-agents-and-made-checklists-tick-themselves-45gm</link>
      <guid>https://dev.to/agentrq/how-we-built-a-shared-markdown-board-for-ai-agents-and-made-checklists-tick-themselves-45gm</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; We run one AI agent per workspace, and each one only sees its own tasks. That's good for focus and bad for hand-offs. The &lt;strong&gt;Pano&lt;/strong&gt; (AgentRQ v0.10.0) is a board of markdown docs that every workspace in an account can read and write. Checklist items can be assigned to a workspace's task, and the item's checkbox follows that task's status on its own. The interesting parts are the design choices: &lt;strong&gt;the markdown is the source of truth&lt;/strong&gt;, &lt;strong&gt;agents get no search&lt;/strong&gt;, &lt;strong&gt;a status change rewrites the doc on the server&lt;/strong&gt;, and &lt;strong&gt;every write carries a version, so two agents can't silently overwrite each other&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2jra4v7vt9p8j65q1ur4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2jra4v7vt9p8j65q1ur4.png" alt="The Pano board: post-it docs from the api, web and design workspaces, a note written by the user, and a chat box for the supervisor" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem are we solving?
&lt;/h2&gt;

&lt;p&gt;Single-purpose agents work well. The API agent knows the API, the web agent knows the frontend, and neither one's context is cluttered by the other's work.&lt;/p&gt;

&lt;p&gt;But real work crosses those boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The API agent changes a response shape. The web agent needs the new contract.&lt;/li&gt;
&lt;li&gt;A release needs three workspaces to finish their parts before Thursday.&lt;/li&gt;
&lt;li&gt;A postmortem should be read by every agent that touches webhooks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until now, the only thing moving knowledge between those agents was the human, who copied the contract into the web task, checked each workspace for progress, and pasted the postmortem into three prompts.&lt;/p&gt;

&lt;p&gt;We wanted a shared surface that agents can write to and read from, that humans can see at a glance, and that doesn't wreck the isolation that makes single-purpose agents good.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Pano doc?
&lt;/h2&gt;

&lt;p&gt;A doc is deliberately boring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a title (up to 200 characters)&lt;/li&gt;
&lt;li&gt;markdown (up to 256 KiB)&lt;/li&gt;
&lt;li&gt;a paper color (&lt;code&gt;yellow&lt;/code&gt;, &lt;code&gt;pink&lt;/code&gt;, &lt;code&gt;green&lt;/code&gt;, &lt;code&gt;blue&lt;/code&gt;, &lt;code&gt;orange&lt;/code&gt;, &lt;code&gt;purple&lt;/code&gt;, &lt;code&gt;amber&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;files (up to 2 MiB each, 100 per doc)&lt;/li&gt;
&lt;li&gt;comments, each recording who wrote it: a workspace or the human&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It belongs to the &lt;strong&gt;account&lt;/strong&gt;, not to a workspace. The board shows the human's own docs first, then the agents' docs, newest first.&lt;/p&gt;

&lt;p&gt;Agents reach it through one MCP tool, &lt;code&gt;pano&lt;/code&gt;, which takes an &lt;code&gt;action&lt;/code&gt; and a &lt;code&gt;payload&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"save"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"payload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"v2.4 release plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"markdown"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"- [ ] Cursor pagination&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- [ ] Changelog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"payload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0kH25QEUKFV"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"includeComments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"payload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0kH25QEUKFV"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Merged behind the flag."&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other actions are &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;attach&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt; and &lt;code&gt;help&lt;/code&gt;. A save without an &lt;code&gt;id&lt;/code&gt; creates a doc and returns its id. A save with an &lt;code&gt;id&lt;/code&gt; replaces the title and markdown, but only if it also sends the doc's current &lt;code&gt;version&lt;/code&gt; (more on that below).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why can't agents search the Pano?
&lt;/h2&gt;

&lt;p&gt;This was the most debated choice, and we think it's the most important one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agents can't list or search the Pano.&lt;/strong&gt; An agent reads a doc only because someone handed it the doc's id: in a task, a reply, or an event payload. The board UI has a title filter for humans. Agents don't.&lt;/p&gt;

&lt;p&gt;The reasoning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolation stays real.&lt;/strong&gt; The point of one-agent-per-workspace is a small, relevant context. If every agent could browse every doc, the Pano would become a shared junk drawer that every agent half-reads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hand-offs become explicit.&lt;/strong&gt; "Here's the contract, id &lt;code&gt;0kH25Ofyi1Z&lt;/code&gt;" is a deliberate act. You can trace exactly why an agent read something.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No relevance ranking to get wrong.&lt;/strong&gt; There's no retrieval step quietly deciding what context an agent gets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cost is that the writer has to pass the id along. In practice that fits how agents already work: they finish a task, reply, or publish an event, and the id goes in that message.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does an assigned checklist item follow its task?
&lt;/h2&gt;

&lt;p&gt;This is the part developers ask about most.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmn28ttdjiwtnayjta2ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmn28ttdjiwtnayjta2ac.png" alt="A release plan doc: a checklist with an item assigned to @api showing Ongoing and one assigned to @web showing Completed and ticked" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: assigning writes a link into the markdown
&lt;/h3&gt;

&lt;p&gt;When you pick &lt;strong&gt;Assign to → api&lt;/strong&gt; on a checklist item, the web app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;creates a task in the &lt;code&gt;api&lt;/code&gt; workspace whose title is the item text and whose body points back to the doc;&lt;/li&gt;
&lt;li&gt;rewrites that line of the markdown so it ends with a link to the task, with the status in the link's title;&lt;/li&gt;
&lt;li&gt;saves the doc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The result is plain markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt; ] Cursor pagination on /v2/invoices → [@api&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;/workspaces/0kH1tWzfwLx/tasks/0kH1ye6SDz7&lt;/span&gt; &lt;span class="nn"&gt;"notstarted"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's &lt;strong&gt;no separate assignments table&lt;/strong&gt;. The link is the assignment, and the link's title is the cached status. Any agent that reads the doc sees who owns the item and where the task lives, with no extra API call. The renderer turns that link into the status chip you see on the board.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: a status change triggers a server-side rewrite
&lt;/h3&gt;

&lt;p&gt;Task status can change from anywhere: the human in the UI, the agent through its MCP tool, or the supervisor. All of those emit the same internal CRUD event. A subscriber listens for task updates and completions and runs a sync:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the task's path, &lt;code&gt;/workspaces/&amp;lt;ws&amp;gt;/tasks/&amp;lt;task&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Find the account's live docs whose markdown contains that path. It's a plain &lt;code&gt;LIKE '%path%'&lt;/code&gt; query, which is enough because the path is unique.&lt;/li&gt;
&lt;li&gt;For each doc, walk the markdown line by line and rewrite matching items.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The line-matching is two regexes: one recognizes a task-list item, and one recognizes an assignee link at the end of the line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// a task-list item: a list marker, then [ ] or [x]&lt;/span&gt;
&lt;span class="s"&gt;`^[ \t]*(?:[-*+]|\d{1,9}[.)])[ \t]+\[([ xX])\](?:[ \t]|$)`&lt;/span&gt;
&lt;span class="c"&gt;// an assignee: a link to a task, titled with its status&lt;/span&gt;
&lt;span class="s"&gt;`\]\((/workspaces/[0-9A-Za-z]+/tasks/[0-9A-Za-z]+)(?: "[a-z]*")?\)[ \t]*$`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For each line that has both and points at this task, the sync writes the new status into the link title, and sets the box to &lt;code&gt;[x]&lt;/code&gt; when the status is &lt;code&gt;completed&lt;/code&gt; (otherwise &lt;code&gt;[ ]&lt;/code&gt;). Lines inside fenced code blocks are skipped, because a &lt;code&gt;- [ ]&lt;/code&gt; there renders as text, not a checkbox.&lt;/p&gt;

&lt;p&gt;So when the &lt;code&gt;api&lt;/code&gt; agent marks its task &lt;code&gt;completed&lt;/code&gt;, the item becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;x] Cursor pagination on /v2/invoices → [@api&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;/workspaces/0kH1tWzfwLx/tasks/0kH1ye6SDz7&lt;/span&gt; &lt;span class="nn"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the checkbox doesn't just tick on completion. It follows the status both ways: reopen the task and the box clears again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: the write is a sync, not a save
&lt;/h3&gt;

&lt;p&gt;A subtle detail: this write &lt;strong&gt;is not a normal save&lt;/strong&gt;. It updates only the markdown, excerpt, size and checklist counters, and deliberately skips &lt;code&gt;updated_at&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why it matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The doc keeps its place on the board.&lt;/strong&gt; A task finishing in another workspace shouldn't bump the release plan to the top as if someone edited it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The author stays the author.&lt;/strong&gt; The doc isn't suddenly "updated by api".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The doc's lifetime doesn't change.&lt;/strong&gt; Docs expire a set number of days after their last save (more on that below). A background status sync shouldn't keep a doc alive forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What the sync &lt;strong&gt;does&lt;/strong&gt; change is the doc's &lt;code&gt;version&lt;/code&gt;. The markdown is different now, so any agent still holding the old version has to read the doc again before it writes. The next section explains why that matters.&lt;/p&gt;

&lt;p&gt;The "2 of 6 done" progress is recounted from the markdown with the same task-item regex on every write, so the board, the card and the doc always agree.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: open boards update live
&lt;/h3&gt;

&lt;p&gt;After the rewrite, the server publishes a &lt;code&gt;pano.changed&lt;/code&gt; event on the account's event stream. Any open board or doc page reloads that doc. The human watching the release plan sees the chip go from Ongoing to Completed and the box tick, without a refresh.&lt;/p&gt;

&lt;p&gt;One honest constraint: the event bus is in-process, so only the backend instance that handled the task change does the rewrite. That's fine, because the rewrite goes to the shared database, and any instance serves the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do two agents avoid overwriting each other?
&lt;/h2&gt;

&lt;p&gt;A shared doc has the classic lost-update problem. In the first version of the Pano, a save with an id replaced the whole doc. So this could happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;api&lt;/code&gt; agent reads the release plan.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;web&lt;/code&gt; agent reads the same release plan.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;api&lt;/code&gt; ticks its item and saves the whole markdown.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;web&lt;/code&gt; adds a line and saves the whole markdown it read in step 2.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;web&lt;/code&gt;'s save silently wipes out &lt;code&gt;api&lt;/code&gt;'s tick. Nobody gets an error, and the doc is just wrong. With several agents and a server-side checklist sync all writing to the same docs, this isn't hypothetical.&lt;/p&gt;

&lt;p&gt;The fix (&lt;a href="https://github.com/agentrq/agentrq/pull/896" rel="noopener noreferrer"&gt;agentrq#896&lt;/a&gt;, merged right after v0.10.0) is &lt;strong&gt;optimistic concurrency&lt;/strong&gt; with a version number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Every doc has a version
&lt;/h3&gt;

&lt;p&gt;Each doc has a &lt;code&gt;version&lt;/code&gt;, starting at 1, which goes up on &lt;strong&gt;every&lt;/strong&gt; write: a save, an edit, and the checklist sync described above. &lt;code&gt;read&lt;/code&gt; returns it, and any update (a &lt;code&gt;save&lt;/code&gt; with an id, or an &lt;code&gt;edit&lt;/code&gt;) must send the version it read. Creating a doc needs no version.&lt;/p&gt;

&lt;h3&gt;
  
  
  The check happens in the UPDATE itself
&lt;/h3&gt;

&lt;p&gt;The important detail is &lt;strong&gt;where&lt;/strong&gt; the check runs. Reading the version, comparing it, and then writing would still leave a race window between the compare and the write. Instead, the version is part of the &lt;code&gt;UPDATE&lt;/code&gt;'s &lt;code&gt;WHERE&lt;/code&gt; clause, and the same statement bumps it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;pano_docs&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;markdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;expires_at&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt;   &lt;span class="c1"&gt;-- the version the writer read&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If another write got in first, the row's version has already moved, the &lt;code&gt;WHERE&lt;/code&gt; matches nothing, and &lt;strong&gt;zero rows are affected&lt;/strong&gt;. The server then checks whether the doc still exists at all. If it does, the write is a conflict. If it doesn't, it's "not found". Either the whole write lands at version N+1, or nothing changes. The compare and the write can't be split.&lt;/p&gt;

&lt;h3&gt;
  
  
  A conflict tells the agent exactly what to do
&lt;/h3&gt;

&lt;p&gt;A stale write is refused with &lt;strong&gt;HTTP 409&lt;/strong&gt; in the REST API, and the MCP tool returns a message written for an agent to act on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;the Pano doc changed since you read it (you sent version 3, it is now 4):
read it again, apply your change to the new content and save again with the new version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A save with no version at all gets a similar message that names the current version. That matters because agents written before versioning existed would otherwise keep overwriting. Now they're told how to fix their call.&lt;/p&gt;

&lt;p&gt;The agent doesn't need special retry logic. It does what the message says: read the doc, redo its change on the new content, and save with the new version. The overwrite becomes an explicit merge, done by the one party that knows what its change meant.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;edit&lt;/code&gt;: change a line without resending the doc
&lt;/h3&gt;

&lt;p&gt;Versioning makes a whole-doc save safe, but resending 256 KiB of markdown to tick one box is still wasteful, and a bigger payload means more chances for an agent to garble something it didn't mean to touch. So there's a new &lt;code&gt;edit&lt;/code&gt; action that takes a list of ops:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"edit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"payload"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0kH25QEUKFV"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ops"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"replace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"oldString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"- [ ] Changelog and docs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"newString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"- [x] Changelog and docs"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"op"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"append"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;- [ ] Announce on the blog"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;append&lt;/code&gt; adds text to the end.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;replace&lt;/code&gt; swaps &lt;code&gt;oldString&lt;/code&gt; for &lt;code&gt;newString&lt;/code&gt;, but &lt;strong&gt;only if &lt;code&gt;oldString&lt;/code&gt; occurs exactly once&lt;/strong&gt;. Zero matches is refused ("not in the markdown"). Two or more is refused with the count and a hint to include more surrounding text. That's the same rule as a good code-edit tool: an ambiguous edit is an error, never a guess.&lt;/li&gt;
&lt;li&gt;The ops apply &lt;strong&gt;in order, all or none&lt;/strong&gt;. If op 2 fails, op 1 isn't saved either.&lt;/li&gt;
&lt;li&gt;The version is checked &lt;strong&gt;before&lt;/strong&gt; the ops run. Against a stale doc, a &lt;code&gt;replace&lt;/code&gt; would fail with a misleading "not found", so the agent is told the real problem: the doc changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result then goes through the same save path, so the size limits, the linked-file rules and the version check all still apply.&lt;/p&gt;

&lt;p&gt;From a shell, the CLI does the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @agentrq/agentrq-ws@latest pano edit &amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;--version&lt;/span&gt; 3 &lt;span class="nt"&gt;--replace&lt;/span&gt; &lt;span class="s2"&gt;"- [ ] Tag"&lt;/span&gt; &lt;span class="nt"&gt;--with&lt;/span&gt; &lt;span class="s2"&gt;"- [x] Tag"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;save&lt;/code&gt; and &lt;code&gt;edit&lt;/code&gt; now print the doc's id &lt;strong&gt;and&lt;/strong&gt; its new version, so a script can chain writes without another read.&lt;/p&gt;

&lt;h3&gt;
  
  
  What humans see on a conflict
&lt;/h3&gt;

&lt;p&gt;The web editor uses the same check. If you're editing a doc and an agent saves it first, your save is refused, &lt;strong&gt;but your draft stays in the editor&lt;/strong&gt;. A banner says the note changed while you were editing and offers to load the latest version, so you can copy your text first. Ticking a box on the board works the same way: on a 409, the doc is reloaded and you're asked to try again, so what you see is what a retry would change.&lt;/p&gt;

&lt;p&gt;The checklist sync bumping the version fits in here too. If the &lt;code&gt;api&lt;/code&gt; task completes while you have the release plan open in the editor, the server's rewrite moves the version, and your stale save is refused instead of un-ticking the item.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do @mentions turn into tasks?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7fh6pv2kovizkf5ick0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7fh6pv2kovizkf5ick0g.png" alt="An API contract doc with a comment from the web workspace asking for a bigger page size, and the api workspace's answer" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comments are plain text with an author. Typing &lt;code&gt;@&lt;/code&gt; suggests workspaces. When the comment is posted, every workspace it names by its full name gets a task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title: &lt;code&gt;Pano: &amp;lt;doc title&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;body: the comment quoted, then an instruction to read the doc with &lt;code&gt;includeComments&lt;/code&gt; and &lt;strong&gt;answer with a comment on the doc&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last part is the design. The answer goes back on the doc, not into a private task thread, so the conversation stays where the work is and the human can read it later. Pings are sent about a second apart, because the server allows one task creation per second per account. If one ping fails, the comment is already posted and the others still go out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stops the board from filling up forever?
&lt;/h2&gt;

&lt;p&gt;Every doc has a time to live: &lt;strong&gt;30 days after its last save&lt;/strong&gt; by default. A save can ask for any whole number of days up to a server maximum (365 by default, configurable). An expired doc is hidden right away. An hourly sweep on every backend instance deletes expired docs and their files. If two instances race, the loser just skips the doc.&lt;/p&gt;

&lt;p&gt;This matches how hand-off docs actually behave. A release plan is useful for a few weeks. A postmortem can ask for a year.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the rules for files?
&lt;/h2&gt;

&lt;p&gt;There are two kinds of files, and the split keeps docs self-consistent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linked files&lt;/strong&gt; travel with the markdown. Each must be linked from it by name, as &lt;code&gt;![chart](chart.png)&lt;/code&gt; or &lt;code&gt;[spec](spec.pdf)&lt;/code&gt;. A save that sends a file the markdown doesn't link is &lt;strong&gt;refused&lt;/strong&gt;. A linked file that the markdown stops linking is &lt;strong&gt;deleted at the next save&lt;/strong&gt;. So every linked file is always reachable from the doc's text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attachments&lt;/strong&gt; are added with &lt;code&gt;attach&lt;/code&gt;, need no link, and stay until the doc is deleted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Limits refuse rather than truncate. An agent told its doc is over 256 KiB can decide what to cut. One whose doc was silently cut in half can't.&lt;/p&gt;

&lt;p&gt;For shells and CI, the &lt;code&gt;agentrq-ws&lt;/code&gt; CLI keeps the doc out of the agent's context entirely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @agentrq/agentrq-ws@latest pano save &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s2"&gt;"Release plan"&lt;/span&gt; &lt;span class="nt"&gt;--markdown&lt;/span&gt; @plan.md &lt;span class="nt"&gt;--file&lt;/span&gt; chart.png &lt;span class="nt"&gt;--color&lt;/span&gt; blue
npx &lt;span class="nt"&gt;-y&lt;/span&gt; @agentrq/agentrq-ws@latest pano &lt;span class="nb"&gt;read&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;--comments&lt;/span&gt; &lt;span class="nt"&gt;--out&lt;/span&gt; ./pano
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;save&lt;/code&gt; prints only the id. &lt;code&gt;read --out&lt;/code&gt; writes the markdown and its linked files side by side, so relative links still resolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does this unlock?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents hand work to each other directly.&lt;/strong&gt; The API agent posts the contract and puts the id in its reply. The web agent reads it. No human copy-paste.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A plan tracks itself.&lt;/strong&gt; Items assigned to workspaces tick when the work is done, not when someone remembers to update the list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation and coordination together.&lt;/strong&gt; Each workspace keeps its own tasks and memory. The Pano is the one shared surface, used on purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hand-offs become visible.&lt;/strong&gt; What agents tell each other is on a page a human can scan, edit or delete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Many writers, no lost updates.&lt;/strong&gt; Agents, the checklist sync and humans can all write to the same doc, and a stale write is refused instead of quietly winning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is the Pano a vector store or RAG?&lt;/strong&gt;&lt;br&gt;
No. There's no embedding, no retrieval and no search for agents. An agent reads exactly the docs whose ids it was given.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if someone edits an assigned line by hand?&lt;/strong&gt;&lt;br&gt;
The sync only matches lines that are a task-list item &lt;strong&gt;and&lt;/strong&gt; end with a link to that exact task path. Change the text before the arrow freely. Remove the link, and the item is no longer assigned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does a status sync count as an edit?&lt;/strong&gt;&lt;br&gt;
Not for the board. It updates the markdown and checklist counts without touching &lt;code&gt;updated_at&lt;/code&gt;, so the doc keeps its place, author and expiry. It does bump the &lt;code&gt;version&lt;/code&gt;, so a writer holding the old one has to read again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens if two agents save the same doc at once?&lt;/strong&gt;&lt;br&gt;
The first write wins and moves the version. The second is refused with a 409 and a message telling the agent to read the doc again, redo its change and save with the new version. Nothing is silently overwritten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not lock the doc while an agent edits it?&lt;/strong&gt;&lt;br&gt;
Agents can stall or crash mid-task, and a lock held by a dead agent blocks everyone. Optimistic concurrency costs nothing when there's no conflict, which is almost always, and when there is one, the writer that knows what its change meant is the one asked to redo it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who can read a doc?&lt;/strong&gt;&lt;br&gt;
Every workspace in the account, plus the human. Comments and writes record the workspace that made them (a fork records its parent).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I self-host it?&lt;/strong&gt;&lt;br&gt;
Yes. AgentRQ is open source. File storage is local by default, or S3 with &lt;code&gt;AGENTRQ_PANO_STORAGE=s3&lt;/code&gt;, and &lt;code&gt;AGENTRQ_PANO_MAX_TTL_DAYS&lt;/code&gt; caps doc lifetime.&lt;/p&gt;




&lt;p&gt;How are you passing context between agents today: shared files, a vector store, or a human in the middle? We'd like to hear what's worked for you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://agentrq.com/blog/pano-shared-markdown-board-for-ai-agents-across-workspaces" rel="noopener noreferrer"&gt;AgentRQ blog&lt;/a&gt;. AgentRQ is an open-source, human-in-the-loop task manager for AI agents: &lt;a href="https://github.com/agentrq/agentrq" rel="noopener noreferrer"&gt;github.com/agentrq/agentrq&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>mcp</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Copilot YOLO mode, dissected: what --yolo, /yolo and Allow all actually skip</title>
      <dc:creator>Tony</dc:creator>
      <pubDate>Mon, 12 Oct 2026 18:02:40 +0000</pubDate>
      <link>https://dev.to/agentrq/copilot-yolo-mode-dissected-what-yolo-yolo-and-allow-all-actually-skip-4pbi</link>
      <guid>https://dev.to/agentrq/copilot-yolo-mode-dissected-what-yolo-yolo-and-allow-all-actually-skip-4pbi</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copilot CLI:&lt;/strong&gt; &lt;code&gt;copilot --yolo&lt;/code&gt; (same flag as &lt;code&gt;--allow-all&lt;/code&gt;), or &lt;code&gt;/yolo&lt;/code&gt; in a running session. It is shorthand for &lt;code&gt;--allow-all-tools&lt;/code&gt; + &lt;code&gt;--allow-all-paths&lt;/code&gt; + &lt;code&gt;--allow-all-urls&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code:&lt;/strong&gt; pick &lt;strong&gt;Allow all&lt;/strong&gt; in the chat permission picker, type &lt;code&gt;/yolo&lt;/code&gt;, or set &lt;code&gt;"chat.tools.global.autoApprove": true&lt;/code&gt; to make it permanent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it skips:&lt;/strong&gt; approval prompts. &lt;strong&gt;What it doesn't:&lt;/strong&gt; your &lt;code&gt;--deny-tool&lt;/code&gt; rules, and (in VS Code, explicitly documented) an enabled sandbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autopilot is a different switch.&lt;/strong&gt; It keeps the agent iterating; YOLO approves its tool calls. Unattended runs usually want both.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything here was checked on October 7, 2026 against GitHub's Copilot CLI reference, the github/copilot-cli changelog (1.0.93) and VS Code's agent docs in microsoft/vscode-docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does "YOLO" mean two different things in Copilot?
&lt;/h2&gt;

&lt;p&gt;Because Copilot ships two agent runtimes with two permission systems. The &lt;strong&gt;Copilot CLI&lt;/strong&gt; is a terminal agent with flag-driven permissions. &lt;strong&gt;Copilot Chat in VS Code&lt;/strong&gt; is an editor agent whose permissions hang off a picker and &lt;code&gt;settings.json&lt;/code&gt;. They share vocabulary (&lt;code&gt;/yolo&lt;/code&gt; exists in both) but not config. Nothing you set in VS Code changes the CLI, and vice versa.&lt;/p&gt;

&lt;p&gt;The one thing they agree on is the layering. There are three separate gates between the model and your machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model wants to act
   │
   ▼
[1] deny rules ─────────── always win, YOLO or not
   │
   ▼
[2] approval prompt ────── this is the only layer YOLO removes
   │
   ▼
[3] sandbox (if enabled) ─ still limits files + network
   │
   ▼
your shell / filesystem / network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep that picture in mind; every flag below is about layer 2.&lt;/p&gt;

&lt;h2&gt;
  
  
  What exactly does copilot --yolo turn on?
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;copilot &lt;span class="nt"&gt;--yolo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--yolo&lt;/code&gt; and &lt;code&gt;--allow-all&lt;/code&gt; are the same flag, documented as "Enable all permissions (tools, paths, and URLs)". It decomposes into three narrower switches you can use on their own:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;What stops asking&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--allow-all-tools&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;every tool call (GitHub notes this is required when you drive the CLI from a script)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--allow-all-paths&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the check on which file paths the agent may touch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--allow-all-urls&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;URL fetch approval&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The env var &lt;code&gt;COPILOT_ALLOW_ALL=true&lt;/code&gt; does the same as &lt;code&gt;--yolo&lt;/code&gt; &lt;strong&gt;and&lt;/strong&gt; trusts the current directory, which makes it the CI-friendly form: no flag plumbing through wrapper scripts.&lt;/p&gt;

&lt;p&gt;The nerdy bit worth noticing: paths and URLs are separate trust dimensions from tools. If your threat model is "the agent may run &lt;code&gt;npm test&lt;/code&gt; but must not read &lt;code&gt;~/.ssh&lt;/code&gt; or exfiltrate to random hosts", &lt;code&gt;--allow-all-tools&lt;/code&gt; alone is a materially different posture from &lt;code&gt;--yolo&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do the in-session commands map onto each other?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;/permissions&lt;/code&gt; is now the canonical command, with four arguments: &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;assisted&lt;/code&gt;, &lt;code&gt;allow-all&lt;/code&gt; and &lt;code&gt;show&lt;/code&gt;. Everything else is an alias:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/yolo&lt;/code&gt; and &lt;code&gt;/allow-all&lt;/code&gt; → &lt;code&gt;/permissions allow-all&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/yolo&lt;/code&gt; also takes &lt;code&gt;off&lt;/code&gt;, &lt;code&gt;auto&lt;/code&gt; and &lt;code&gt;show&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/reset-allowed-tools&lt;/code&gt; (or &lt;code&gt;/permissions default&lt;/code&gt;) undoes it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While it's on, the footer shows a &lt;strong&gt;YOLO&lt;/strong&gt; indicator, so you can't forget you're flying without a net.&lt;/p&gt;

&lt;p&gt;One gotcha for people coming from other agents: &lt;strong&gt;Shift+Tab does not toggle YOLO in the Copilot CLI.&lt;/strong&gt; It cycles standard → plan → autopilot. That's a mode-of-work switch, not a permission switch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why isn't Autopilot the same thing as YOLO?
&lt;/h2&gt;

&lt;p&gt;Two orthogonal axes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autopilot&lt;/strong&gt; (&lt;code&gt;--autopilot&lt;/code&gt;, &lt;code&gt;/autopilot&lt;/code&gt;, or Shift+Tab) answers "should the agent keep going without checking in with me?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YOLO&lt;/strong&gt; answers "should the agent run tools without asking me?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Autopilot without YOLO: the agent keeps working, then blocks on the first approval. YOLO without Autopilot: approvals fly through, but the agent stops to check in. An unattended run usually needs both. VS Code's security docs make the same point from the other side: Autopilot "combines auto-approval with autonomous iteration" and "reduces your ability to review intermediate steps".&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I get most of the speed without approving everything?
&lt;/h2&gt;

&lt;p&gt;Yes, and this is where Copilot's design is genuinely nice. Two halfway layers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern rules.&lt;/strong&gt; &lt;code&gt;--allow-tool&lt;/code&gt; and &lt;code&gt;--deny-tool&lt;/code&gt; take typed patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;copilot &lt;span class="nt"&gt;--allow-tool&lt;/span&gt; &lt;span class="s1"&gt;'shell(git:*)'&lt;/span&gt; &lt;span class="nt"&gt;--deny-tool&lt;/span&gt; &lt;span class="s1"&gt;'shell(git push)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other shapes: &lt;code&gt;write(src/*.ts)&lt;/code&gt;, &lt;code&gt;read(.env)&lt;/code&gt;, &lt;code&gt;url(github.com)&lt;/code&gt;, &lt;code&gt;MyMCP(create_issue)&lt;/code&gt;. The rule that matters: &lt;strong&gt;a deny always wins&lt;/strong&gt;, including over &lt;code&gt;--yolo&lt;/code&gt;. That gives you a cheap "YOLO minus the footguns" profile: &lt;code&gt;--yolo --deny-tool 'shell(git push)'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assisted permissions.&lt;/strong&gt; &lt;code&gt;/permissions assisted&lt;/code&gt; puts a safety model in front of the prompt. It approves routine requests and only escalates the rest to you. It's a classifier in layer 2, not a sandbox, so it reduces prompts without adding isolation.&lt;/p&gt;

&lt;p&gt;Admins get the last word: &lt;code&gt;"disableBypassPermissionsMode": "disable"&lt;/code&gt; under &lt;code&gt;permissions&lt;/code&gt; kills all of this, and &lt;code&gt;"allow-auto-only"&lt;/code&gt; restricts users to the assisted mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does VS Code's version work?
&lt;/h2&gt;

&lt;p&gt;Copilot Chat calls it &lt;strong&gt;Allow all&lt;/strong&gt;, one of three permission levels:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Manual&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;asks for each tool call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Assisted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;a model approves routine requests (needs &lt;code&gt;chat.assistedPermissions.enabled&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Allow all&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;asks for nothing; VS Code warns you the first time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three ways in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The permission picker in the chat input.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/yolo&lt;/code&gt; or &lt;code&gt;/autoApprove&lt;/code&gt; in chat, for the current session. Undo with &lt;code&gt;/disableYolo&lt;/code&gt; or &lt;code&gt;/disableAutoApprove&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Permanently, in &lt;code&gt;settings.json&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"chat.tools.global.autoApprove"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last one approves every tool in every workspace, and VS Code's own docs flag it as a setting that "disables critical security protections". The docs recommend the session-scoped Allow all when you don't need auto-approval everywhere. The experimental &lt;code&gt;chat.permissions.default&lt;/code&gt; (&lt;code&gt;default&lt;/code&gt;, &lt;code&gt;autoApprove&lt;/code&gt;, &lt;code&gt;autopilot&lt;/code&gt;) picks the level new chats start with, and orgs can block global auto-approve with the &lt;code&gt;ChatToolsAutoApprove&lt;/code&gt; policy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Are terminal allowlists enough to keep me safe?
&lt;/h2&gt;

&lt;p&gt;They're the VS Code halfway option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"chat.tools.terminal.autoApprove"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mkdir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"/^git (status|diff|log)\\b/"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keys are prefixes or regexes. &lt;code&gt;true&lt;/code&gt; auto-approves; &lt;code&gt;false&lt;/code&gt; forces a prompt even if another rule would approve. Note that &lt;code&gt;false&lt;/code&gt; means &lt;strong&gt;ask&lt;/strong&gt;, not &lt;strong&gt;block&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But read the fine print: VS Code's security docs say auto-approval rules "use best-effort command parsing and have known limitations with shell aliases, quote concatenation, and complex shell syntax". Anyone who has written a shell parser knows why: &lt;code&gt;g'it' push&lt;/code&gt;, an alias, or &lt;code&gt;bash -c "$(…)"&lt;/code&gt; can all slip past a prefix match. Treat allowlists as a convenience, and put the real boundary somewhere that enforces it at the OS level.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the sandbox actually enforce, and what doesn't YOLO touch?
&lt;/h2&gt;

&lt;p&gt;In VS Code, turn on &lt;code&gt;chat.agent.sandbox.enabled&lt;/code&gt; (or the &lt;strong&gt;Sandboxing for terminal&lt;/strong&gt; toggle in the picker). The docs are explicit that Allow all and Autopilot skip prompts "but an enabled sandbox still restricts terminal file system and network access". Under the hood VS Code's docs list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS:&lt;/strong&gt; Apple's Seatbelt, built in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux / WSL2:&lt;/strong&gt; bubblewrap for filesystem isolation plus &lt;code&gt;socat&lt;/code&gt; for network proxying (&lt;code&gt;apt-get install bubblewrap socat&lt;/code&gt;). WSL1 is out, because bubblewrap needs user namespaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two caveats from the same docs: outbound network stays &lt;strong&gt;on&lt;/strong&gt; by default (&lt;code&gt;chat.agent.sandbox.network.allowNetwork&lt;/code&gt; defaults to &lt;code&gt;true&lt;/code&gt;), so lock that down separately; and the sandbox is "not a virtual machine or user-account boundary". If you see the older key &lt;code&gt;chat.tools.terminal.sandbox.enabled&lt;/code&gt; in blog posts, it's no longer in VS Code's docs.&lt;/p&gt;

&lt;p&gt;The Copilot CLI has &lt;code&gt;/sandbox&lt;/code&gt; / &lt;code&gt;--sandbox&lt;/code&gt; too. GitHub's reference still marks it experimental while the changelog says it's available to everyone, and the CLI docs don't say whether &lt;code&gt;--yolo&lt;/code&gt; bypasses it. We treat it as a separate layer like VS Code's, but if you rely on it, check what &lt;code&gt;/sandbox&lt;/code&gt; reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can a cloned repo flip YOLO on for me?
&lt;/h2&gt;

&lt;p&gt;In VS Code, the front-line defense is Workspace Trust: an untrusted folder opens in restricted mode, which "also disables agents". So review a repo before you trust it, because trust is what unlocks agents in it at all. The global auto-approve setting is something you set yourself, and the docs steer you to the session-scoped level instead. The CLI has a notion of trusted directories too: &lt;code&gt;COPILOT_ALLOW_ALL=true&lt;/code&gt; trusts the current directory, and &lt;code&gt;/add-dir PATH&lt;/code&gt; grants file access to another directory and loads its &lt;code&gt;.github/skills&lt;/code&gt; and &lt;code&gt;.github/agents&lt;/code&gt; as trusted configuration. That's worth remembering before you point a YOLO session at a repo you haven't read.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I turn on YOLO per task or per workspace with AgentRQ?
&lt;/h2&gt;

&lt;p&gt;Copilot's YOLO is session-scoped: once on, it's on for everything that session does. If you'd rather decide &lt;strong&gt;per task&lt;/strong&gt;, and answer prompts from somewhere other than the terminal, you can route the Copilot CLI through &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt; via the &lt;a href="https://agentrq.com/docs/connect-acp-agent" rel="noopener noreferrer"&gt;ACP Gateway&lt;/a&gt; (&lt;a href="https://agentrq.com/docs/agents/github-copilot" rel="noopener noreferrer"&gt;Copilot setup guide&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @agentrq/acp-gateway@latest &lt;span class="nt"&gt;--agent&lt;/span&gt; github-copilot-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This covers the Copilot CLI only; Copilot Chat in VS Code keeps its own picker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start Copilot without &lt;code&gt;--yolo&lt;/code&gt;.&lt;/strong&gt; The gateway moves each new session out of any mode that would approve on its own and into one where Copilot asks a person. Every permission request then lands in the AgentRQ task (web, phone or Slack) with the command or edit attached, and you answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Allow Once&lt;/strong&gt;: this call only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always Allow&lt;/strong&gt;: adds the tool to the workspace's auto-approved list, so routine calls stop asking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deny&lt;/strong&gt;: Copilot gets a refusal and carries on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If nobody answers within 30 minutes, the gateway cancels the turn rather than guessing; tune that with &lt;code&gt;--permission-timeout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per task.&lt;/strong&gt; Flip the &lt;strong&gt;YOLO&lt;/strong&gt; toggle on a task, or set it when you create one, to put just that task in &lt;a href="https://agentrq.com/features/yolo-mode" rel="noopener noreferrer"&gt;YOLO mode&lt;/a&gt;. Every permission request in it is auto-approved and Copilot never waits, while every other task in the workspace still asks. The setting sticks to the task even if the agent disconnects and reconnects. Scheduled tasks, event triggers and workflow steps have the same switch, so the nightly job can run in YOLO while your interactive work stays supervised.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per workspace.&lt;/strong&gt; Workspace settings has &lt;strong&gt;YOLO Mode (Execute All)&lt;/strong&gt; (UI warning: "Agent will not ask for permission"). Under the hood it's a default, not a global override: the approval check reads the task's own YOLO flag, and the workspace switch decides what that flag starts as. New tasks you create in the web form open with the YOLO toggle already on (you can still switch it off per task), and tasks the agent creates for itself over the workspace MCP server inherit it. Flipping the switch doesn't rewrite tasks that already exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or let a model approve and deny for you, from plain-English rules.&lt;/strong&gt; Between "ask me every time" and "approve everything" there's a third option: an &lt;a href="https://github.com/agentrq/agentrq/blob/main/docs/EXTENSIONS.md" rel="noopener noreferrer"&gt;AgentRQ desktop extension&lt;/a&gt; that reviews each permission request before it reaches you. Extensions are trusted Node modules loaded by the AgentRQ desktop app. One registers a reviewer with &lt;code&gt;ctx.hooks.add({ id, review(request) { ... } })&lt;/code&gt; and is handed the pending call: the tool name, the argument preview the harness sent, and the workspace. It answers &lt;code&gt;{ behavior: 'deny', reason }&lt;/code&gt;, &lt;code&gt;{ behavior: 'allow' }&lt;/code&gt;, or nothing at all to abstain. Point &lt;code&gt;review()&lt;/code&gt; at an external decision API such as &lt;a href="https://agentrq.com/blog/jev-system-one-models" rel="noopener noreferrer"&gt;TypeSafe's Jev&lt;/a&gt;, a "System One" model that returns a typed &lt;code&gt;choice&lt;/code&gt; with calibrated &lt;code&gt;probabilities&lt;/code&gt; and a &lt;code&gt;confidence&lt;/code&gt; in milliseconds instead of generating text. Send the tool call as the state, and your workspace's rules in plain English ("git push is fine on feature branches, never on main", "never read anything under ~/.aws") as a Choice question over allow / deny / ask me. Then threshold it: approve only on a high-confidence allow, refuse on a confident deny, and abstain on everything else so the request lands on your phone as usual. The rules can live on a per-workspace settings tab the extension draws itself; the bundled &lt;code&gt;guardrail&lt;/code&gt; example does exactly that with literal patterns.&lt;/p&gt;

&lt;p&gt;The review contract is built on one asymmetry: refusing costs a tool call, approving costs whatever the tool call does. So one refusal settles a request; silence (an abstain, an exception, or a reviewer that misses its 5-second deadline) is never an allow, the request just stays in front of you; and an extension needs the &lt;code&gt;decide&lt;/code&gt; consent level to approve, while &lt;code&gt;deny&lt;/code&gt; consent can only refuse. The install screen starts every extension at &lt;code&gt;none&lt;/code&gt;. Reviews only happen while the desktop app is open and signed in, so treat this as a fast first pass, not a security boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trade-off.&lt;/strong&gt; Workspace-wide is one click and zero prompts, but it outlives the job you actually trusted: the next task inherits it whether you meant to or not. Per-task YOLO expires with the task. Our default is the workspace switch off, per-task YOLO for the jobs you've vetted, &lt;strong&gt;Always Allow&lt;/strong&gt; for the boring tools, the sandbox on, and a clean git tree before every YOLO run. The tool call history keeps a record of every call, including the auto-approved ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is &lt;code&gt;copilot --yolo&lt;/code&gt; the same as &lt;code&gt;--allow-all&lt;/code&gt;?&lt;/strong&gt; Yes. Same flag: tools, paths and URLs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does &lt;code&gt;--yolo&lt;/code&gt; override &lt;code&gt;--deny-tool&lt;/code&gt;?&lt;/strong&gt; No. A deny always wins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why doesn't Shift+Tab turn on YOLO in the CLI?&lt;/strong&gt; It cycles standard, plan and autopilot. Use &lt;code&gt;/yolo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I make Allow all permanent in VS Code?&lt;/strong&gt; &lt;code&gt;"chat.tools.global.autoApprove": true&lt;/code&gt;, though the session-scoped picker level is the safer habit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Allow all disable the VS Code sandbox?&lt;/strong&gt; No. An enabled sandbox still restricts terminal filesystem and network access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is Autopilot YOLO?&lt;/strong&gt; No. Autopilot keeps the agent going; YOLO approves its tool calls.&lt;/p&gt;

&lt;p&gt;For every other agent, see &lt;a href="https://agentrq.com/blog/what-is-yolo-mode-and-how-to-turn-it-on-in-every-coding-agent" rel="noopener noreferrer"&gt;what YOLO mode is and how to turn it on in every coding agent&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your turn:&lt;/strong&gt; do you run Copilot with &lt;code&gt;--yolo&lt;/code&gt; plus a couple of &lt;code&gt;--deny-tool&lt;/code&gt; guards, or do you trust the assisted classifier more than your own regexes? Tell me your setup in the comments.&lt;/p&gt;




&lt;p&gt;Originally published on &lt;a href="https://agentrq.com/guidelines/yolo-mode/github-copilot" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>githubcopilot</category>
      <category>vscode</category>
      <category>ai</category>
      <category>security</category>
    </item>
    <item>
      <title>Gemini CLI YOLO mode, read from the source: why settings.json can't turn it on</title>
      <dc:creator>Tony</dc:creator>
      <pubDate>Mon, 12 Oct 2026 18:01:40 +0000</pubDate>
      <link>https://dev.to/agentrq/gemini-cli-yolo-mode-read-from-the-source-why-settingsjson-cant-turn-it-on-2kma</link>
      <guid>https://dev.to/agentrq/gemini-cli-yolo-mode-read-from-the-source-why-settingsjson-cant-turn-it-on-2kma</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start YOLO with &lt;code&gt;gemini --approval-mode=yolo&lt;/code&gt;, or press &lt;strong&gt;Ctrl+Y&lt;/strong&gt; in a running session. &lt;code&gt;--yolo&lt;/code&gt; / &lt;code&gt;-y&lt;/code&gt; still work but are deprecated, and combining &lt;code&gt;--yolo&lt;/code&gt; with &lt;code&gt;--approval-mode&lt;/code&gt; is an error.&lt;/li&gt;
&lt;li&gt;You &lt;strong&gt;cannot&lt;/strong&gt; make YOLO the default in &lt;code&gt;settings.json&lt;/code&gt;. That's a deliberate design choice, and the code that enforces it is three lines long.&lt;/li&gt;
&lt;li&gt;YOLO only removes approval prompts. The sandbox (Seatbelt, Docker, Podman, gVisor, LXC) is a separate switch, and in the current source YOLO never turns it on.&lt;/li&gt;
&lt;li&gt;In an untrusted folder, any mode other than &lt;code&gt;default&lt;/code&gt; gets forced back to &lt;code&gt;default&lt;/code&gt;. If &lt;code&gt;security.disableYoloMode&lt;/code&gt; or admin secure mode is set, asking for YOLO is a fatal config error, not a silent downgrade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything below was checked against the Gemini CLI source (google-gemini/gemini-cli, &lt;code&gt;0.65.0-nightly.20261006&lt;/code&gt;) and its docs, on October 7–8, 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is this even for in late 2026?
&lt;/h2&gt;

&lt;p&gt;Short version: Gemini CLI users with a Gemini Code Assist &lt;strong&gt;Standard or Enterprise&lt;/strong&gt; license.&lt;/p&gt;

&lt;p&gt;Since June 18, 2026, Gemini CLI no longer serves Google AI Pro, Ultra or free Code Assist users. Google moved them to the Antigravity CLI (&lt;code&gt;agy&lt;/code&gt;), which has a different YOLO story (it's &lt;code&gt;agy --dangerously-skip-permissions&lt;/code&gt;, and there's no &lt;code&gt;--yolo&lt;/code&gt; at all). Gemini CLI is still developed, though, and the approval code is worth reading on its own. It's one of the cleaner permission designs among coding agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does Gemini CLI actually do with an approval mode?
&lt;/h2&gt;

&lt;p&gt;There are four modes: &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;auto_edit&lt;/code&gt;, &lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;yolo&lt;/code&gt;. Here's how the CLI picks one at startup, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;--approval-mode &amp;lt;x&amp;gt;&lt;/code&gt; on the command line&lt;/li&gt;
&lt;li&gt;else &lt;code&gt;--yolo&lt;/code&gt; / &lt;code&gt;-y&lt;/code&gt;, which maps to &lt;code&gt;yolo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;else &lt;code&gt;general.defaultApprovalMode&lt;/code&gt; from settings, &lt;strong&gt;unless its value is &lt;code&gt;yolo&lt;/code&gt;, in which case it's skipped&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;else &lt;code&gt;default&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 3 is the interesting one. The resolver doesn't reject a &lt;code&gt;"yolo"&lt;/code&gt; value in settings. It just reads past it, as if the key weren't there. The settings schema says it outright: YOLO "can only be enabled via command line".&lt;/p&gt;

&lt;p&gt;Two gates come after the mode is resolved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kill switch.&lt;/strong&gt; If &lt;code&gt;security.disableYoloMode&lt;/code&gt; or &lt;code&gt;admin.secureModeEnabled&lt;/code&gt; is set and the resolved mode is YOLO, startup throws a &lt;code&gt;FatalConfigError&lt;/code&gt;. It doesn't quietly drop you to &lt;code&gt;default&lt;/code&gt;. You asked for something that's banned, and the CLI tells you so.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Folder trust.&lt;/strong&gt; If the current folder isn't trusted, any mode other than &lt;code&gt;default&lt;/code&gt; gets forced back to &lt;code&gt;default&lt;/code&gt;, with a warning. This one applies to &lt;code&gt;auto_edit&lt;/code&gt; and &lt;code&gt;plan&lt;/code&gt; too, not just YOLO.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why can't I just put "yolo" in settings.json?
&lt;/h2&gt;

&lt;p&gt;The threat model is a cloned repo.&lt;/p&gt;

&lt;p&gt;Gemini CLI merges settings from several layers, and one of them is the workspace's own &lt;code&gt;.gemini/settings.json&lt;/code&gt;. If a project file could set &lt;code&gt;defaultApprovalMode: "yolo"&lt;/code&gt;, then &lt;code&gt;git clone evil-repo &amp;amp;&amp;amp; cd evil-repo &amp;amp;&amp;amp; gemini&lt;/code&gt; would hand an attacker-controlled &lt;code&gt;GEMINI.md&lt;/code&gt; an agent that never asks before running a shell command. Prompt injection plus auto-approval is the worst combination in agent security.&lt;/p&gt;

&lt;p&gt;So the rule is: YOLO has to come from a human typing a flag (or a key) in this process. Settings can make you &lt;strong&gt;more&lt;/strong&gt; cautious (&lt;code&gt;disableYoloMode&lt;/code&gt;, &lt;code&gt;secureModeEnabled&lt;/code&gt;, folder trust), but never less. If you want YOLO every time, the supported answer is a shell alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;gemini-yolo&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'gemini --approval-mode=yolo --sandbox'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that with Qwen Code, Gemini CLI's fork, which &lt;strong&gt;does&lt;/strong&gt; allow &lt;code&gt;tools.approvalMode: "yolo"&lt;/code&gt; in settings. It pushes the protection down to folder trust instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does YOLO turn the sandbox on?
&lt;/h2&gt;

&lt;p&gt;Not in the current code, whatever one older config page says.&lt;/p&gt;

&lt;p&gt;Gemini CLI has two independent layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What it gates&lt;/th&gt;
&lt;th&gt;Switch&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Approval mode&lt;/td&gt;
&lt;td&gt;Whether a human confirms each tool call&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--approval-mode&lt;/code&gt;, Ctrl+Y, Shift+Tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sandbox&lt;/td&gt;
&lt;td&gt;What a tool call can touch once it runs&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--sandbox&lt;/code&gt;, &lt;code&gt;GEMINI_SANDBOX&lt;/code&gt;, &lt;code&gt;tools.sandbox&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The sandbox resolver never reads the approval mode. With nothing set, it returns "no sandbox". Here's what you get when you turn it on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS, &lt;code&gt;sandbox: true&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;sandbox-exec&lt;/code&gt; (Seatbelt) is picked first. The default profile is &lt;code&gt;permissive-open&lt;/code&gt;. Despite the name, it starts from &lt;code&gt;(deny default)&lt;/code&gt;, allows file reads anywhere, and allows writes only to the project dir, temp, cache, &lt;code&gt;~/.npm&lt;/code&gt;, &lt;code&gt;~/.cache&lt;/code&gt; and any &lt;code&gt;--include-directories&lt;/code&gt;. It also explicitly blocks the Docker socket and writes to &lt;code&gt;~/.gemini&lt;/code&gt; credential files (&lt;code&gt;oauth_creds.json&lt;/code&gt;, &lt;code&gt;mcp-oauth-tokens.json&lt;/code&gt;, …). Pick another built-in profile with &lt;code&gt;SEATBELT_PROFILE&lt;/code&gt;: &lt;code&gt;permissive-*&lt;/code&gt; and &lt;code&gt;restrictive-*&lt;/code&gt; come in &lt;code&gt;-open&lt;/code&gt;, &lt;code&gt;-closed&lt;/code&gt; and &lt;code&gt;-proxied&lt;/code&gt; network flavors, and &lt;code&gt;strict-*&lt;/code&gt; in &lt;code&gt;-open&lt;/code&gt; and &lt;code&gt;-proxied&lt;/code&gt;. Anything not on that list is rejected, which also stops path traversal through the variable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux/other, &lt;code&gt;sandbox: true&lt;/code&gt;:&lt;/strong&gt; Docker, then Podman, whichever exists.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit only:&lt;/strong&gt; &lt;code&gt;runsc&lt;/code&gt; (gVisor, Linux only, run via Docker's &lt;code&gt;--runtime=runsc&lt;/code&gt;), &lt;code&gt;lxc&lt;/code&gt; (needs a container you already have running, so it's never auto-detected) and &lt;code&gt;windows-native&lt;/code&gt; (Windows only).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A wrong value fails fast. &lt;code&gt;GEMINI_SANDBOX=runsc&lt;/code&gt; on a Mac, or &lt;code&gt;true&lt;/code&gt; with neither Docker nor Podman installed, is a fatal error, not a silent run without a sandbox.&lt;/p&gt;

&lt;p&gt;The point: YOLO plus a sandbox is a reasonable setup. YOLO without one means "run anything with my user's full privileges". Pass &lt;code&gt;--sandbox&lt;/code&gt; yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do Ctrl+Y and Shift+Tab interact?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ctrl+Y&lt;/strong&gt; toggles between YOLO and &lt;code&gt;default&lt;/code&gt;. This is the only in-session way &lt;strong&gt;into&lt;/strong&gt; YOLO.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shift+Tab&lt;/strong&gt; cycles &lt;code&gt;default → auto_edit → plan&lt;/code&gt; (plan only if it's enabled). It never lands on YOLO. If you're in YOLO and press it, you drop to &lt;code&gt;auto_edit&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small design choice, sensible result: the key you hit all the time can't take you to the dangerous mode by accident.&lt;/p&gt;

&lt;p&gt;One more thing: &lt;code&gt;--yolo&lt;/code&gt; together with &lt;code&gt;--approval-mode&lt;/code&gt; doesn't pick a winner. It's a validation error. Ambiguous intent fails at the door.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens in CI and headless runs?
&lt;/h2&gt;

&lt;p&gt;This edge case trips people up. In non-interactive mode (&lt;code&gt;gemini -p "…"&lt;/code&gt;) there's nobody to answer a prompt, and the policy engine handles that by &lt;strong&gt;translating &lt;code&gt;ask_user&lt;/code&gt; decisions into &lt;code&gt;deny&lt;/code&gt;&lt;/strong&gt;. So in headless &lt;code&gt;default&lt;/code&gt; mode, a tool call that would have asked simply doesn't run.&lt;/p&gt;

&lt;p&gt;Belt and braces: the CLI also removes &lt;code&gt;ask_user&lt;/code&gt;, the tool the model uses to ask you a question, from the toolset in headless and ACP modes. The source comment says why: so that "it can never be allowed via a high-priority policy rule when no human is present". In ACP mode the IDE or client does the asking instead.&lt;/p&gt;

&lt;p&gt;So headless, your options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--approval-mode=yolo&lt;/code&gt;, ideally with &lt;code&gt;--sandbox&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--approval-mode=auto_edit&lt;/code&gt;, plus policy rules that allow the shell commands you need&lt;/li&gt;
&lt;li&gt;or a policy file that says &lt;code&gt;allow&lt;/code&gt; for exactly the tools the job uses&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are the halfway options?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;auto_edit&lt;/code&gt;&lt;/strong&gt; approves file edits and still asks before shell commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tools.allowed&lt;/code&gt;&lt;/strong&gt; lists tool patterns that skip the prompt, such as &lt;code&gt;run_shell_command(git)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The policy engine&lt;/strong&gt; is the recommended route: TOML files in &lt;code&gt;~/.gemini/policies/&lt;/code&gt; with &lt;code&gt;allow&lt;/code&gt; / &lt;code&gt;deny&lt;/code&gt; / &lt;code&gt;ask_user&lt;/code&gt; rules, which can be scoped to a mode (including YOLO). &lt;code&gt;--allowed-tools&lt;/code&gt; on the command line is deprecated in its favour.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the Gemini Code Assist extension in VS Code, set &lt;code&gt;"geminicodeassist.agentYoloMode": true&lt;/code&gt; in user settings and reload the window. Note the familiar rule again: it only works in a &lt;strong&gt;trusted&lt;/strong&gt; workspace. In IntelliJ, the matching option is &lt;strong&gt;Auto-approve changes&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I turn on YOLO per task or per workspace with AgentRQ?
&lt;/h2&gt;

&lt;p&gt;Gemini CLI's switch is per process: you either started with &lt;code&gt;--approval-mode=yolo&lt;/code&gt; or you didn't. &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt; moves that decision onto the task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Connect Gemini CLI.&lt;/strong&gt; It goes through the &lt;a href="https://agentrq.com/docs/connect-acp-agent" rel="noopener noreferrer"&gt;ACP Gateway&lt;/a&gt;. The &lt;a href="https://agentrq.com/docs/agents/gemini-cli" rel="noopener noreferrer"&gt;Gemini CLI setup guide&lt;/a&gt; and the &lt;a href="https://agentrq.com/blog/agentrq-acp-gateway-gemini-cli" rel="noopener noreferrer"&gt;step-by-step post&lt;/a&gt; have the details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @agentrq/acp-gateway@latest &lt;span class="nt"&gt;--agent&lt;/span&gt; gemini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start it &lt;strong&gt;without&lt;/strong&gt; &lt;code&gt;--approval-mode=yolo&lt;/code&gt;. The gateway also moves each new session out of any mode that would approve on its own and into one where Gemini CLI asks a person.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Answer from anywhere.&lt;/strong&gt; Each permission request shows up in the AgentRQ task, on the web, on your phone or in Slack, along with the command or edit it's asking about. You answer &lt;strong&gt;Allow Once&lt;/strong&gt;, &lt;strong&gt;Always Allow&lt;/strong&gt; (adds the tool to the workspace's auto-approved list) or &lt;strong&gt;Deny&lt;/strong&gt;. If nobody answers within 30 minutes, the gateway cancels the turn instead of guessing. &lt;code&gt;--permission-timeout&lt;/code&gt; changes that limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3a. YOLO for one task.&lt;/strong&gt; Flip the &lt;strong&gt;YOLO&lt;/strong&gt; toggle on a task, or when you create it. Every permission request in that task is approved automatically, while every other task in the workspace still asks. The flag lives on the task, so it persists across agent disconnects and reconnects. &lt;a href="https://agentrq.com/features/task-scheduling" rel="noopener noreferrer"&gt;Scheduled tasks&lt;/a&gt;, &lt;a href="https://agentrq.com/features/events" rel="noopener noreferrer"&gt;event triggers&lt;/a&gt; and &lt;a href="https://agentrq.com/features/workflows" rel="noopener noreferrer"&gt;workflow&lt;/a&gt; steps have the same switch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3b. YOLO for the whole workspace.&lt;/strong&gt; Workspace settings has &lt;strong&gt;YOLO Mode (Execute All)&lt;/strong&gt; (UI warning: "Agent will not ask for permission"). Under the hood it's a default, not a global override: the approval check reads the task's own YOLO flag, and the workspace switch decides what that flag starts as. New tasks you create in the web form open with the YOLO toggle already on (you can still switch it off per task), and tasks the agent creates for itself over the workspace MCP server inherit it. Flipping the switch doesn't rewrite tasks that already exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or let a model approve and deny for you, from plain-English rules.&lt;/strong&gt; Between "ask me every time" and "approve everything" there's a third option: an &lt;a href="https://github.com/agentrq/agentrq/blob/main/docs/EXTENSIONS.md" rel="noopener noreferrer"&gt;AgentRQ desktop extension&lt;/a&gt; that reviews each permission request before it reaches you. Extensions are trusted Node modules loaded by the AgentRQ desktop app. One registers a reviewer with &lt;code&gt;ctx.hooks.add({ id, review(request) { ... } })&lt;/code&gt; and is handed the pending call: the tool name, the argument preview the harness sent, and the workspace. It answers &lt;code&gt;{ behavior: 'deny', reason }&lt;/code&gt;, &lt;code&gt;{ behavior: 'allow' }&lt;/code&gt;, or nothing at all to abstain. Point &lt;code&gt;review()&lt;/code&gt; at an external decision API such as &lt;a href="https://agentrq.com/blog/jev-system-one-models" rel="noopener noreferrer"&gt;TypeSafe's Jev&lt;/a&gt;, a "System One" model that returns a typed &lt;code&gt;choice&lt;/code&gt; with calibrated &lt;code&gt;probabilities&lt;/code&gt; and a &lt;code&gt;confidence&lt;/code&gt; in milliseconds instead of generating text. Send the tool call as the state, and your workspace's rules in plain English ("git push is fine on feature branches, never on main", "never read anything under ~/.aws") as a Choice question over allow / deny / ask me. Then threshold it: approve only on a high-confidence allow, refuse on a confident deny, and abstain on everything else so the request lands on your phone as usual. The rules can live on a per-workspace settings tab the extension draws itself; the bundled &lt;code&gt;guardrail&lt;/code&gt; example does exactly that with literal patterns.&lt;/p&gt;

&lt;p&gt;The review contract is built on one asymmetry: refusing costs a tool call, approving costs whatever the tool call does. So one refusal settles a request; silence (an abstain, an exception, or a reviewer that misses its 5-second deadline) is never an allow, the request just stays in front of you; and an extension needs the &lt;code&gt;decide&lt;/code&gt; consent level to approve, while &lt;code&gt;deny&lt;/code&gt; consent can only refuse. The install screen starts every extension at &lt;code&gt;none&lt;/code&gt;. Reviews only happen while the desktop app is open and signed in, so treat this as a fast first pass, not a security boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trade-off.&lt;/strong&gt; Per-task YOLO is scoped trust: it ends when the job you vetted ends, and an unattended nightly job can run in YOLO while your interactive work stays supervised. Workspace-wide YOLO is easier, but it outlives any single decision you made, and every new task inherits it. The setup that holds up: leave the workspace switch off, use per-task YOLO, keep &lt;code&gt;GEMINI_SANDBOX=true&lt;/code&gt; (or &lt;code&gt;"tools": {"sandbox": true}&lt;/code&gt;) so the auto-approved commands still run in a container, start from a clean git tree, and read the &lt;a href="https://agentrq.com/features/tool-call-history" rel="noopener noreferrer"&gt;tool call history&lt;/a&gt; afterwards. More on the per-task model: &lt;a href="https://agentrq.com/features/yolo-mode" rel="noopener noreferrer"&gt;AgentRQ YOLO mode&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is &lt;code&gt;gemini --yolo&lt;/code&gt; still a thing?&lt;/strong&gt; It works, but it's deprecated. Use &lt;code&gt;--approval-mode=yolo&lt;/code&gt;, and don't pass both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I make YOLO the default in settings.json?&lt;/strong&gt; No. The resolver skips &lt;code&gt;"yolo"&lt;/code&gt; in &lt;code&gt;defaultApprovalMode&lt;/code&gt;. Use a shell alias.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does Ctrl+Y do?&lt;/strong&gt; It toggles YOLO ↔ default in the running session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does YOLO enable the sandbox?&lt;/strong&gt; Not in the current source. Add &lt;code&gt;--sandbox&lt;/code&gt; or set &lt;code&gt;GEMINI_SANDBOX&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does Gemini CLI refuse to start with &lt;code&gt;--yolo&lt;/code&gt;?&lt;/strong&gt; &lt;code&gt;security.disableYoloMode&lt;/code&gt; or &lt;code&gt;admin.secureModeEnabled&lt;/code&gt; is set. That's a fatal error by design. If it starts but drops you to &lt;code&gt;default&lt;/code&gt;, the folder isn't trusted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do my tool calls silently not run in &lt;code&gt;gemini -p&lt;/code&gt;?&lt;/strong&gt; Headless mode turns "ask" into "deny". Use YOLO (with a sandbox), &lt;code&gt;auto_edit&lt;/code&gt;, or allow rules in a policy file.&lt;/p&gt;

&lt;p&gt;For every other agent, see &lt;a href="https://agentrq.com/blog/what-is-yolo-mode-and-how-to-turn-it-on-in-every-coding-agent" rel="noopener noreferrer"&gt;what YOLO mode is and how to turn it on in every coding agent&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Over to you: do you think "YOLO only from a flag, never from settings" is the right call, or should a tool trust your user-level config the way Qwen Code does? And if you run Gemini CLI in CI, which sandbox backend did you end up on? 👇&lt;/p&gt;

&lt;p&gt;Originally published on &lt;a href="https://agentrq.com/guidelines/yolo-mode/gemini-cli" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>cli</category>
      <category>gemini</category>
    </item>
    <item>
      <title>How to Enable Claude Code Channels for Team and Enterprise Plans (Step by Step)</title>
      <dc:creator>Mustafa Turan</dc:creator>
      <pubDate>Sat, 10 Oct 2026 19:18:49 +0000</pubDate>
      <link>https://dev.to/agentrq/how-to-enable-claude-code-channels-for-team-and-enterprise-plans-step-by-step-54a8</link>
      <guid>https://dev.to/agentrq/how-to-enable-claude-code-channels-for-team-and-enterprise-plans-step-by-step-54a8</guid>
      <description>&lt;p&gt;You connected Claude Code to a channel, maybe &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt;, a Telegram bot or a Discord bot, and sent it a message from your phone. Nothing happened. Claude Code started, the MCP server connected and its tools work, but the message never showed up in the session. A startup warning says to ask your admin.&lt;/p&gt;

&lt;p&gt;If you are on a &lt;strong&gt;claude.ai Team or Enterprise plan&lt;/strong&gt;, that is expected. Channels ship switched &lt;strong&gt;off&lt;/strong&gt; for organizations, and one person has to flip a switch before anyone can use them.&lt;/p&gt;

&lt;p&gt;This guide walks through that switch screen by screen, then covers the managed-settings route and how to limit which channel plugins your team can run.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code Channels are a research preview, and they are &lt;strong&gt;blocked by default on claude.ai Team and Enterprise&lt;/strong&gt; plans.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Owner&lt;/strong&gt; enables them at &lt;strong&gt;Organization settings → Claude Code → Channels&lt;/strong&gt; (&lt;a href="https://claude.ai/admin-settings/claude-code" rel="noopener noreferrer"&gt;claude.ai/admin-settings/claude-code&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;The alternative is to set &lt;code&gt;channelsEnabled: true&lt;/code&gt; in managed settings. Add &lt;code&gt;allowedChannelPlugins&lt;/code&gt; to pick which plugins can register.&lt;/li&gt;
&lt;li&gt;Once Channels are on, each developer still chooses channels per session. Step 4 shows how to set up AgentRQ, Telegram and Discord.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are Claude Code Channels, and why are they off for my org?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;channel&lt;/strong&gt; is an MCP server that &lt;strong&gt;pushes&lt;/strong&gt; events into a Claude Code session that is already running. Ordinary MCP tools only respond when Claude calls them. A channel can deliver a new task, a reply to a question the agent asked you, a CI failure or a monitoring alert into the session while you are away from the terminal. Claude reads the event, does the work against your real files and can reply through the same channel.&lt;/p&gt;

&lt;p&gt;That makes a channel an inbound path into a developer's machine, and Anthropic leaves it to organization admins to decide whether to allow it. The defaults depend on how you sign in:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Account type&lt;/th&gt;
&lt;th&gt;Channels by default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pro / Max (no organization)&lt;/td&gt;
&lt;td&gt;Available, opt in per session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude.ai &lt;strong&gt;Team / Enterprise&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Blocked until an Owner enables them&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Console (API key)&lt;/td&gt;
&lt;td&gt;Allowed, unless your org deploys managed settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bedrock / Google Cloud / Foundry&lt;/td&gt;
&lt;td&gt;Not available&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You also need Claude Code &lt;strong&gt;v2.1.80 or later&lt;/strong&gt;. The official channel plugins (Telegram, Discord, iMessage and the fakechat demo) need &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who can enable Channels?
&lt;/h2&gt;

&lt;p&gt;Only a user with the &lt;strong&gt;Owner&lt;/strong&gt; role on the claude.ai organization. Admins without the Owner role, and regular members, will not be able to change the toggle. If that isn't you, send this post to your Owner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Open Organization settings
&lt;/h2&gt;

&lt;p&gt;Sign in to &lt;a href="https://claude.ai" rel="noopener noreferrer"&gt;claude.ai&lt;/a&gt; with your Team or Enterprise account. Click your name in the &lt;strong&gt;bottom-left corner&lt;/strong&gt; to open the account menu, make sure your organization (not your personal account) is selected at the top, and choose &lt;strong&gt;Organization settings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F413pxzc22eddqjffmbgm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F413pxzc22eddqjffmbgm.png" alt="The claude.ai account menu open in the bottom-left corner, with Organization settings highlighted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Go to Products → Claude Code and find Channels
&lt;/h2&gt;

&lt;p&gt;In the left sidebar of Organization settings, scroll to the &lt;strong&gt;Products&lt;/strong&gt; group and click &lt;strong&gt;Claude Code&lt;/strong&gt; (1).&lt;/p&gt;

&lt;p&gt;The Claude Code page is long. The quickest way to the setting is your browser's find bar: press &lt;code&gt;Cmd+F&lt;/code&gt; on macOS or &lt;code&gt;Ctrl+F&lt;/code&gt; on Windows and Linux, and type &lt;code&gt;channels&lt;/code&gt; (2). It sits in the &lt;strong&gt;Capabilities&lt;/strong&gt; section, below Dynamic workflows.&lt;/p&gt;

&lt;p&gt;Turn on the &lt;strong&gt;Channels&lt;/strong&gt; toggle (3). It carries a &lt;strong&gt;Preview&lt;/strong&gt; badge, and its description reads: "Allow your team to receive inbound messages from MCP servers in Claude Code sessions."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fepszshustshzvzxc7u7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fepszshustshzvzxc7u7c.png" alt="Organization settings, Claude Code page: (1) Products → Claude Code in the sidebar, (2) the browser find bar searching for channels, (3) the Channels Preview toggle switched on"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can skip the menu clicks by opening the page directly: &lt;a href="https://claude.ai/admin-settings/claude-code" rel="noopener noreferrer"&gt;claude.ai/admin-settings/claude-code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Confirm it says "Set by admin"
&lt;/h2&gt;

&lt;p&gt;Once the toggle is on, the label next to it changes from &lt;strong&gt;Default&lt;/strong&gt; to &lt;strong&gt;Set by admin&lt;/strong&gt;. That label shows the setting is now enforced for the whole organization, and members cannot override it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fij9oou9xpe7fwje0e9cg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fij9oou9xpe7fwje0e9cg.png" alt="The Channels Preview setting switched on, labelled Set by admin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the whole admin side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Connect a channel (AgentRQ, Telegram or Discord)
&lt;/h2&gt;

&lt;p&gt;Turning the setting on doesn't start anything. Each developer still picks which channel servers their session will trust. Below are three common setups: AgentRQ, plus Anthropic's official Telegram and Discord plugins. Pick one, or run several at once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: AgentRQ
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt; lets you assign tasks, answer the agent's questions and approve its actions from your phone or desktop while Claude Code keeps running on your machine. You don't run a bot or a server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create a workspace.&lt;/strong&gt; Sign in at &lt;a href="https://app.agentrq.com" rel="noopener noreferrer"&gt;app.agentrq.com&lt;/a&gt;, create a workspace for your project and click &lt;strong&gt;Generate MCP Token&lt;/strong&gt;. The token is shown only once, so copy it. Note the workspace ID too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Add the server to &lt;code&gt;.mcp.json&lt;/code&gt;&lt;/strong&gt; in the project root, where you run &lt;code&gt;claude&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agentrq-WORKSPACE_ID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://WORKSPACE_ID.mcp.agentrq.com/mcp?token=YOUR_MCP_TOKEN"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server key has to include your workspace ID, because the next command refers to the server by that name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Start Claude Code with the server as a channel:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--dangerously-load-development-channels&lt;/span&gt; server:agentrq-WORKSPACE_ID &lt;span class="nt"&gt;--name&lt;/span&gt; my-api-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A server in &lt;code&gt;.mcp.json&lt;/code&gt; alone gives Claude the AgentRQ tools, but it can't push anything into the session. New tasks and your replies only arrive as they happen when the server is also named as a channel.&lt;/p&gt;

&lt;p&gt;AgentRQ is a custom channel. During the research preview, only the plugins on Anthropic's allowlist load through &lt;code&gt;--channels&lt;/code&gt;, so a custom channel like this one loads through &lt;code&gt;--dangerously-load-development-channels&lt;/code&gt;. That flag skips the plugin allowlist after a confirmation prompt. &lt;strong&gt;It does not get around an organization that has Channels turned off&lt;/strong&gt;, which is why the Owner toggle above comes first. &lt;code&gt;--name&lt;/code&gt; just labels the session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Send it work.&lt;/strong&gt; Create a task in the AgentRQ app. It arrives in the running session as a &lt;code&gt;&amp;lt;channel&amp;gt;&lt;/code&gt; event, Claude starts on it, and its progress updates and questions come back to the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option B: Telegram
&lt;/h3&gt;

&lt;p&gt;The official plugins run on &lt;a href="https://bun.sh" rel="noopener noreferrer"&gt;Bun&lt;/a&gt;, so install that first.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In Telegram, open &lt;a href="https://t.me/BotFather" rel="noopener noreferrer"&gt;@BotFather&lt;/a&gt;, send &lt;code&gt;/newbot&lt;/code&gt;, choose a name and a username ending in &lt;code&gt;bot&lt;/code&gt;, and copy the token it returns.&lt;/li&gt;
&lt;li&gt;Install the plugin and save the token. Run these inside Claude Code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin install telegram@claude-plugins-official
/telegram:configure &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Exit Claude Code and restart it with the channel:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--channels&lt;/span&gt; plugin:telegram@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Send any message to your bot. It replies with a pairing code. Approve the code and lock access to your account:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/telegram:access pair &amp;lt;code&amp;gt;
/telegram:access policy allowlist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option C: Discord
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;a href="https://discord.com/developers/applications" rel="noopener noreferrer"&gt;Discord Developer Portal&lt;/a&gt;, create an application. In the &lt;strong&gt;Bot&lt;/strong&gt; section, click &lt;strong&gt;Reset Token&lt;/strong&gt; and copy it. Under &lt;strong&gt;Privileged Gateway Intents&lt;/strong&gt;, turn on &lt;strong&gt;Message Content Intent&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;OAuth2 → URL Generator&lt;/strong&gt;, select the &lt;code&gt;bot&lt;/code&gt; scope with these permissions: View Channels, Send Messages, Send Messages in Threads, Read Message History, Attach Files and Add Reactions. Open the generated URL to add the bot to your server.&lt;/li&gt;
&lt;li&gt;Install the plugin, save the token, then restart with the channel:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin install discord@claude-plugins-official
/discord:configure &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--channels&lt;/span&gt; plugin:discord@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Send the bot a DM. It replies with a pairing code. Approve it and lock access:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/discord:access pair &amp;lt;code&amp;gt;
/discord:access policy allowlist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To run more than one channel in a session, list them all. &lt;code&gt;--channels&lt;/code&gt; takes several plugins separated by spaces, and you can use it together with &lt;code&gt;--dangerously-load-development-channels&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--channels&lt;/span&gt; plugin:telegram@claude-plugins-official plugin:discord@claude-plugins-official &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dangerously-load-development-channels&lt;/span&gt; server:agentrq-WORKSPACE_ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neither flag shows up in &lt;code&gt;claude --help&lt;/code&gt; while Channels are in preview, but both work. If the org setting is still off, every server connects and its tools work, but no channel messages arrive, and a startup warning tells the user to ask an admin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I enable Channels with managed settings instead?
&lt;/h2&gt;

&lt;p&gt;Yes. If you already roll out Claude Code &lt;a href="https://code.claude.com/docs/en/settings" rel="noopener noreferrer"&gt;managed settings&lt;/a&gt;, set the master switch there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"channelsEnabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the same switch as the toggle above, and users cannot override it. Console organizations that deploy managed settings need this key too, because deploying managed settings blocks Channels until it is set.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I restrict which channel plugins can run?
&lt;/h2&gt;

&lt;p&gt;By default, any plugin on Anthropic's channel allowlist can register, which means the ones in &lt;a href="https://github.com/anthropics/claude-plugins-official/tree/main/external_plugins" rel="noopener noreferrer"&gt;claude-plugins-official&lt;/a&gt;. On Team and Enterprise you can &lt;strong&gt;replace&lt;/strong&gt; that list with &lt;code&gt;allowedChannelPlugins&lt;/code&gt;. Each entry names a plugin and the marketplace it comes from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"channelsEnabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"allowedChannelPlugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"marketplace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-plugins-official"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"telegram"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"marketplace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-plugins-official"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"discord"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"marketplace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"acme-corp-plugins"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"internal-alerts"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few rules worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;allowedChannelPlugins&lt;/code&gt; only applies when &lt;code&gt;channelsEnabled&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If a plugin isn't on your list, Claude Code still starts, but the channel doesn't register. The startup notice says the plugin is not on the organization's approved list.&lt;/li&gt;
&lt;li&gt;Each entry has to match the &lt;strong&gt;plugin name&lt;/strong&gt; as well as the marketplace.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;empty array&lt;/strong&gt; blocks every allowlisted plugin. Servers loaded with &lt;code&gt;--dangerously-load-development-channels&lt;/code&gt;, such as AgentRQ, can still run. To shut Channels off completely, development flag included, leave &lt;code&gt;channelsEnabled&lt;/code&gt; unset.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What should admins think about before turning it on?
&lt;/h2&gt;

&lt;p&gt;Channels are useful because they let outside events reach a session, and that is also the part to plan for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Who can reach the session.&lt;/strong&gt; Telegram and Discord keep a sender allowlist that you fill by pairing, and messages from anyone else are dropped silently. Always finish with &lt;code&gt;access policy allowlist&lt;/code&gt;. With AgentRQ, the workspace MCP token is the key. Anyone with the token can connect to the workspace, so keep &lt;code&gt;.mcp.json&lt;/code&gt; out of public repos and generate a new token if one leaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who can approve actions.&lt;/strong&gt; If a channel relays permission prompts, anyone who can answer through it can approve or deny tool use in that session. Only give that access to people you would trust at the keyboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unattended sessions.&lt;/strong&gt; People who pair Channels with &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; should do it only in environments they trust.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I need to restart Claude Code after the admin enables Channels?&lt;/strong&gt;&lt;br&gt;
Yes. The setting is checked when a session starts. Exit and relaunch with the channel flag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The MCP server connects and its tools work, so why don't messages arrive?&lt;/strong&gt;&lt;br&gt;
That is the exact symptom of Channels being off at the org level. The server still connects, but channel messages are dropped. Check the startup warning, then ask your Owner to check &lt;strong&gt;Organization settings → Claude Code → Channels&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'm an Admin but the toggle doesn't change.&lt;/strong&gt;&lt;br&gt;
Enabling Channels requires the &lt;strong&gt;Owner&lt;/strong&gt; role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does enabling Channels connect everyone to AgentRQ, Telegram or Discord automatically?&lt;/strong&gt;&lt;br&gt;
No. It only allows Channels. Each developer still sets up a channel and names it with &lt;code&gt;--channels&lt;/code&gt; or &lt;code&gt;--dangerously-load-development-channels&lt;/code&gt; when they start a session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are Channels available on Bedrock, Google Cloud or Microsoft Foundry?&lt;/strong&gt;&lt;br&gt;
No. They need Anthropic authentication, either a claude.ai login or a Console API key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is this stable?&lt;/strong&gt;&lt;br&gt;
Channels are still a &lt;strong&gt;research preview&lt;/strong&gt;. Anthropic says the flag syntax and the protocol may change, so check the &lt;a href="https://code.claude.com/docs/en/channels#enable-channels-for-your-organization" rel="noopener noreferrer"&gt;official Channels docs&lt;/a&gt; before you script it.&lt;/p&gt;




&lt;p&gt;Has your team turned Channels on yet? What's the first thing you'd hand to an agent you can reach from your phone? Tell us in the comments.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>mcp</category>
      <category>devops</category>
    </item>
    <item>
      <title>Codex CLI YOLO mode: two knobs, one flag, and why --yolo also kills the sandbox</title>
      <dc:creator>Tony</dc:creator>
      <pubDate>Sat, 10 Oct 2026 15:30:53 +0000</pubDate>
      <link>https://dev.to/agentrq/codex-cli-yolo-mode-two-knobs-one-flag-and-why-yolo-also-kills-the-sandbox-13ja</link>
      <guid>https://dev.to/agentrq/codex-cli-yolo-mode-two-knobs-one-flag-and-why-yolo-also-kills-the-sandbox-13ja</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;codex --yolo&lt;/code&gt; is a short alias of &lt;code&gt;--dangerously-bypass-approvals-and-sandbox&lt;/code&gt;. It sets &lt;strong&gt;approvals to &lt;code&gt;never&lt;/code&gt;&lt;/strong&gt; &lt;em&gt;and&lt;/em&gt; &lt;strong&gt;the sandbox to &lt;code&gt;danger-full-access&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;That second part is unusual. Claude Code's and Gemini CLI's YOLO modes skip prompts but leave sandboxing alone. Codex's removes both.&lt;/li&gt;
&lt;li&gt;The two knobs are orthogonal: &lt;code&gt;-a never -s workspace-write&lt;/code&gt; gives you "never ask, but stay fenced", which is what most people actually want.&lt;/li&gt;
&lt;li&gt;The sandbox is real OS isolation: &lt;strong&gt;Seatbelt&lt;/strong&gt; (&lt;code&gt;sandbox-exec&lt;/code&gt;) on macOS, &lt;strong&gt;bubblewrap + seccomp&lt;/strong&gt; on Linux/WSL2, a native sandbox on Windows, and &lt;strong&gt;nothing&lt;/strong&gt; on WSL1.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;codex exec&lt;/code&gt; never asks for approval, so in CI the sandbox is the &lt;em&gt;only&lt;/em&gt; knob that matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every flag below was checked against openai/codex at commit 72c9595 (release 0.161.0), &lt;code&gt;@agentclientprotocol/codex-acp&lt;/code&gt; 2.1.1 and OpenAI's Codex docs on October 7, 2026.&lt;/p&gt;




&lt;h2&gt;
  
  
  What are the two knobs?
&lt;/h2&gt;

&lt;p&gt;Codex models safety as two independent dimensions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Knob&lt;/th&gt;
&lt;th&gt;Config key&lt;/th&gt;
&lt;th&gt;CLI flag&lt;/th&gt;
&lt;th&gt;Values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;When to ask you&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;approval_policy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-a&lt;/code&gt; / &lt;code&gt;--ask-for-approval&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;on-request&lt;/code&gt; (default), &lt;code&gt;never&lt;/code&gt;, or a &lt;code&gt;granular&lt;/code&gt; table&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What a command can reach&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sandbox_mode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;-s&lt;/code&gt; / &lt;code&gt;--sandbox&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;read-only&lt;/code&gt;, &lt;code&gt;workspace-write&lt;/code&gt;, &lt;code&gt;danger-full-access&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;on-request&lt;/code&gt; means the model may stop and ask whenever it wants to do something the sandbox would block. The sandbox then decides, at the OS level, which files are writable and whether there's network.&lt;/p&gt;

&lt;p&gt;Because the knobs are independent, you get a 2×3 grid of behaviours. The interesting cells:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex &lt;span class="nt"&gt;-a&lt;/span&gt; never &lt;span class="nt"&gt;-s&lt;/span&gt; danger-full-access   &lt;span class="c"&gt;# == codex --yolo&lt;/span&gt;
codex &lt;span class="nt"&gt;-a&lt;/span&gt; never &lt;span class="nt"&gt;-s&lt;/span&gt; workspace-write      &lt;span class="c"&gt;# never asks, still fenced&lt;/span&gt;
codex &lt;span class="nt"&gt;-a&lt;/span&gt; on-request &lt;span class="nt"&gt;-s&lt;/span&gt; danger-full-access  &lt;span class="c"&gt;# no fence, may still ask (rarely does)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The middle one has a lovely failure mode: when a command needs more than the sandbox allows, it simply &lt;strong&gt;fails&lt;/strong&gt;, and the error goes back to the model to work around. No human in the loop, but no escape either.&lt;/p&gt;

&lt;p&gt;On the CLI, &lt;code&gt;-a&lt;/code&gt; only accepts &lt;code&gt;on-request&lt;/code&gt; and &lt;code&gt;never&lt;/code&gt;. Combining flags that both set a knob is rejected: &lt;code&gt;--yolo&lt;/code&gt; can't be combined with &lt;code&gt;-a&lt;/code&gt;, and &lt;code&gt;--approve-for-me&lt;/code&gt; can't be combined with &lt;code&gt;-a&lt;/code&gt;, &lt;code&gt;-s&lt;/code&gt; or &lt;code&gt;--yolo&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does Codex's YOLO also drop the sandbox?
&lt;/h2&gt;

&lt;p&gt;Because the flag's own help text says it's meant for environments that are &lt;strong&gt;already sandboxed from the outside&lt;/strong&gt; (it calls itself "EXTREMELY DANGEROUS"). The design assumption is: if you're telling Codex "never ask", you're probably in a container, VM or CI runner where an inner sandbox is just friction. That assumption is great in CI and terrible on your laptop.&lt;/p&gt;

&lt;p&gt;Here's what &lt;code&gt;danger-full-access&lt;/code&gt; actually means. Not "the project". Everything &lt;strong&gt;your user account&lt;/strong&gt; can reach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every file you can read or write: &lt;code&gt;~/.ssh&lt;/code&gt;, &lt;code&gt;~/.aws&lt;/code&gt;, &lt;code&gt;~/.config/gcloud&lt;/code&gt;, browser profiles, other repos, dotfiles.&lt;/li&gt;
&lt;li&gt;Unrestricted network: download-and-run, call APIs with any token it finds, exfiltrate anything.&lt;/li&gt;
&lt;li&gt;Your git identity: &lt;code&gt;.git&lt;/code&gt; is no longer protected, so history rewrites and &lt;code&gt;git push --force&lt;/code&gt; go out as you.&lt;/li&gt;
&lt;li&gt;Every exported env var in the shell that started Codex.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now add prompt injection. A malicious instruction in a README, an issue, or a fetched web page can steer the model, and with YOLO on nothing pauses to ask you.&lt;/p&gt;

&lt;h2&gt;
  
  
  How is the sandbox actually built?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;Seatbelt via &lt;code&gt;sandbox-exec&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Built into the OS, nothing to install&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;bubblewrap + a seccomp network filter&lt;/td&gt;
&lt;td&gt;Uses &lt;code&gt;bwrap&lt;/code&gt; from &lt;code&gt;PATH&lt;/code&gt; or a bundled copy. The old Landlock backend is legacy and refused for filesystem-restricted policies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WSL2&lt;/td&gt;
&lt;td&gt;Same as Linux&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WSL1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;None&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;WSL1 can't create the user namespaces bubblewrap needs, so Codex refuses sandboxed commands&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native Windows&lt;/td&gt;
&lt;td&gt;Codex's own sandbox&lt;/td&gt;
&lt;td&gt;Unelevated and elevated variants; &lt;code&gt;/setup-default-sandbox&lt;/code&gt; sets up the elevated one&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Linux one is the gotcha. bubblewrap needs &lt;strong&gt;unprivileged user namespaces&lt;/strong&gt;. Inside an unprivileged container they're often unavailable, you get a startup warning, and the sandbox can't start. That's the one situation where running &lt;code&gt;--yolo&lt;/code&gt; inside a container is the normal setup rather than a shortcut: the container &lt;em&gt;is&lt;/em&gt; the sandbox.&lt;/p&gt;

&lt;p&gt;Even in &lt;code&gt;workspace-write&lt;/code&gt;, Codex keeps &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;.codex&lt;/code&gt; and &lt;code&gt;.agents&lt;/code&gt; &lt;strong&gt;read-only&lt;/strong&gt;, so it can't rewrite history or its own config without asking. That's a neat detail: the agent's own control plane is outside its write fence.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I get most of YOLO without dropping the fence?
&lt;/h2&gt;

&lt;p&gt;Most YOLO cravings come from two &lt;code&gt;workspace-write&lt;/code&gt; limits: no network, and no writes outside the project. Open them individually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;sandbox_mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"workspace-write"&lt;/span&gt;
&lt;span class="py"&gt;approval_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"never"&lt;/span&gt;

&lt;span class="nn"&gt;[sandbox_workspace_write]&lt;/span&gt;
&lt;span class="py"&gt;network_access&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;writable_roots&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"/Users/me/.cache/pip"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;network_access&lt;/code&gt; makes &lt;code&gt;npm install&lt;/code&gt;/&lt;code&gt;pip install&lt;/code&gt; work. &lt;code&gt;writable_roots&lt;/code&gt; (or &lt;code&gt;--add-dir &amp;lt;DIR&amp;gt;&lt;/code&gt; per run) adds folders. &lt;code&gt;exclude_tmpdir_env_var&lt;/code&gt; and &lt;code&gt;exclude_slash_tmp&lt;/code&gt; remove &lt;code&gt;$TMPDIR&lt;/code&gt; and &lt;code&gt;/tmp&lt;/code&gt; from the writable set if you want it tighter.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does config precedence work, and where does project trust fit?
&lt;/h2&gt;

&lt;p&gt;Codex reads &lt;code&gt;~/.codex/config.toml&lt;/code&gt; (or &lt;code&gt;$CODEX_HOME/config.toml&lt;/code&gt;). The YOLO default is just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;approval_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"never"&lt;/span&gt;
&lt;span class="py"&gt;sandbox_mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"danger-full-access"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few precedence rules worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-c key=value&lt;/code&gt;&lt;/strong&gt; overrides any key for one run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission profiles&lt;/strong&gt;: &lt;code&gt;default_permissions = ":danger-full-access"&lt;/code&gt; (also &lt;code&gt;:workspace&lt;/code&gt;, &lt;code&gt;:read-only&lt;/code&gt;) is the newer form, and &lt;strong&gt;wins over &lt;code&gt;sandbox_mode&lt;/code&gt;&lt;/strong&gt; when set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Profiles&lt;/strong&gt;: &lt;code&gt;codex -p yolo&lt;/code&gt; layers &lt;code&gt;~/.codex/yolo.config.toml&lt;/code&gt; on top of your normal config. Keeping YOLO in a profile means it's opt-in per launch. (Old &lt;code&gt;[profiles.yolo]&lt;/code&gt; tables still load, but &lt;code&gt;-p&lt;/code&gt; now means the separate file.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed &lt;code&gt;requirements.toml&lt;/code&gt;&lt;/strong&gt;: an admin can forbid &lt;code&gt;never&lt;/code&gt; or &lt;code&gt;danger-full-access&lt;/code&gt;, and Codex falls back to the allowed default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retired value&lt;/strong&gt;: &lt;code&gt;approval_policy = "untrusted"&lt;/code&gt; is now a hard error at startup. &lt;code&gt;on-failure&lt;/code&gt; is still accepted as another name for &lt;code&gt;on-request&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project trust&lt;/strong&gt; is how Codex handles the "random cloned repo" problem. The first time you open a folder, Codex asks whether you trust it and records &lt;code&gt;trust_level = "trusted"&lt;/code&gt; under &lt;code&gt;[projects."/path"]&lt;/code&gt; in &lt;em&gt;your&lt;/em&gt; config. A trusted, version-controlled project starts in &lt;code&gt;workspace-write&lt;/code&gt; + &lt;code&gt;on-request&lt;/code&gt;; anything untrusted or not under version control starts &lt;strong&gt;read-only&lt;/strong&gt;. Trust only sets the &lt;em&gt;default&lt;/em&gt;: an explicit &lt;code&gt;--yolo&lt;/code&gt; or config key still wins. The point is that the decision lives in your home directory, not in the repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does the in-session switch work?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;/permissions&lt;/code&gt; opens a picker with three presets:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Preset&lt;/th&gt;
&lt;th&gt;Approvals&lt;/th&gt;
&lt;th&gt;Sandbox&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read Only&lt;/td&gt;
&lt;td&gt;on-request&lt;/td&gt;
&lt;td&gt;&lt;code&gt;read-only&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;on-request&lt;/td&gt;
&lt;td&gt;&lt;code&gt;workspace-write&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full Access&lt;/td&gt;
&lt;td&gt;never&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;danger-full-access&lt;/code&gt; (the YOLO preset)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With the Auto-review experiment on, there's also an Auto-review mode that routes approvals to an automatic reviewer (the CLI equivalent is &lt;code&gt;--approve-for-me&lt;/code&gt;, hidden alias &lt;code&gt;--not-so-yolo&lt;/code&gt;, which pairs that reviewer with &lt;code&gt;workspace-write&lt;/code&gt;). &lt;code&gt;/approvals&lt;/code&gt; is gone; &lt;code&gt;/approve&lt;/code&gt; only retries one action the reviewer rejected. There's no keyboard shortcut to Full Access, which is deliberate friction.&lt;/p&gt;

&lt;p&gt;Gotcha: config is read at session start. Edit &lt;code&gt;config.toml&lt;/code&gt; mid-session and nothing changes until you restart or use &lt;code&gt;/permissions&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes in CI with codex exec?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;codex exec&lt;/code&gt; runs one task non-interactively. There's nobody to ask, so it &lt;strong&gt;never asks&lt;/strong&gt; and has no &lt;code&gt;-a&lt;/code&gt; flag. The sandbox is the only knob, and it &lt;strong&gt;defaults to read-only&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"summarize the open TODOs"&lt;/span&gt;                        &lt;span class="c"&gt;# read-only&lt;/span&gt;
codex &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--sandbox&lt;/span&gt; workspace-write &lt;span class="s2"&gt;"fix the failing tests"&lt;/span&gt;
codex &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;--yolo&lt;/span&gt; &lt;span class="s2"&gt;"run the full release script"&lt;/span&gt;              &lt;span class="c"&gt;# no sandbox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;exec&lt;/code&gt; refuses to run outside a git repo unless you pass &lt;code&gt;--skip-git-repo-check&lt;/code&gt; (or &lt;code&gt;--yolo&lt;/code&gt;, which skips it too). &lt;code&gt;--json&lt;/code&gt; streams JSON Lines events; &lt;code&gt;-o &amp;lt;file&amp;gt;&lt;/code&gt; writes the final message. Use &lt;code&gt;CODEX_API_KEY&lt;/code&gt; scoped to that one step, not job-wide, if the workflow checks out untrusted code.&lt;/p&gt;

&lt;p&gt;On GitHub, &lt;code&gt;openai/codex-action@v1&lt;/code&gt; keeps the key behind a proxy, drops &lt;code&gt;sudo&lt;/code&gt; by default (&lt;code&gt;safety-strategy: drop-sudo&lt;/code&gt;), and takes &lt;code&gt;permission-profile: ":workspace"&lt;/code&gt;. A hosted runner is exactly the "outer sandbox" &lt;code&gt;--yolo&lt;/code&gt; assumes, but the workspace profile is usually enough.&lt;/p&gt;

&lt;p&gt;Two more things YOLO does &lt;strong&gt;not&lt;/strong&gt; skip: hooks still need to be trusted once (&lt;code&gt;--dangerously-bypass-hook-trust&lt;/code&gt; exists for automation that vets them), and &lt;code&gt;--full-auto&lt;/code&gt; is simply gone (use &lt;code&gt;-s workspace-write&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  How does YOLO map over ACP?
&lt;/h2&gt;

&lt;p&gt;Codex doesn't speak the Agent Client Protocol natively. &lt;code&gt;@agentclientprotocol/codex-acp&lt;/code&gt; is a stdio adapter that starts the Codex App Server and translates both ways. Over ACP there are no flags, just four session modes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ACP mode&lt;/th&gt;
&lt;th&gt;Approvals&lt;/th&gt;
&lt;th&gt;Sandbox&lt;/th&gt;
&lt;th&gt;CLI equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;read-only&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;asks you&lt;/td&gt;
&lt;td&gt;read-only&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-s read-only&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;workspace-write&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;asks you&lt;/td&gt;
&lt;td&gt;workspace-write&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/permissions&lt;/code&gt; Default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;agent&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;automatic reviewer&lt;/td&gt;
&lt;td&gt;workspace-write&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--approve-for-me&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;agent-full-access&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;never&lt;/td&gt;
&lt;td&gt;danger-full-access&lt;/td&gt;
&lt;td&gt;&lt;code&gt;--yolo&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note the default is &lt;code&gt;agent&lt;/code&gt;, so Codex over ACP doesn't ask you about most things even before YOLO. &lt;code&gt;INITIAL_AGENT_MODE=agent-full-access&lt;/code&gt; starts it in YOLO; &lt;code&gt;CODEX_CONFIG&lt;/code&gt; merges a JSON object into session config.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I turn on YOLO per task or per workspace with AgentRQ?
&lt;/h2&gt;

&lt;p&gt;Every Codex switch above is session-scoped. If you want YOLO for &lt;em&gt;one job&lt;/em&gt; and approvals for everything else, move the decision out of Codex and into a task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Connect Codex through the &lt;a href="https://agentrq.com/docs/connect-acp-agent" rel="noopener noreferrer"&gt;ACP Gateway&lt;/a&gt;&lt;/strong&gt; (&lt;a href="https://agentrq.com/docs/agents/codex-cli" rel="noopener noreferrer"&gt;Codex CLI ACP setup guide&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @agentrq/acp-gateway@latest &lt;span class="nt"&gt;--login&lt;/span&gt; &lt;span class="nt"&gt;--agent&lt;/span&gt; codex-acp   &lt;span class="c"&gt;# once&lt;/span&gt;
npx @agentrq/acp-gateway@latest &lt;span class="nt"&gt;--agent&lt;/span&gt; codex-acp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gateway moves each new session out of any self-approving mode (Auto review, Full access) and into &lt;strong&gt;read-only&lt;/strong&gt;, so every edit and command comes to you as a permission request in the AgentRQ task, on the web, your phone or &lt;a href="https://agentrq.com/docs/integrations/slack" rel="noopener noreferrer"&gt;Slack&lt;/a&gt;. You answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Allow Once&lt;/strong&gt;: this call only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always Allow&lt;/strong&gt;: adds the tool to the workspace's auto-approved list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deny&lt;/strong&gt;: Codex gets the rejection; you can reply with what to do instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If nobody answers within 30 minutes, the gateway cancels the turn instead of guessing (&lt;code&gt;--permission-timeout&lt;/code&gt; changes it).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2a. Per task.&lt;/strong&gt; Flip the &lt;strong&gt;YOLO&lt;/strong&gt; toggle on a task, or set it at creation. Every permission request in that task is auto-approved; every other task still asks. &lt;a href="https://agentrq.com/features/task-scheduling" rel="noopener noreferrer"&gt;Scheduled tasks&lt;/a&gt;, &lt;a href="https://agentrq.com/features/events" rel="noopener noreferrer"&gt;event triggers&lt;/a&gt; and &lt;a href="https://agentrq.com/features/workflows" rel="noopener noreferrer"&gt;workflow&lt;/a&gt; steps have the same switch. The per-task flag persists across agent disconnects and reconnects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2b. Per workspace.&lt;/strong&gt; Workspace settings has &lt;strong&gt;YOLO Mode (Execute All)&lt;/strong&gt; (UI warning: "Agent will not ask for permission"). Under the hood it's a default, not a global override: the approval check reads the task's own YOLO flag, and the workspace switch decides what that flag starts as. New tasks you create in the web form open with the YOLO toggle already on (you can still switch it off per task), and tasks the agent creates for itself over the workspace MCP server inherit it. Flipping the switch doesn't rewrite tasks that already exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or let a model approve and deny for you, from plain-English rules.&lt;/strong&gt; Between "ask me every time" and "approve everything" there's a third option: an &lt;a href="https://github.com/agentrq/agentrq/blob/main/docs/EXTENSIONS.md" rel="noopener noreferrer"&gt;AgentRQ desktop extension&lt;/a&gt; that reviews each permission request before it reaches you. Extensions are trusted Node modules loaded by the AgentRQ desktop app. One registers a reviewer with &lt;code&gt;ctx.hooks.add({ id, review(request) { ... } })&lt;/code&gt; and is handed the pending call: the tool name, the argument preview the harness sent, and the workspace. It answers &lt;code&gt;{ behavior: 'deny', reason }&lt;/code&gt;, &lt;code&gt;{ behavior: 'allow' }&lt;/code&gt;, or nothing at all to abstain. Point &lt;code&gt;review()&lt;/code&gt; at an external decision API such as &lt;a href="https://agentrq.com/blog/jev-system-one-models" rel="noopener noreferrer"&gt;TypeSafe's Jev&lt;/a&gt;, a "System One" model that returns a typed &lt;code&gt;choice&lt;/code&gt; with calibrated &lt;code&gt;probabilities&lt;/code&gt; and a &lt;code&gt;confidence&lt;/code&gt; in milliseconds instead of generating text. Send the tool call as the state, and your workspace's rules in plain English ("git push is fine on feature branches, never on main", "never read anything under ~/.aws") as a Choice question over allow / deny / ask me. Then threshold it: approve only on a high-confidence allow, refuse on a confident deny, and abstain on everything else so the request lands on your phone as usual. The rules can live on a per-workspace settings tab the extension draws itself; the bundled &lt;code&gt;guardrail&lt;/code&gt; example does exactly that with literal patterns.&lt;/p&gt;

&lt;p&gt;The review contract is built on one asymmetry: refusing costs a tool call, approving costs whatever the tool call does. So one refusal settles a request; silence (an abstain, an exception, or a reviewer that misses its 5-second deadline) is never an allow, the request just stays in front of you; and an extension needs the &lt;code&gt;decide&lt;/code&gt; consent level to approve, while &lt;code&gt;deny&lt;/code&gt; consent can only refuse. The install screen starts every extension at &lt;code&gt;none&lt;/code&gt;. Reviews only happen while the desktop app is open and signed in, so treat this as a fast first pass, not a security boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trade-off.&lt;/strong&gt; Workspace-wide is AgentRQ's version of putting &lt;code&gt;approval_policy = "never"&lt;/code&gt; in your global config: zero friction, but it outlives the job you trusted. Per-task YOLO scopes it to one unit of work. Crucially, YOLO in AgentRQ only removes the &lt;em&gt;questions&lt;/em&gt;: Codex keeps the sandbox of the mode it's in, so it never turns into &lt;code&gt;danger-full-access&lt;/code&gt;. Concrete example: task A ("upgrade test deps and fix what breaks", YOLO on) runs to the end unattended; task B ("clean up the staging deploy script", YOLO off) pings your phone for &lt;code&gt;./deploy.sh --dry-run&lt;/code&gt; (Allow Once) and later &lt;code&gt;git push --force origin staging&lt;/code&gt; (Deny, "open a PR instead"). Same Codex, same gateway. Start YOLO tasks from a clean git tree and check the &lt;a href="https://agentrq.com/features/tool-call-history" rel="noopener noreferrer"&gt;tool call history&lt;/a&gt; afterwards. More in the &lt;a href="https://agentrq.com/features/yolo-mode" rel="noopener noreferrer"&gt;YOLO mode feature page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is &lt;code&gt;--yolo&lt;/code&gt; the same as &lt;code&gt;--dangerously-bypass-approvals-and-sandbox&lt;/code&gt;?&lt;/strong&gt; Yes, identical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I get no prompts but keep the sandbox?&lt;/strong&gt; &lt;code&gt;codex -a never -s workspace-write&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why "unexpected argument '--yolo'"?&lt;/strong&gt; Your Codex predates the alias. &lt;code&gt;npm install -g @openai/codex@latest&lt;/code&gt; or &lt;code&gt;brew upgrade --cask codex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does Codex still ask in YOLO?&lt;/strong&gt; Config changed mid-session, only one of the two keys is set, an admin &lt;code&gt;requirements.toml&lt;/code&gt; forbids it, a hook awaits trust, or you're on ACP where the client picks the mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Codex sandbox work in WSL1?&lt;/strong&gt; No. Use WSL2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is &lt;code&gt;--full-auto&lt;/code&gt; YOLO?&lt;/strong&gt; It never was, and it's removed. Use &lt;code&gt;--sandbox workspace-write&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Comparing agents? Here's &lt;a href="https://agentrq.com/blog/what-is-yolo-mode-and-how-to-turn-it-on-in-every-coding-agent" rel="noopener noreferrer"&gt;YOLO mode in every coding agent&lt;/a&gt;, side by side.&lt;/p&gt;




&lt;p&gt;Where do you land: &lt;code&gt;--yolo&lt;/code&gt; only inside containers, or &lt;code&gt;-a never -s workspace-write&lt;/code&gt; with &lt;code&gt;network_access = true&lt;/code&gt; everywhere? And has anyone hit the bubblewrap user-namespace wall in their CI? Tell me in the comments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://agentrq.com/guidelines/yolo-mode/codex-cli" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codex</category>
      <category>security</category>
      <category>cli</category>
    </item>
    <item>
      <title>Claude Code YOLO mode: what --dangerously-skip-permissions really turns off (and what it doesn't)</title>
      <dc:creator>Tony</dc:creator>
      <pubDate>Fri, 09 Oct 2026 15:35:38 +0000</pubDate>
      <link>https://dev.to/agentrq/claude-code-yolo-mode-what-dangerously-skip-permissions-really-turns-off-and-what-it-doesnt-46h1</link>
      <guid>https://dev.to/agentrq/claude-code-yolo-mode-what-dangerously-skip-permissions-really-turns-off-and-what-it-doesnt-46h1</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code's YOLO mode is officially called &lt;strong&gt;bypass permissions&lt;/strong&gt;: &lt;code&gt;claude --dangerously-skip-permissions&lt;/code&gt;, which is exactly &lt;code&gt;claude --permission-mode bypassPermissions&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It removes the &lt;strong&gt;permission prompts&lt;/strong&gt;. It does &lt;strong&gt;not&lt;/strong&gt; touch the &lt;strong&gt;Bash sandbox&lt;/strong&gt;, which is a separate, OS-enforced layer (Seatbelt on macOS, bubblewrap + socat on Linux/WSL2).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deny&lt;/code&gt; rules, explicit &lt;code&gt;ask&lt;/code&gt; rules and the critical-path &lt;code&gt;rm&lt;/code&gt; guard still fire in bypass mode.&lt;/li&gt;
&lt;li&gt;A repo's own &lt;code&gt;.claude/settings.json&lt;/code&gt; &lt;strong&gt;cannot&lt;/strong&gt; switch YOLO on. Only user settings, managed settings or &lt;code&gt;--settings&lt;/code&gt; can.&lt;/li&gt;
&lt;li&gt;For most people, &lt;strong&gt;auto mode&lt;/strong&gt; (a classifier reviews each action) is the better "YOLO, but not stupid".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything here was checked against Anthropic's docs at code.claude.com and &lt;code&gt;claude --help&lt;/code&gt; from Claude Code 2.1.292 on October 7, 2026.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why does "skip permissions" not mean "no guardrails"?
&lt;/h2&gt;

&lt;p&gt;The first thing to internalize is that Claude Code has &lt;strong&gt;two independent safety layers&lt;/strong&gt;, and they're enforced in completely different places:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Enforced by&lt;/th&gt;
&lt;th&gt;What it gates&lt;/th&gt;
&lt;th&gt;Does YOLO remove it?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Permission prompts&lt;/td&gt;
&lt;td&gt;Claude Code itself, before a tool call runs&lt;/td&gt;
&lt;td&gt;Every tool call: Bash, Edit, Write, MCP tools…&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bash sandbox&lt;/td&gt;
&lt;td&gt;The operating system, while a command runs&lt;/td&gt;
&lt;td&gt;Filesystem writes and network egress of shell commands and their children&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;No&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The permission layer is a policy check in the agent's process: "is this tool call allowed, denied, or do I ask the human?" Bypass mode short-circuits the "ask" branch to "allow". Allow rules become irrelevant, because everything is allowed anyway.&lt;/p&gt;

&lt;p&gt;The sandbox is a different beast. When it's on, Claude Code wraps each shell command in an OS-level boundary built on Anthropic's open source &lt;code&gt;@anthropic-ai/sandbox-runtime&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS:&lt;/strong&gt; the built-in &lt;strong&gt;Seatbelt&lt;/strong&gt; framework. Nothing to install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linux and WSL2:&lt;/strong&gt; &lt;strong&gt;bubblewrap&lt;/strong&gt; for filesystem isolation and &lt;strong&gt;socat&lt;/strong&gt; to relay network traffic through the sandbox proxy (plus a seccomp filter; &lt;code&gt;/sandbox&lt;/code&gt; shows a Dependencies tab if any piece is missing).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Windows:&lt;/strong&gt; no sandbox. Use WSL2.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default a sandboxed command can write only to the working directory, a per-user temp dir and directories you've added. Network has &lt;em&gt;no direct route out&lt;/em&gt;: everything goes through a local proxy that checks each host against an allowlist that starts empty. That's why something like &lt;code&gt;curl --noproxy '*'&lt;/code&gt; just fails to resolve: there's no route around the proxy.&lt;/p&gt;

&lt;p&gt;So YOLO answers "should I ask?" and the sandbox answers "what can this process physically reach?". You can (and should) run them together.&lt;/p&gt;

&lt;h2&gt;
  
  
  What survives bypass mode?
&lt;/h2&gt;

&lt;p&gt;Even with every prompt gone, these still apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;deny&lt;/code&gt; rules&lt;/strong&gt; and &lt;strong&gt;explicit &lt;code&gt;ask&lt;/code&gt; rules&lt;/strong&gt; in your permission config.&lt;/li&gt;
&lt;li&gt;The guard against &lt;strong&gt;&lt;code&gt;rm&lt;/code&gt; on critical paths&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Questions Claude asks you directly&lt;/strong&gt; (it's still allowed to stop and ask).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The sandbox&lt;/strong&gt;, if you turned it on with &lt;code&gt;/sandbox&lt;/code&gt; or &lt;code&gt;"sandbox": {"enabled": true}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's one sharp edge in that last point. When a command fails inside the sandbox (say, a tool that's incompatible with it, or a blocked host), Claude can retry it with a &lt;code&gt;dangerouslyDisableSandbox&lt;/code&gt; parameter. In &lt;code&gt;bypassPermissions&lt;/code&gt; mode, that unsandboxed retry &lt;strong&gt;runs without a prompt&lt;/strong&gt;. Two ways to close the hatch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sandbox"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowUnsandboxedCommands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that set, Claude Code ignores &lt;code&gt;dangerouslyDisableSandbox&lt;/code&gt; entirely (the &lt;code&gt;/sandbox&lt;/code&gt; Overrides tab calls this &lt;strong&gt;Strict sandbox mode&lt;/strong&gt;). Alternatively, add an ask rule for &lt;code&gt;Bash(dangerouslyDisableSandbox:true)&lt;/code&gt;; per the docs it prompts even in bypass mode and beats a matching allow rule.&lt;/p&gt;

&lt;p&gt;Also worth knowing: the sandbox covers &lt;strong&gt;shell commands only&lt;/strong&gt;. Read/Edit/Write/WebFetch, hooks, local MCP servers and your status line command run outside it, governed only by permission rules. In bypass mode that means they're governed by… your deny rules. If you want one boundary around everything, run the whole &lt;code&gt;claude&lt;/code&gt; process in a container or VM.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you actually turn it on?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;Full YOLO&lt;/th&gt;
&lt;th&gt;Halfway&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude --dangerously-skip-permissions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;claude --permission-mode auto&lt;/code&gt; or &lt;code&gt;acceptEdits&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;settings.json&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"defaultMode": "bypassPermissions"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"defaultMode": "acceptEdits"&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;In a session&lt;/td&gt;
&lt;td&gt;Shift+Tab, if allowed at launch&lt;/td&gt;
&lt;td&gt;Shift+Tab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VS Code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claudeCode.allowDangerouslySkipPermissions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;mode selector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rules&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"allow": ["Bash(npm test)"]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--dangerously-skip-permissions&lt;/span&gt;
&lt;span class="c"&gt;# identical to:&lt;/span&gt;
claude &lt;span class="nt"&gt;--permission-mode&lt;/span&gt; bypassPermissions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--permission-mode&lt;/code&gt; takes &lt;code&gt;manual&lt;/code&gt; (the default, spelled &lt;code&gt;default&lt;/code&gt; in config files), &lt;code&gt;acceptEdits&lt;/code&gt;, &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;plan&lt;/code&gt;, &lt;code&gt;dontAsk&lt;/code&gt; and &lt;code&gt;bypassPermissions&lt;/code&gt;. The first interactive run shows a warning you have to accept.&lt;/p&gt;

&lt;p&gt;As a persistent default, in &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"defaultMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bypassPermissions"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why can't a cloned repo flip YOLO on for you?
&lt;/h2&gt;

&lt;p&gt;This is my favourite design decision in the whole permission system. &lt;code&gt;defaultMode: "bypassPermissions"&lt;/code&gt; is honoured in &lt;strong&gt;user settings&lt;/strong&gt;, &lt;strong&gt;managed settings&lt;/strong&gt; and a file passed with &lt;strong&gt;&lt;code&gt;--settings&lt;/code&gt;&lt;/strong&gt;. It is &lt;strong&gt;ignored&lt;/strong&gt; in a project's own &lt;code&gt;.claude/settings.json&lt;/code&gt; and &lt;code&gt;.claude/settings.local.json&lt;/code&gt;: Claude Code just starts in the default mode.&lt;/p&gt;

&lt;p&gt;Think about the threat model. Project settings ship &lt;em&gt;with the repo&lt;/em&gt;. If they could set bypass mode, then &lt;code&gt;git clone evil/repo &amp;amp;&amp;amp; cd repo &amp;amp;&amp;amp; claude&lt;/code&gt; would hand an attacker an agent that runs anything without asking, and the attacker's README or issue text is right there to prompt-inject it. The rule is simple: &lt;strong&gt;only scopes you control can lower your guard.&lt;/strong&gt; The same idea shows up elsewhere in the sandbox docs, where credential-masking settings are honoured only from user/managed/&lt;code&gt;--settings&lt;/code&gt; scopes and ignored in a repo's settings.&lt;/p&gt;

&lt;p&gt;Cloud sessions ignore &lt;code&gt;bypassPermissions&lt;/code&gt; from settings files too, and admins can kill the mode org-wide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"disableBypassPermissionsMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"disable"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why won't --dangerously-skip-permissions run as root?
&lt;/h2&gt;

&lt;p&gt;On Linux and macOS, Claude Code &lt;strong&gt;refuses to start in bypass mode as root or under sudo&lt;/strong&gt;, unless it detects it's already inside a sandbox. That's the "no prompts &lt;em&gt;and&lt;/em&gt; unlimited privilege" combination it won't sign off on. If you hit this in a container, it's the container detection that matters; on a bare host, the fix is "don't be root", not "find a workaround".&lt;/p&gt;

&lt;h2&gt;
  
  
  Why isn't bypass in my Shift+Tab cycle?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Shift+Tab&lt;/strong&gt; cycles auto → default → acceptEdits → plan, then any optional modes. Bypass is only part of the cycle if the session was &lt;strong&gt;launched with permission&lt;/strong&gt; to use it. To have it available without starting in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--allow-dangerously-skip-permissions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a nice two-step arm-then-fire design: the capability is granted at process start (a deliberate act), and only &lt;em&gt;then&lt;/em&gt; can a keystroke reach it. A stray Shift+Tab in a normal session can never land you in YOLO.&lt;/p&gt;

&lt;p&gt;In VS Code, &lt;code&gt;claudeCode.allowDangerouslySkipPermissions&lt;/code&gt; plays the same "arm" role: it adds &lt;strong&gt;Bypass permissions&lt;/strong&gt; to the mode selector. &lt;code&gt;claudeCode.initialPermissionMode&lt;/code&gt; sets what new conversations start in (&lt;code&gt;default&lt;/code&gt;, &lt;code&gt;acceptEdits&lt;/code&gt;, &lt;code&gt;plan&lt;/code&gt;, &lt;code&gt;bypassPermissions&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Is auto mode just YOLO with extra steps?
&lt;/h2&gt;

&lt;p&gt;No, and it's what I'd reach for first. In &lt;strong&gt;auto mode&lt;/strong&gt; a separate classifier model reviews each action and only stops you for the risky ones. Since 2.1.283 it's the default starting mode in the terminal and VS Code on supported models.&lt;/p&gt;

&lt;p&gt;The other halfway options compose nicely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;acceptEdits&lt;/code&gt;&lt;/strong&gt;: file edits go through, shell commands still ask.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allow rules&lt;/strong&gt;: &lt;code&gt;"Bash(npm test)"&lt;/code&gt;, &lt;code&gt;"Bash(git *)"&lt;/code&gt;, &lt;code&gt;"Read"&lt;/code&gt; in &lt;code&gt;permissions.allow&lt;/code&gt;, or &lt;code&gt;--allowedTools&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox auto-allow&lt;/strong&gt;: with the sandbox on, sandboxed Bash commands can run without prompts because the OS, not you, limits what they can reach. Deny rules, critical-path &lt;code&gt;rm&lt;/code&gt; and content-scoped ask rules like &lt;code&gt;Bash(git push *)&lt;/code&gt; still prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last combo is, for me, the sweet spot: zero prompts for &lt;code&gt;npm test&lt;/code&gt; and friends, but a kernel-enforced fence around writes and egress.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I turn on YOLO per task or per workspace with AgentRQ?
&lt;/h2&gt;

&lt;p&gt;Everything above is &lt;strong&gt;session-scoped&lt;/strong&gt;: you decide once, at launch or with Shift+Tab, and that decision covers every tool call until you exit. If you run Claude Code unattended (scheduled jobs, long refactors while you're away), you usually want something finer: YOLO for &lt;em&gt;this&lt;/em&gt; job, prompts for everything else. That's the gap &lt;a href="https://agentrq.com/features/yolo-mode" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt; fills by moving the approval decision out of the terminal and into a task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Connect Claude Code to a workspace.&lt;/strong&gt; Follow the &lt;a href="https://agentrq.com/docs/connect-claude-code" rel="noopener noreferrer"&gt;Claude Code setup guide&lt;/a&gt;, which adds the workspace as an MCP server and a notification channel. Alternatively, run it through the &lt;a href="https://agentrq.com/docs/connect-acp-agent" rel="noopener noreferrer"&gt;ACP Gateway&lt;/a&gt; with &lt;code&gt;--agent claude-acp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Start Claude Code without bypass.&lt;/strong&gt; Use the default mode or &lt;code&gt;acceptEdits&lt;/code&gt;, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude &lt;span class="nt"&gt;--permission-mode&lt;/span&gt; acceptEdits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avoid auto mode here, otherwise the classifier answers the permission requests before they ever reach you. Each request now shows up in the AgentRQ task (web, phone or Slack) with the command or edit it's about, and you answer one of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Allow Once&lt;/strong&gt;: this call only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always Allow&lt;/strong&gt;: adds the tool to the workspace's auto-approved list, so routine calls stop asking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deny&lt;/strong&gt;: Claude Code gets a rejection and carries on with another approach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3a. YOLO for one task.&lt;/strong&gt; Flip the &lt;strong&gt;YOLO&lt;/strong&gt; toggle on a task, or set it when you create the task. Every permission request in that task is approved automatically and Claude Code never waits, while every other task in the workspace still asks. The flag is per task and persists across agent disconnects and reconnects. &lt;a href="https://agentrq.com/features/task-scheduling" rel="noopener noreferrer"&gt;Scheduled tasks&lt;/a&gt;, &lt;a href="https://agentrq.com/features/events" rel="noopener noreferrer"&gt;event triggers&lt;/a&gt; and &lt;a href="https://agentrq.com/features/workflows" rel="noopener noreferrer"&gt;workflow&lt;/a&gt; steps have the same switch, so a nightly job can run in YOLO while your interactive work stays supervised.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3b. YOLO for the whole workspace.&lt;/strong&gt; Workspace settings has &lt;strong&gt;YOLO Mode (Execute All)&lt;/strong&gt; (UI warning: "Agent will not ask for permission"). Under the hood it's a default, not a global override: the approval check reads the task's own YOLO flag, and the workspace switch decides what that flag starts as. New tasks you create in the web form open with the YOLO toggle already on (you can still switch it off per task), and tasks the agent creates for itself over the workspace MCP server inherit it. Flipping the switch doesn't rewrite tasks that already exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or let a model approve and deny for you, from plain-English rules.&lt;/strong&gt; Between "ask me every time" and "approve everything" there's a third option: an &lt;a href="https://github.com/agentrq/agentrq/blob/main/docs/EXTENSIONS.md" rel="noopener noreferrer"&gt;AgentRQ desktop extension&lt;/a&gt; that reviews each permission request before it reaches you. Extensions are trusted Node modules loaded by the AgentRQ desktop app. One registers a reviewer with &lt;code&gt;ctx.hooks.add({ id, review(request) { ... } })&lt;/code&gt; and is handed the pending call: the tool name, the argument preview the harness sent, and the workspace. It answers &lt;code&gt;{ behavior: 'deny', reason }&lt;/code&gt;, &lt;code&gt;{ behavior: 'allow' }&lt;/code&gt;, or nothing at all to abstain. Point &lt;code&gt;review()&lt;/code&gt; at an external decision API such as &lt;a href="https://agentrq.com/blog/jev-system-one-models" rel="noopener noreferrer"&gt;TypeSafe's Jev&lt;/a&gt;, a "System One" model that returns a typed &lt;code&gt;choice&lt;/code&gt; with calibrated &lt;code&gt;probabilities&lt;/code&gt; and a &lt;code&gt;confidence&lt;/code&gt; in milliseconds instead of generating text. Send the tool call as the state, and your workspace's rules in plain English ("git push is fine on feature branches, never on main", "never read anything under ~/.aws") as a Choice question over allow / deny / ask me. Then threshold it: approve only on a high-confidence allow, refuse on a confident deny, and abstain on everything else so the request lands on your phone as usual. The rules can live on a per-workspace settings tab the extension draws itself; the bundled &lt;code&gt;guardrail&lt;/code&gt; example does exactly that with literal patterns.&lt;/p&gt;

&lt;p&gt;The review contract is built on one asymmetry: refusing costs a tool call, approving costs whatever the tool call does. So one refusal settles a request; silence (an abstain, an exception, or a reviewer that misses its 5-second deadline) is never an allow, the request just stays in front of you; and an extension needs the &lt;code&gt;decide&lt;/code&gt; consent level to approve, while &lt;code&gt;deny&lt;/code&gt; consent can only refuse. The install screen starts every extension at &lt;code&gt;none&lt;/code&gt;. Reviews only happen while the desktop app is open and signed in, so treat this as a fast first pass, not a security boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per task vs. workspace-wide, the trade-off:&lt;/strong&gt; the workspace switch is the AgentRQ equivalent of putting &lt;code&gt;bypassPermissions&lt;/code&gt; in your user settings: convenient, but it outlives the job you actually trusted, and it covers work you haven't seen yet. Per-task YOLO scopes the blast radius to one unit of work and expires with it. My rule: leave Execute All off, use per-task YOLO for jobs you'd happily &lt;code&gt;git reset&lt;/code&gt;, and lean on &lt;strong&gt;Always Allow&lt;/strong&gt; for boring tools (prune that list now and then). Either way, Claude Code's own layers still apply underneath:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep &lt;code&gt;/sandbox&lt;/code&gt; on, ideally with &lt;code&gt;allowUnsandboxedCommands: false&lt;/code&gt;. AgentRQ removes the questions; the sandbox still limits what an approved command can touch.&lt;/li&gt;
&lt;li&gt;Start every YOLO task from a clean git tree, so any change is one &lt;code&gt;git reset&lt;/code&gt; away.&lt;/li&gt;
&lt;li&gt;Read the &lt;a href="https://agentrq.com/features/tool-call-history" rel="noopener noreferrer"&gt;tool call history&lt;/a&gt; afterwards; it lists every call, including the auto-approved ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; the same as &lt;code&gt;--permission-mode bypassPermissions&lt;/code&gt;?&lt;/strong&gt; Yes, exactly the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does YOLO mode turn off the sandbox?&lt;/strong&gt; No. It only skips prompts. But unsandboxed &lt;em&gt;retries&lt;/em&gt; run without asking in bypass mode unless you set &lt;code&gt;allowUnsandboxedCommands: false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I put bypass mode in my repo's &lt;code&gt;.claude/settings.json&lt;/code&gt;?&lt;/strong&gt; You can write it, but Claude Code ignores it there. Use &lt;code&gt;~/.claude/settings.json&lt;/code&gt;, managed settings or &lt;code&gt;--settings&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does it refuse to start as root?&lt;/strong&gt; Bypass mode is blocked as root/sudo on Linux and macOS unless Claude Code detects it's already sandboxed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is bypass missing from Shift+Tab?&lt;/strong&gt; Start the session with &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; or &lt;code&gt;--allow-dangerously-skip-permissions&lt;/code&gt;, or set bypass in user settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the sandbox cover MCP servers and hooks?&lt;/strong&gt; No. They run with your full access; only shell commands are sandboxed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I approve Claude Code permissions from my phone?&lt;/strong&gt; Yes. Connect it to an AgentRQ workspace and answer Allow Once, Always Allow or Deny in the task.&lt;/p&gt;

&lt;p&gt;If you're comparing agents, here's how &lt;a href="https://agentrq.com/blog/what-is-yolo-mode-and-how-to-turn-it-on-in-every-coding-agent" rel="noopener noreferrer"&gt;YOLO mode works in every coding agent&lt;/a&gt;, side by side.&lt;/p&gt;




&lt;p&gt;So, what's your setup: full bypass inside a container, auto mode on the host, or sandbox auto-allow with a strict no-retry policy? And has the unsandboxed retry ever surprised you? Tell me in the comments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://agentrq.com/guidelines/yolo-mode/claude-code" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>security</category>
      <category>cli</category>
    </item>
    <item>
      <title>There is no agy --yolo. How YOLO mode actually works in Antigravity (IDE and CLI)</title>
      <dc:creator>Tony</dc:creator>
      <pubDate>Thu, 08 Oct 2026 15:37:53 +0000</pubDate>
      <link>https://dev.to/agentrq/there-is-no-agy-yolo-how-yolo-mode-actually-works-in-antigravity-ide-and-cli-456l</link>
      <guid>https://dev.to/agentrq/there-is-no-agy-yolo-how-yolo-mode-actually-works-in-antigravity-ide-and-cli-456l</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;agy --yolo&lt;/code&gt; is not a flag. The CLI's YOLO is &lt;code&gt;agy --dangerously-skip-permissions&lt;/code&gt;, or &lt;code&gt;"toolPermission": "always-proceed"&lt;/code&gt; in &lt;code&gt;~/.gemini/antigravity-cli/settings.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the Antigravity IDE, YOLO is the &lt;strong&gt;Turbo&lt;/strong&gt; permission preset.&lt;/li&gt;
&lt;li&gt;The two are &lt;strong&gt;not equivalent&lt;/strong&gt;. Turbo turns off approvals &lt;strong&gt;and&lt;/strong&gt; the sandbox, and opens the whole filesystem. The CLI flag turns off approvals only, and leaves the terminal sandbox however it was, which by default means &lt;strong&gt;off&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The sane middle ground is the IDE's &lt;strong&gt;Default&lt;/strong&gt; preset, or &lt;code&gt;proceed-in-sandbox&lt;/code&gt; in the CLI with the sandbox actually enabled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Checked against Google's Antigravity docs (antigravity.google/docs) on October 7, 2026. Antigravity is closed source and Google doesn't publish the CLI's full flag list, so everything here comes from the documentation, not the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are people typing &lt;code&gt;agy --yolo&lt;/code&gt; in the first place?
&lt;/h2&gt;

&lt;p&gt;Migration muscle memory. On June 18, 2026, Google moved free, Google AI Pro and Ultra users from Gemini CLI to the Antigravity CLI. Gemini CLI had &lt;code&gt;--yolo&lt;/code&gt; (now deprecated in favour of &lt;code&gt;--approval-mode=yolo&lt;/code&gt;). &lt;code&gt;agy&lt;/code&gt; didn't carry it over. Instead, it borrowed Claude Code's spelling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agy &lt;span class="nt"&gt;--dangerously-skip-permissions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The naming is a design statement in itself. "yolo" sounds like a fun mode. "dangerously skip permissions" says what you're giving up. Google's CLI guide lists it with &lt;code&gt;--sandbox&lt;/code&gt; as launch flags that override your saved settings for that one session, and the settings panel shows when a value came from a flag rather than the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the two layers YOLO can touch?
&lt;/h2&gt;

&lt;p&gt;Like most serious agents, Antigravity separates two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Approval:&lt;/strong&gt; does a human confirm this tool call before it runs?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containment:&lt;/strong&gt; once it runs, what can it reach?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Where the IDE and CLI differ is in how their "YOLO" maps onto those layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Approvals&lt;/th&gt;
&lt;th&gt;Terminal sandbox&lt;/th&gt;
&lt;th&gt;Filesystem&lt;/th&gt;
&lt;th&gt;MCP / web tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IDE &lt;strong&gt;Turbo&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Off&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Off&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Whole filesystem&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Off&lt;/td&gt;
&lt;td&gt;Unchanged (&lt;code&gt;--sandbox&lt;/code&gt; / &lt;code&gt;enableTerminalSandbox&lt;/code&gt;, default off)&lt;/td&gt;
&lt;td&gt;Unchanged&lt;/td&gt;
&lt;td&gt;Allowed (no prompts)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So "YOLO in the CLI" leaves you exactly as sandboxed as you were before. On a stock install, that's not at all. Turbo is the more honest of the two: it's labelled as the everything-off preset.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does the CLI's toolPermission work?
&lt;/h2&gt;

&lt;p&gt;The CLI keeps settings in &lt;code&gt;~/.gemini/antigravity-cli/settings.json&lt;/code&gt;, and it only writes the keys you change. The one that matters is &lt;code&gt;toolPermission&lt;/code&gt;, which takes four values. Ordered from most to least paranoid:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strict&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Asks before every tool that isn't a read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;request-review&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Asks before writes, shell commands and web tools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;proceed-in-sandbox&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Runs terminal commands without asking &lt;strong&gt;as long as they stay in the sandbox&lt;/strong&gt;, asks otherwise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;always-proceed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Never asks. This is YOLO&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;proceed-in-sandbox&lt;/code&gt; is the interesting design. Approval depends on containment, so the prompt only appears when the command wants out. The catch is that it's only meaningful if the sandbox is on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"toolPermission"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"proceed-in-sandbox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"enableTerminalSandbox"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In-session, &lt;code&gt;/permissions&lt;/code&gt; opens the permissions manager (mode and rules for the running session), and &lt;code&gt;/config&lt;/code&gt; or &lt;code&gt;/settings&lt;/code&gt; opens the full editor. When a &lt;strong&gt;subagent&lt;/strong&gt; is waiting on an action, &lt;code&gt;Ctrl+K&lt;/code&gt; approves just that one action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I get something finer than a global mode?
&lt;/h2&gt;

&lt;p&gt;Yes, with rules. A &lt;code&gt;permissions&lt;/code&gt; block takes &lt;code&gt;allow&lt;/code&gt;, &lt;code&gt;ask&lt;/code&gt; and &lt;code&gt;deny&lt;/code&gt; lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"command(git)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command(npm test)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"write_file(src/)"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"command(rm)"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Matchers cover commands (including &lt;code&gt;command(regex:...)&lt;/code&gt;), file writes, URLs and MCP tools (&lt;code&gt;mcp(server/tool)&lt;/code&gt;). Precedence is the conservative one: &lt;strong&gt;deny beats ask, ask beats allow&lt;/strong&gt;. So a broad allow can never swallow a specific deny, and that's what lets you safely allow &lt;code&gt;command(git)&lt;/code&gt; while still denying something narrower.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do the IDE presets actually configure?
&lt;/h2&gt;

&lt;p&gt;On macOS and Linux: &lt;strong&gt;Settings → General → Permission Settings&lt;/strong&gt;. A project can override the preset or choose &lt;strong&gt;Inherit General&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Preset&lt;/th&gt;
&lt;th&gt;Sandbox&lt;/th&gt;
&lt;th&gt;Terminal commands&lt;/th&gt;
&lt;th&gt;Files&lt;/th&gt;
&lt;th&gt;MCP and web&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default&lt;/td&gt;
&lt;td&gt;On&lt;/td&gt;
&lt;td&gt;Free inside the sandbox, ask outside&lt;/td&gt;
&lt;td&gt;Workspace + temp&lt;/td&gt;
&lt;td&gt;Ask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request Review&lt;/td&gt;
&lt;td&gt;Off&lt;/td&gt;
&lt;td&gt;Always ask&lt;/td&gt;
&lt;td&gt;Workspace only&lt;/td&gt;
&lt;td&gt;Ask&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turbo&lt;/td&gt;
&lt;td&gt;Off&lt;/td&gt;
&lt;td&gt;Run without asking&lt;/td&gt;
&lt;td&gt;Whole filesystem&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Look at the shape of &lt;strong&gt;Default&lt;/strong&gt;. It isn't "ask about everything". It's the IDE version of &lt;code&gt;proceed-in-sandbox&lt;/code&gt;: the agent runs freely while it's contained, and stops when it wants to leave. For most work that's the better trade than Turbo. You keep the speed, and the blast radius stays at "workspace + temp".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Review&lt;/strong&gt; is the odd one out. It turns the sandbox &lt;strong&gt;off&lt;/strong&gt;, but makes up for it by asking about every command and limiting files to the workspace. That's human review instead of OS containment.&lt;/p&gt;

&lt;p&gt;Two more IDE knobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Artifact review policy&lt;/strong&gt; (&lt;code&gt;asks-for-review&lt;/code&gt;, &lt;code&gt;agent-decides&lt;/code&gt;, &lt;code&gt;always-proceed&lt;/code&gt;) decides whether the agent waits for you to review its plans and other artifacts. It's YOLO for planning, separate from YOLO for tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict mode&lt;/strong&gt; is the anti-Turbo. It sends terminal commands, browser JavaScript and artifacts to review, and turns the sandbox on &lt;strong&gt;with no network&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt; still uses the older model. Set &lt;strong&gt;Terminal Command Auto Execution&lt;/strong&gt; to &lt;strong&gt;Always Proceed&lt;/strong&gt; (it still respects your deny list) and the outside-of-folder file access policy to &lt;strong&gt;Always Allow&lt;/strong&gt;. Sandbox mode is a separate toggle there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is there an "Antigravity 2.0 YOLO mode"?
&lt;/h2&gt;

&lt;p&gt;Forum posts mention "Antigravity 2.0", but we found no official 2.0 page that changes the permission model. Today's documented options are Turbo in the IDE and &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; / &lt;code&gt;always-proceed&lt;/code&gt; in &lt;code&gt;agy&lt;/code&gt;. If that changes, the doc pages above are where it'll show up first.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I turn on YOLO per task or per workspace with AgentRQ?
&lt;/h2&gt;

&lt;p&gt;Both native switches cover a whole session (or a whole IDE preset). &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt; moves the decision to the task, and lets you answer prompts away from the terminal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Connect Antigravity&lt;/strong&gt; through the &lt;a href="https://agentrq.com/docs/connect-acp-agent" rel="noopener noreferrer"&gt;ACP Gateway&lt;/a&gt; (&lt;a href="https://agentrq.com/docs/agents/antigravity" rel="noopener noreferrer"&gt;Antigravity setup guide&lt;/a&gt;). Its registry build publishes no checksum, so the first run needs &lt;code&gt;--allow-unverified-agent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @agentrq/acp-gateway@latest &lt;span class="nt"&gt;--agent&lt;/span&gt; antigravity-acp &lt;span class="nt"&gt;--allow-unverified-agent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start it &lt;strong&gt;without&lt;/strong&gt; &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; or &lt;code&gt;always-proceed&lt;/code&gt;. The gateway also moves each new session out of any self-approving mode and into one where the agent asks a person.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Answer from anywhere.&lt;/strong&gt; Each permission request shows up in the AgentRQ task, on the web, your phone or Slack, with the command or edit it wants to run. You answer &lt;strong&gt;Allow Once&lt;/strong&gt;, &lt;strong&gt;Always Allow&lt;/strong&gt; (adds the tool to the workspace's auto-approved list) or &lt;strong&gt;Deny&lt;/strong&gt;. If nobody answers within 30 minutes, the gateway cancels the turn instead of guessing. &lt;code&gt;--permission-timeout&lt;/code&gt; changes the limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3a. YOLO for one task.&lt;/strong&gt; Flip the &lt;strong&gt;YOLO&lt;/strong&gt; toggle on a task, or when you create it. Every request in that task is auto-approved, and every other task still asks. The flag lives on the task, so it survives agent disconnects and reconnects. &lt;a href="https://agentrq.com/features/task-scheduling" rel="noopener noreferrer"&gt;Scheduled tasks&lt;/a&gt;, &lt;a href="https://agentrq.com/features/events" rel="noopener noreferrer"&gt;event triggers&lt;/a&gt; and &lt;a href="https://agentrq.com/features/workflows" rel="noopener noreferrer"&gt;workflow&lt;/a&gt; steps have the same switch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3b. YOLO for the whole workspace.&lt;/strong&gt; Workspace settings has &lt;strong&gt;YOLO Mode (Execute All)&lt;/strong&gt; (UI warning: "Agent will not ask for permission"). Under the hood it's a default, not a global override: the approval check reads the task's own YOLO flag, and the workspace switch decides what that flag starts as. New tasks you create in the web form open with the YOLO toggle already on (you can still switch it off per task), and tasks the agent creates for itself over the workspace MCP server inherit it. Flipping the switch doesn't rewrite tasks that already exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or let a model approve and deny for you, from plain-English rules.&lt;/strong&gt; Between "ask me every time" and "approve everything" there's a third option: an &lt;a href="https://github.com/agentrq/agentrq/blob/main/docs/EXTENSIONS.md" rel="noopener noreferrer"&gt;AgentRQ desktop extension&lt;/a&gt; that reviews each permission request before it reaches you. Extensions are trusted Node modules loaded by the AgentRQ desktop app. One registers a reviewer with &lt;code&gt;ctx.hooks.add({ id, review(request) { ... } })&lt;/code&gt; and is handed the pending call: the tool name, the argument preview the harness sent, and the workspace. It answers &lt;code&gt;{ behavior: 'deny', reason }&lt;/code&gt;, &lt;code&gt;{ behavior: 'allow' }&lt;/code&gt;, or nothing at all to abstain. Point &lt;code&gt;review()&lt;/code&gt; at an external decision API such as &lt;a href="https://agentrq.com/blog/jev-system-one-models" rel="noopener noreferrer"&gt;TypeSafe's Jev&lt;/a&gt;, a "System One" model that returns a typed &lt;code&gt;choice&lt;/code&gt; with calibrated &lt;code&gt;probabilities&lt;/code&gt; and a &lt;code&gt;confidence&lt;/code&gt; in milliseconds instead of generating text. Send the tool call as the state, and your workspace's rules in plain English ("git push is fine on feature branches, never on main", "never read anything under ~/.aws") as a Choice question over allow / deny / ask me. Then threshold it: approve only on a high-confidence allow, refuse on a confident deny, and abstain on everything else so the request lands on your phone as usual. The rules can live on a per-workspace settings tab the extension draws itself; the bundled &lt;code&gt;guardrail&lt;/code&gt; example does exactly that with literal patterns.&lt;/p&gt;

&lt;p&gt;The review contract is built on one asymmetry: refusing costs a tool call, approving costs whatever the tool call does. So one refusal settles a request; silence (an abstain, an exception, or a reviewer that misses its 5-second deadline) is never an allow, the request just stays in front of you; and an extension needs the &lt;code&gt;decide&lt;/code&gt; consent level to approve, while &lt;code&gt;deny&lt;/code&gt; consent can only refuse. The install screen starts every extension at &lt;code&gt;none&lt;/code&gt;. Reviews only happen while the desktop app is open and signed in, so treat this as a fast first pass, not a security boundary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trade-off.&lt;/strong&gt; Per-task YOLO is scoped trust: it ends with the job you vetted, so a nightly scheduled run can be YOLO while your interactive tasks stay supervised. Workspace-wide YOLO is less friction, but every future task inherits it. With Antigravity in particular, remember the layering above. AgentRQ's YOLO only answers the &lt;strong&gt;approval&lt;/strong&gt; question, so set &lt;code&gt;"enableTerminalSandbox": true&lt;/code&gt; and auto-approved commands still run inside the sandbox. Add a clean git tree before each YOLO task and a look at the &lt;a href="https://agentrq.com/features/tool-call-history" rel="noopener noreferrer"&gt;tool call history&lt;/a&gt; afterwards. More: &lt;a href="https://agentrq.com/features/yolo-mode" rel="noopener noreferrer"&gt;AgentRQ YOLO mode&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does &lt;code&gt;agy --yolo&lt;/code&gt; exist?&lt;/strong&gt; No. Use &lt;code&gt;agy --dangerously-skip-permissions&lt;/code&gt;, or &lt;code&gt;"toolPermission": "always-proceed"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between Turbo and the agy flag?&lt;/strong&gt; Turbo also turns off the sandbox and opens the whole filesystem. The CLI flag only skips approvals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the agy terminal sandbox on by default?&lt;/strong&gt; No. Enable it with &lt;code&gt;--sandbox&lt;/code&gt; or &lt;code&gt;"enableTerminalSandbox": true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the safest "fast" setting?&lt;/strong&gt; The IDE's Default preset, or &lt;code&gt;proceed-in-sandbox&lt;/code&gt; with the sandbox on in the CLI: no prompts while contained, a prompt when the agent wants out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do deny rules still work with always-proceed?&lt;/strong&gt; The docs say Windows' Always Proceed respects the deny list. For rules in general, deny beats ask beats allow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I approve Antigravity commands from my phone?&lt;/strong&gt; Connect it to &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt; through the ACP Gateway. Permission requests show up in the task.&lt;/p&gt;

&lt;p&gt;For every other agent, see &lt;a href="https://agentrq.com/blog/what-is-yolo-mode-and-how-to-turn-it-on-in-every-coding-agent" rel="noopener noreferrer"&gt;what YOLO mode is and how to turn it on in every coding agent&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Question for the comments: is "approve automatically &lt;strong&gt;only while sandboxed&lt;/strong&gt;" (Default / &lt;code&gt;proceed-in-sandbox&lt;/code&gt;) the pattern every agent should copy, or does it just move the trust problem into the sandbox config? 👇&lt;/p&gt;

&lt;p&gt;Originally published on &lt;a href="https://agentrq.com/guidelines/yolo-mode/antigravity" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>cli</category>
      <category>google</category>
    </item>
    <item>
      <title>Use Claude right inside your Chrome and let it play with WebMCP tools</title>
      <dc:creator>Mustafa Turan</dc:creator>
      <pubDate>Fri, 02 Oct 2026 03:00:01 +0000</pubDate>
      <link>https://dev.to/agentrq/use-claude-right-inside-your-chrome-and-let-it-play-with-webmcp-tools-3k41</link>
      <guid>https://dev.to/agentrq/use-claude-right-inside-your-chrome-and-let-it-play-with-webmcp-tools-3k41</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; WebMCP lets a website offer tools to AI agents, but only an agent inside that same tab can call them. We built a Chrome extension that removes that limit. Share a site with a workspace, and Claude Code (or Codex, or any MCP agent) can call the site's tools from your laptop or from a server in another building. The call runs in your signed-in tab, and anything that writes waits for your approval. The same popup also shows the &lt;strong&gt;live Claude Code terminal&lt;/strong&gt; of every agent on every machine you've connected. Below are the problems we hit building both, and how we solved them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem does WebMCP leave open?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/webmachinelearning/webmcp" rel="noopener noreferrer"&gt;WebMCP&lt;/a&gt; is a young browser standard. A page registers tools with &lt;code&gt;document.modelContext&lt;/code&gt;, such as "search the docs" or "create an issue", each with a name, a description and a JSON Schema for its input. An agent can call them without scraping the page or clicking through it.&lt;/p&gt;

&lt;p&gt;There's a catch: the tools live in the page's JavaScript. Only an agent running in that browser, in that tab, can reach them. Your Claude Code session in a terminal can't. Neither can the agent on your build box, or the one a cron job wakes up at 3am.&lt;/p&gt;

&lt;p&gt;Those are the agents doing most of the work. So we asked: what would it take to give a page's tools to an agent that isn't anywhere near the browser?&lt;/p&gt;

&lt;p&gt;Here's where we ended up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Claude Code / Codex / any MCP agent  (laptop, build box, cloud VM)
              │  MCP: listSiteTools · getSiteToolDefinition · callSiteTool
              ▼
         AgentRQ server ── approval in the task, if the tool writes
              │  WebSocket, opened by the browser
              ▼
   Extension service worker ── picks the right tab
              │  chrome.runtime messages
              ▼
   Bridge (isolated world) ⇄ Observer (page's world) ── tool.execute()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4a9e7p79iskhbqb3n25u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4a9e7p79iskhbqb3n25u.png" alt="The AgentRQ popup over agentrq.com: the icon shows a green 3, and a strip offers to share the site's 3 WebMCP tools with a workspace"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: The WebMCP bridge
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Challenge 1: How do you see a page's tools without becoming a tool provider?
&lt;/h3&gt;

&lt;p&gt;The obvious approach is to inject a &lt;code&gt;modelContext&lt;/code&gt; and see what the page puts in it. We didn't, because then the extension would decide which pages get WebMCP and how it behaves. A page that feature-detects WebMCP would detect us instead of Chrome.&lt;/p&gt;

&lt;p&gt;Instead, a small observer script runs in the page's own JavaScript world at &lt;code&gt;document_start&lt;/code&gt;, in the top frame only. It wraps the browser's native &lt;code&gt;registerTool&lt;/code&gt; so that it still calls through to Chrome, and it records what was registered. If the browser has no &lt;code&gt;modelContext&lt;/code&gt;, the observer does nothing. It never adds one.&lt;/p&gt;

&lt;p&gt;Three edge cases turned out to matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tools can be withdrawn.&lt;/strong&gt; &lt;code&gt;registerTool&lt;/code&gt; takes an &lt;code&gt;AbortSignal&lt;/code&gt;. When a page aborts a tool, any calls still running on it fail with a clear error instead of hanging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-registration wins.&lt;/strong&gt; If a page registers the same name twice, the newer one replaces the older one, and an abort on the stale one doesn't remove the new one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Descriptors must survive JSON.&lt;/strong&gt; A tool whose description or schema can't be serialized can never be described to a remote agent, so we drop it at the door.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenge 2: How do you talk to page code without the page listening in?
&lt;/h3&gt;

&lt;p&gt;Content scripts come in two worlds. The &lt;strong&gt;main world&lt;/strong&gt; shares JavaScript with the page, so it can wrap &lt;code&gt;registerTool&lt;/code&gt;, but it can't use extension APIs. The &lt;strong&gt;isolated world&lt;/strong&gt; can use &lt;code&gt;chrome.runtime&lt;/code&gt;, but it can't see the page's objects. So the design needs two scripts, the observer and a bridge, and they have to talk over the DOM, which the page can also use.&lt;/p&gt;

&lt;p&gt;A fixed event name like &lt;code&gt;agentrq-call&lt;/code&gt; would let any page listen to every call or forge results. Here's what we did instead:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The bridge (isolated world) generates a random UUID and drops it on &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; as a data attribute.&lt;/li&gt;
&lt;li&gt;The observer (main world) runs next. It &lt;strong&gt;reads the nonce and deletes the attribute&lt;/strong&gt; before any page script runs.&lt;/li&gt;
&lt;li&gt;Every message travels as a &lt;code&gt;CustomEvent&lt;/code&gt; whose &lt;strong&gt;event type is the nonce&lt;/strong&gt;. The page doesn't know the event name, so it can't subscribe and can't forge.&lt;/li&gt;
&lt;li&gt;The observer saves &lt;code&gt;dispatchEvent&lt;/code&gt;, &lt;code&gt;CustomEvent&lt;/code&gt; and &lt;code&gt;JSON&lt;/code&gt; at startup, so a page script that patches them later can't intercept anything.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Gotcha:&lt;/strong&gt; this depends on the bridge running before the observer. Chrome runs &lt;code&gt;document_start&lt;/code&gt; scripts in order of their &lt;strong&gt;registration IDs&lt;/strong&gt;, not the order you register them in. The bridge's ID has to sort first alphabetically. We learned that the hard way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 3: How does a server reach a browser behind NAT?
&lt;/h3&gt;

&lt;p&gt;It can't, so the browser dials out. The extension's Manifest V3 service worker opens a WebSocket to the AgentRQ server. That brought three MV3 problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A WebSocket from a service worker carries no cookies.&lt;/strong&gt; The worker first asks for a one-minute &lt;strong&gt;ticket&lt;/strong&gt; using your normal sign-in cookie (refreshing the short-lived access token once if needed), then connects with that ticket.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome kills idle service workers.&lt;/strong&gt; An open socket keeps the worker alive only while traffic flows, and &lt;strong&gt;pings from the server don't count&lt;/strong&gt;. So the worker sends its own ping every 20 seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No socket unless it's needed.&lt;/strong&gt; The socket is open only while at least one site is shared. When it drops, it reconnects with backoff from 1s up to 30s.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenge 4: Which tab runs the call?
&lt;/h3&gt;

&lt;p&gt;You might have three tabs of the same site open, or none. The worker tracks every tab that has announced tools and sends each call to the &lt;strong&gt;most recently used&lt;/strong&gt; tab of that origin that offers that tool. If you've closed them all, it &lt;strong&gt;reopens the site in a background tab&lt;/strong&gt; and waits for the page to register the tool again.&lt;/p&gt;

&lt;p&gt;Navigation was the messiest part:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A page unloading mid-call&lt;/strong&gt; fails only the calls sent to &lt;em&gt;that document&lt;/em&gt;. After a cross-site navigation, the new page may have announced its tools before the old page's unload event arrives, so we track calls by document, not by tab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The back/forward cache&lt;/strong&gt; restores a page without re-running its scripts, so the observer never announces again. The bridge keeps the page's last tool list and sends it again on a persisted &lt;code&gt;pageshow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A navigate tool&lt;/strong&gt; (one that moves the page somewhere) sends its result before the page unloads. Results and "page gone" go through the same channel in order, so the result arrives first instead of being reported as a failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenge 5: How do you keep remote tools from eating the agent's context window?
&lt;/h3&gt;

&lt;p&gt;If you send every schema of every tool on every shared site with each listing, the agent pays for it in tokens on every call. So the MCP surface has three steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;listSiteTools&lt;/code&gt; returns &lt;strong&gt;only names and descriptions&lt;/strong&gt;, plus whether each site is online.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getSiteToolDefinition&lt;/code&gt; returns one tool's full input schema when the agent actually wants to use it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;callSiteTool&lt;/code&gt; runs it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server &lt;strong&gt;validates arguments against the page's own JSON Schema&lt;/strong&gt; before anything reaches your browser, so a malformed call fails fast with a message the agent can fix. Calls have a 60-second deadline and results are capped at 256 KiB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 6: How do you let a remote agent act as you without handing it your credentials?
&lt;/h3&gt;

&lt;p&gt;This is the part we think matters most. The call runs &lt;strong&gt;in your signed-in Chrome, with your session on that site&lt;/strong&gt;. The agent never sees a password, a cookie or an API token. To the site, it's just you, in your tab, using a tool the site chose to offer.&lt;/p&gt;

&lt;p&gt;That makes approval essential:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tools the site annotates as &lt;strong&gt;read-only&lt;/strong&gt; (a search, say) just run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anything else asks first.&lt;/strong&gt; The request appears in the task the agent is working on, showing the tool and the exact arguments as pretty-printed JSON. You choose &lt;strong&gt;Allow once&lt;/strong&gt;, &lt;strong&gt;Always allow &amp;lt;tool&amp;gt; on this site&lt;/strong&gt;, or &lt;strong&gt;Deny&lt;/strong&gt;. "Always allow" is remembered per site and per tool.&lt;/li&gt;
&lt;li&gt;The agent has to pass the &lt;code&gt;taskId&lt;/code&gt; it's working on, so every write is tied to a piece of work you can see.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only a human can share a site&lt;/strong&gt;, from the popup, one site at a time. An agent can't add one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection is off by default.&lt;/strong&gt; Until you turn it on, the extension doesn't even look. Once it's on, nothing leaves the browser until you click Share.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also put effort into the failure messages, because the agent is the one reading them. If Chrome is closed, the agent doesn't get a vague "connection refused". It's told the human's Chrome isn't connected and to ask them to open it. If a site doesn't have the tool it asked for, the error lists the tools it does have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Claude Code's terminal, inside the extension
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3auhaqxsaslljtpqknet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3auhaqxsaslljtpqknet.png" alt="The live Claude Code terminal of an agent on a connected machine, shown in AgentRQ"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the toolbar icon (or press Alt+Shift+A), open an agent, and you get its &lt;strong&gt;real, live terminal&lt;/strong&gt;, not a log or a summary. You can watch it, scroll back, or type into it and take over. It works the same for the agent on your laptop, the one on the box under your desk and the one on a cloud VM, without SSH or a &lt;code&gt;tmux attach&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 7: Why not just bundle the web app into the extension?
&lt;/h3&gt;

&lt;p&gt;Code bundled into an extension runs on the extension's own &lt;code&gt;chrome-extension://&lt;/code&gt; origin, and your sign-in cookie never goes there. You'd be signed out no matter what. So the popup &lt;strong&gt;frames the server's own web app&lt;/strong&gt; instead. Everything the web app can do works in the popup, with the same session as your tabs.&lt;/p&gt;

&lt;p&gt;Two browser limits shaped the rest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A framed page gets its cookie only if the extension has host permission&lt;/strong&gt; for that site. That's why the extension asks to read app.agentrq.com (or your self-hosted server, which is asked for when you save it and given back when you switch away).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google and GitHub refuse to show sign-in inside a frame.&lt;/strong&gt; A signed-out popup opens sign-in in a tab, and once you're signed in there, the popup is too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chrome caps popups at 800×600 and closes them when you click away, so the popup is phone-sized (440×600). &lt;strong&gt;Full size&lt;/strong&gt; (Alt+Shift+F) opens the same app in a tab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 8: How do you replay a terminal that redraws itself 100 times a second?
&lt;/h3&gt;

&lt;p&gt;The terminal comes from a small daemon on each connected machine. It runs the agent in a pseudo-terminal (ConPTY on Windows, openpty everywhere else) and &lt;strong&gt;dials out&lt;/strong&gt; to the server. There are no inbound ports to open.&lt;/p&gt;

&lt;p&gt;The first instinct is to keep a ring buffer of output and replay it when someone opens the terminal. That fails with Claude Code, because a spinner or progress bar isn't much output. It's &lt;strong&gt;one line rewritten constantly&lt;/strong&gt;. 256 KiB of ring buffer becomes 256 KiB of the same line, and the history you cared about is gone. Replaying it in a fresh terminal shows a thousand frames of how the screen got there instead of what it shows now.&lt;/p&gt;

&lt;p&gt;So the daemon keeps &lt;strong&gt;its own terminal emulator&lt;/strong&gt; for each session and feeds it every byte, whether or not anyone is watching. When you open the terminal, it sends a &lt;strong&gt;redraw of the current screen&lt;/strong&gt;, the same thing tmux does when a second client attaches. A progress bar shows up looking like a progress bar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 9: How do you handle backpressure without corrupting the stream?
&lt;/h3&gt;

&lt;p&gt;"Drop the oldest bytes" is destructive for a terminal. The stream is stateful: drop an &lt;code&gt;ESC[0m&lt;/code&gt; and the colors stay wrong for the rest of the session, and drop half an escape sequence and the emulator parses garbage. So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Output is &lt;strong&gt;coalesced in 25 ms windows&lt;/strong&gt;, which is about one frame. A spinner redrawing 100 times a second becomes roughly 40 sends with no visible difference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No byte is ever dropped.&lt;/strong&gt; If the connection can't keep up, the pending batch is thrown away as a whole and replaced with a redraw of the screen. The viewer misses some in-between frames but always sees a correct screen.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenge 10: Why is input never batched?
&lt;/h3&gt;

&lt;p&gt;It's tempting to batch keystrokes the way output is batched. But that would add latency to every keypress, and it would &lt;strong&gt;merge a deliberate Esc with the next key into an escape sequence nobody typed&lt;/strong&gt;. Esc is how you interrupt Claude Code, so that can't happen.&lt;/p&gt;

&lt;p&gt;Every keystroke is sent the moment it's typed, as the exact bytes xterm.js produced: &lt;code&gt;0x1b&lt;/code&gt; for Esc, &lt;code&gt;\r&lt;/code&gt; for Enter, &lt;code&gt;ESC [ A&lt;/code&gt; for the up arrow. There is no list of "special keys". Any such list would be wrong for the next key combination someone needs, while a transparent byte pipe handles all of them.&lt;/p&gt;

&lt;p&gt;One rule here is about security. &lt;strong&gt;The browser doesn't choose which session it types into.&lt;/strong&gt; The server decides which session an attached viewer may drive and overwrites whatever session ID arrives. Otherwise, changing a number would let you type into someone else's agent.&lt;/p&gt;

&lt;p&gt;That rule came from a bug. The first version took the session ID from the caller and converted it with &lt;code&gt;BigInt&lt;/code&gt;, which throws on a base62 string. &lt;strong&gt;Every keystroke threw while output kept arriving&lt;/strong&gt;, so the terminal looked like it was ignoring the keyboard. The unit tests passed numeric IDs and never caught it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 11: Why did terminals sometimes go blank?
&lt;/h3&gt;

&lt;p&gt;Claude Code's interface is mostly box drawing. The DOM renderer asks the font for those glyphs, and the font we ship doesn't include them, so we use xterm's &lt;strong&gt;WebGL renderer&lt;/strong&gt;, which draws box characters itself. WebGL has two failure modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It fails late.&lt;/strong&gt; On VMs, GPU-less Chromium and machines with blocked drivers, it fails inside &lt;code&gt;activate()&lt;/code&gt;, not in the constructor. So each renderer is tried by actually loading it, and if one throws we move to the next. The last fallback is the plain DOM renderer, because a terminal that renders imperfectly beats one that renders nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It can lose its GPU context at any time&lt;/strong&gt;, through a driver reset, a laptop switching GPUs, or too many contexts in other tabs. Afterward it never draws again, and a blank terminal looks exactly like an agent that stopped. So we rebuild the renderer once. If the context is lost a second time, we drop to the next renderer and stay there, rather than burning GPU contexts in a loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What did we trade away?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your Chrome has to be open.&lt;/strong&gt; Calls run in your browser, so a closed laptop means the site is offline. We chose that over storing your credentials on a server. The agent gets a clear "offline" error rather than a hang.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It only works with sites that ship WebMCP.&lt;/strong&gt; It's an early standard and the list is short. agentrq.com offers three tools and the AgentRQ app exposes its own interface, so there's something to try today.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approvals add a human in the loop.&lt;/strong&gt; That's by design for writes, and "Always allow" per tool keeps it from getting in the way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The popup is small.&lt;/strong&gt; Chrome sets that limit. Full size is one shortcut away.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Which agents can call shared sites?&lt;/strong&gt; Any agent connected to the workspace over MCP, including Claude Code, Codex and Antigravity. There's nothing to install on the agent's side and no token to paste.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the extension read every page I visit?&lt;/strong&gt; Only with detection on, and even then it only checks whether the top frame registers WebMCP tools. Nothing is sent until you share a site. After that, only that site's tool list, its last address and the results of your agents' calls go to your AgentRQ server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I self-host?&lt;/strong&gt; Yes. Set your server's address in Options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it open source?&lt;/strong&gt; Yes. The extension, the daemon and the server are all in the &lt;a href="https://github.com/agentrq/agentrq" rel="noopener noreferrer"&gt;agentrq repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Install &lt;a href="https://chromewebstore.google.com/detail/agentrq/iadkenmjgjoilnioldgchgjpdnbaghbj" rel="noopener noreferrer"&gt;AgentRQ for Chrome&lt;/a&gt;, turn on detection, open agentrq.com, share it with a workspace, and ask Claude Code to search the docs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Over to you:&lt;/strong&gt; if your agents could call any site you're signed into, through tools the site chose to offer and with you approving every write, which site would you hand them first? And if you've built on WebMCP or MV3 service workers, which of these problems did you hit differently? Tell us in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://agentrq.com/blog/agentrq-chrome-extension-webmcp-bridge-for-local-and-remote-agents" rel="noopener noreferrer"&gt;AgentRQ blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>antigravity</category>
      <category>devtools</category>
      <category>webmcp</category>
    </item>
    <item>
      <title>Stop Overwriting Your AI Agent's Task Status: Why We Keep an Immutable State History</title>
      <dc:creator>Mustafa Turan</dc:creator>
      <pubDate>Wed, 30 Sep 2026 01:33:27 +0000</pubDate>
      <link>https://dev.to/agentrq/stop-overwriting-your-ai-agents-task-status-why-we-keep-an-immutable-state-history-159i</link>
      <guid>https://dev.to/agentrq/stop-overwriting-your-ai-agents-task-status-why-we-keep-an-immutable-state-history-159i</guid>
      <description>&lt;p&gt;An agent picks up a task, works on it, marks it &lt;code&gt;completed&lt;/code&gt;. You look at it the next morning.&lt;/p&gt;

&lt;p&gt;How long did it take? How much of that was the agent working, and how much was it waiting for you to click &lt;strong&gt;Allow&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;For a long time &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt; (an open-source task board and MCP server for Claude Code and other agents) couldn't tell you. A task had one status field, and every change overwrote it. &lt;code&gt;ongoing → blocked → ongoing → completed&lt;/code&gt;, and each write erased the one before. The end state was right. Everything in between was gone, and you can't get a duration out of a snapshot.&lt;/p&gt;

&lt;p&gt;We fixed that in &lt;a href="https://github.com/agentrq/agentrq/pull/756" rel="noopener noreferrer"&gt;agentrq/agentrq#756&lt;/a&gt;. This post isn't a code walkthrough. It covers the design decisions behind it, because I think they apply to anyone building agent tooling: why the history is &lt;strong&gt;immutable&lt;/strong&gt;, why the states are a &lt;strong&gt;fixed enum&lt;/strong&gt;, why there is exactly &lt;strong&gt;one writer&lt;/strong&gt;, and why the most useful state in the timeline is one the task can never actually be in, and how it all rolls up into a p50 dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep the current status for everything that asks "what is this task now?", and add an &lt;strong&gt;immutable, append-only history&lt;/strong&gt; beside it for "how did it get here?"&lt;/li&gt;
&lt;li&gt;Immutability is what makes the numbers trustworthy: nobody, not the agent, not a person, not a bug, can rewrite how long something took.&lt;/li&gt;
&lt;li&gt;States are a &lt;strong&gt;closed enum that only ever grows at the end&lt;/strong&gt;, so a row written today means the same thing in five years.&lt;/li&gt;
&lt;li&gt;"Waiting on the human" is a &lt;strong&gt;derived, history-only state&lt;/strong&gt;. It never becomes the task's status, so nothing else in the system behaves differently.&lt;/li&gt;
&lt;li&gt;The same history rolls up into a &lt;strong&gt;stats dashboard&lt;/strong&gt;: p50, min and max of start to close, worked, blocked and needs input, per workspace and across the account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why is overwriting a status the wrong model for agent work?
&lt;/h2&gt;

&lt;p&gt;Because the interesting question about agent work is almost never "is it done?" It's "where did the time go?"&lt;/p&gt;

&lt;p&gt;With a human ticket, you can ask the assignee. With an agent, the only record is what the system kept. If the system kept one mutable field, you have a photograph, not a film.&lt;/p&gt;

&lt;p&gt;It's the event-sourcing lesson in miniature: &lt;strong&gt;the current state is a projection; the transitions are the data.&lt;/strong&gt; Keep the transitions and you can always work out the state. Keep only the state and the transitions are lost for good.&lt;/p&gt;

&lt;p&gt;We didn't go full event sourcing, though. The task's status stays the source of truth for "what is it now", because a lot of the system reads it: the work queue agents pull from, filters, counts, and the MCP tools agents call. We didn't want to touch any of that. The history sits beside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does "immutable history" mean here?
&lt;/h2&gt;

&lt;p&gt;Every status change appends one record: the state the task came from, the state it went to, when, and which agent (and model) made the change. That's it. A record is never edited after it's written, and nothing is ever inserted into the past.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;not started   09:00  ─┐ 6m
ongoing       09:06  ─┤ 24m
needs input   09:30  ─┤ 8m
ongoing       09:38  ─┤ 31m
blocked       10:09  ─┤ 38m
ongoing       10:47  ─┤ 19m
completed     11:06  ─┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A state lasts from its record to the next one. The state the task is in right now lasts until "now", so it keeps counting.&lt;/p&gt;

&lt;p&gt;Two honest caveats about "immutable": if you move a task to another workspace, its history moves with it, and if you delete a task, its history goes too. What never changes is the content of a record: which states, and when.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does immutability matter so much for agents?
&lt;/h2&gt;

&lt;p&gt;Three reasons, in order of how much they bit us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The numbers have to be trustworthy, or they're useless.&lt;/strong&gt; The whole point of the timeline is to answer questions like "is this class of work worth handing to an agent?" and "am I the bottleneck?". If records could be edited, every number derived from them would be an opinion. Append-only means the only way to change the story is to add to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Agents write status too, and they're not always right.&lt;/strong&gt; An agent might mark a task &lt;code&gt;completed&lt;/code&gt;, then get reopened by a person, then complete it again. With an overwritten field, the final &lt;code&gt;completed&lt;/code&gt; is all you see. With an immutable history, the false finish is on the record, with its time. That's exactly the kind of thing you want to spot when you're tuning a prompt or a workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. It makes concurrent writers boring.&lt;/strong&gt; An agent and a person can move the same task at the same moment: the agent marks it &lt;code&gt;completed&lt;/code&gt; while you click &lt;strong&gt;Reject&lt;/strong&gt;. With an append-only log, there's nothing to merge. Both changes are recorded in the order they happened, and each record says where it came from. (We do lock the task while recording, so the second change sees the first one's result as its starting point.)&lt;/p&gt;

&lt;p&gt;There's a fourth, quieter benefit: the conversation got cleaner. Every status change used to drop a "Status updated to …" line into the task thread, which buried the messages that mattered. With the history in its own place, those lines are gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are the states an enum instead of free-form strings?
&lt;/h2&gt;

&lt;p&gt;This looks like a small decision. In an immutable log it's a big one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A record written today has to mean the same thing forever.&lt;/strong&gt; Free-form strings drift. Someone writes &lt;code&gt;complete&lt;/code&gt; instead of &lt;code&gt;completed&lt;/code&gt;, a state gets renamed, a new client sends &lt;code&gt;in_progress&lt;/code&gt;. In a mutable column you can fix that with a migration. In an append-only history, "fixing" old records is exactly what you promised never to do. So the set of states is &lt;strong&gt;closed&lt;/strong&gt;: not started, ongoing, blocked, needs input, completed, rejected, and scheduled (cron). Nothing outside that set can be recorded as itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The enum only ever grows at the end.&lt;/strong&gt; Each state is stored as a small number, and new states are appended after the existing ones, never inserted in between or reordered. Reordering would silently change the meaning of every record already written, so it's the one rule that can't be broken. "Needs input" was added exactly this way, as the last value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There's an explicit "none" state.&lt;/strong&gt; When a task is created, the first record goes from "none" to its first status. That gives the first segment a start time, and it gives any unrecognised status somewhere safe to land instead of failing the write.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Numbers inside, names outside.&lt;/strong&gt; Storage uses the compact number, because this history grows with every status change on every task and the workspace stats pages aggregate over it. Everything outside the backend, including the API, the UI and the agents, sees the readable names. The mapping lives in one place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is there only one writer?
&lt;/h2&gt;

&lt;p&gt;Because a history that some code paths forget to write is worse than no history: it looks complete and isn't.&lt;/p&gt;

&lt;p&gt;Status changes come from everywhere: the MCP tools agents call, the web app, the CLI, scheduled tasks, events that create tasks in other workspaces. Instead of asking each of those to remember to record a transition, the record is written in &lt;strong&gt;one place&lt;/strong&gt;, the storage layer's task save, and &lt;strong&gt;in the same transaction&lt;/strong&gt; as the status change itself.&lt;/p&gt;

&lt;p&gt;That gives two guarantees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No status change without a record.&lt;/strong&gt; If recording fails, the status change rolls back. You never see a task that says &lt;code&gt;completed&lt;/code&gt; with no trace of how it got there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No record without a status change.&lt;/strong&gt; Saving a task for any other reason (a new title, a new description) adds nothing to the history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything above the storage layer sets the status and saves, as it always did. It doesn't know the history exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is "needs input" a state the task can never be in?
&lt;/h2&gt;

&lt;p&gt;This is the part I'd steal if I were building something similar.&lt;/p&gt;

&lt;p&gt;When an agent asks the person something through AgentRQ (a permission request before running a command, or a form question), the task is waiting &lt;strong&gt;on the human&lt;/strong&gt;. That's a different kind of wait from &lt;code&gt;blocked&lt;/code&gt;, where the agent hit a wall and said so. They call for opposite fixes, so they deserve separate numbers.&lt;/p&gt;

&lt;p&gt;The obvious implementation is a new status. We didn't do that. Agents read and write the status, the work queue hands out tasks based on it, and filters and counters group by it. A new value would change behaviour in all of those places: an agent looking up its ongoing tasks could suddenly miss the one it is in the middle of.&lt;/p&gt;

&lt;p&gt;So "needs input" is &lt;strong&gt;derived, and it only exists in the history&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;While any question in the task's thread is still waiting for an answer, the history records the task as &lt;strong&gt;needs input&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;When the last one is answered, the history moves it back to whatever its real status is.&lt;/li&gt;
&lt;li&gt;The task's own status stays &lt;code&gt;ongoing&lt;/code&gt; the whole time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few rules made it correct:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It counts open questions, it doesn't toggle.&lt;/strong&gt; An agent can have two permission requests open at once. Answering the first must not end the wait.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only real questions count.&lt;/strong&gt; An agent's plan has to-do items that are "pending" too, but a to-do isn't a question to anyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Closed means closed.&lt;/strong&gt; A question arriving on a completed task doesn't reopen its history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the status never changes, nothing that reads it behaves any differently. Only the timeline and the totals know.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it look like?
&lt;/h2&gt;

&lt;p&gt;Under each task's description there's now a &lt;a href="https://agentrq.com/features/task-timeline" rel="noopener noreferrer"&gt;task timeline&lt;/a&gt;: one dot per state, with the time spent in each on the line between two dots, and the totals above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F822wr0t1zz1ibylc9ufe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F822wr0t1zz1ibylc9ufe.png" alt="A completed AgentRQ task with its timeline under the description: not started 6m, ongoing 24m, needs input 8m, ongoing 31m, blocked 38m, ongoing 19m, completed. The totals above read worked 1h 14m, blocked 38m, needs input 8m, start to close 2h" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Worked&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1h 14m&lt;/td&gt;
&lt;td&gt;All the time the agent was &lt;code&gt;ongoing&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Blocked&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;38m&lt;/td&gt;
&lt;td&gt;All the time the agent said it couldn't go on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Needs input&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;8m&lt;/td&gt;
&lt;td&gt;All the time a question to the person was open&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Start to close&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2h&lt;/td&gt;
&lt;td&gt;From the &lt;strong&gt;first&lt;/strong&gt; &lt;code&gt;ongoing&lt;/code&gt; to completed or rejected&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Start to close begins at the first &lt;code&gt;ongoing&lt;/code&gt;, not at creation, on purpose. A task that sat in the queue overnight shouldn't look like an agent that took twelve hours.&lt;/p&gt;

&lt;p&gt;An open task keeps ticking. Here the agent is waiting on a permission prompt, so the last dot is yellow and counting, and there's no start to close yet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd37ay0wf0gy49h57f3xm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd37ay0wf0gy49h57f3xm.png" alt="An ongoing task in dark mode, waiting on a permission request. The timeline ends on a pulsing yellow " width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A small consistency detail: the page works out the totals from the same segments it draws, instead of showing the server's numbers next to a bar it animates itself. Otherwise the live counter and the bar would drift apart every second. The server's totals are still in the API for scripts, agents and the stats pages.&lt;/p&gt;

&lt;p&gt;On a phone it collapses to one line, the dots and the total:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjotzo5we9l1k1u8438ps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjotzo5we9l1k1u8438ps.png" alt="Two phone screenshots side by side. Left, light mode: a single-line timeline ending on a yellow needs-input dot at 4m, total 45m, above a permission request. Right, dark mode: a completed task's single-line timeline, total 2h" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How does the dashboard tell the story across every task?
&lt;/h2&gt;

&lt;p&gt;One task's timeline tells you what happened to that task. It doesn't tell you whether that was normal. Is two hours usual for this workspace? Did this week go faster than last? Do agents sit blocked longer in one workspace than another?&lt;/p&gt;

&lt;p&gt;So the history feeds a second view: a &lt;strong&gt;Task Latency&lt;/strong&gt; panel on each workspace's stats page and on the account stats page. It charts the same four totals, in minutes, over every task closed in the range you pick, with a toggle between &lt;strong&gt;P50&lt;/strong&gt; (the typical task), &lt;strong&gt;Min&lt;/strong&gt; (the quickest) and &lt;strong&gt;Max&lt;/strong&gt; (the slowest).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzhdpxzqfm1sn7oijvhyy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzhdpxzqfm1sn7oijvhyy.png" alt="The Task Latency panel on a workspace stats page in light mode. Four summary cards on the left read start to close 108 min, worked 66 min, blocked 19 min and needs input 7 min, over 42 tasks. The chart on the right has one line per value from Sep 21 to Sep 27, and the tooltip for Sep 24 reads 9 closed: start to close 150 min, worked 94 min, blocked 46 min, needs input 17 min" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read the cards like a story. This workspace closed 42 tasks in the week. At p50, a task took &lt;strong&gt;108 minutes&lt;/strong&gt; start to close, of which &lt;strong&gt;66&lt;/strong&gt; were work, &lt;strong&gt;19&lt;/strong&gt; were blocked and &lt;strong&gt;7&lt;/strong&gt; were waiting on a person. (Each line is its own median, so they don't add up exactly, and they aren't meant to.) Hover over Sep 24 and the typical task took 150 minutes, well above the week's figure. That's the day to go and look at.&lt;/p&gt;

&lt;p&gt;The account page shows the same panel across every workspace:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr6l8cf7eb2qsuixlex7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr6l8cf7eb2qsuixlex7c.png" alt="The same Task Latency panel on the account stats page in dark mode, covering 126 closed tasks: start to close 146 min, worked 89 min, blocked 26 min, needs input 9.5 min. The tooltip for Sep 24 reads 27 closed: start to close 203 min, worked 127 min, blocked 62 min, needs input 23 min" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Across the account the typical task took 146 minutes and was blocked for 26 of them. The workspace above beats both, so something else is pulling the account figure up, and you know where to look next.&lt;/p&gt;

&lt;p&gt;The design decisions behind the numbers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why p50 and not the average?&lt;/strong&gt; Agent task durations have a long tail. One task that sat blocked over a weekend turns a 30-minute average into a 3-hour one, and then the average describes no task you actually ran. The median is the task you'd typically get. Min and max sit next to it on purpose: max finds the one that dragged, and min shows how fast the work goes when nothing gets in the way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why an estimated p50?&lt;/strong&gt; Stats are rolled up per hour, per day and per month, so a three-month chart doesn't re-read every task. But medians don't add up. You can't combine two hours' medians into a day's median. So each rollup keeps a small &lt;strong&gt;histogram&lt;/strong&gt; of durations with fixed, log-spaced buckets: under a minute, 1–2 minutes, 2–5 minutes, and so on through hours and days, up to over 30 days. Histograms merge by adding counts. The p50 is read back out of the merged histogram, interpolated inside the bucket where the median falls, and clamped between the exact min and max, which merge perfectly. It's an estimate, and it's exact when a bucket holds a single task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The histogram buckets are immutable too.&lt;/strong&gt; Same lesson as the state enum: counts are stored by position, so the bucket edges can never be changed or reordered. A finer histogram would be a new field, not an edit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One arithmetic, two views.&lt;/strong&gt; The task page and the dashboard compute durations with the same function over the same history, so a task's timeline and its contribution to the chart can never disagree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every close counts once.&lt;/strong&gt; When a task closes, its totals are recorded in the same transaction that closes it. If it's reopened and closed again, its totals are recalculated over its whole history, but a period that was already rolled up isn't rewritten. Each close counts once, in the period it happened in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero is data; nothing is a gap.&lt;/strong&gt; A task that was never blocked counts as 0 minutes blocked, so the blocked line shows how much blocking a typical task really sees, not just the unlucky ones. But a day with &lt;strong&gt;no&lt;/strong&gt; closed tasks is left as a gap in the line, not drawn as zero, so a quiet day never looks like a fast one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The resolution follows the range.&lt;/strong&gt; A day or two plots by the hour, up to about three months by the day, and anything longer by the month. All in UTC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agents can read it too.&lt;/strong&gt; The same figures are available to an agent, so you can ask one to watch for a workspace whose blocked time is creeping up, or to report how long its own work took this week.&lt;/p&gt;

&lt;p&gt;It shipped as a follow-up, in &lt;a href="https://github.com/agentrq/agentrq/pull/758" rel="noopener noreferrer"&gt;agentrq/agentrq#758&lt;/a&gt;. The full tour is in &lt;a href="https://agentrq.com/blog/task-latency-statistics-for-ai-agent-workspaces" rel="noopener noreferrer"&gt;Task Latency: How Long Your Agents' Tasks Take&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it unlock?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"How long did that take?" finally has an answer.&lt;/strong&gt; Start to close per task is the number you want when you decide whether a class of work is worth handing to an agent at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent time vs. your time.&lt;/strong&gt; A two-hour task might be two hours of work, or twenty minutes of work plus an hour and forty minutes waiting on a permission prompt. The first means the task is big. The second means the human is the bottleneck, and the fix is a broader permission rule, a better prompt, or handing it off at a different time of day. Worked and needs input are separate numbers, so you know which one you have.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blocked stops being invisible.&lt;/strong&gt; Before, you saw a blocked task only if you looked while it was blocked. Now every blocked stretch stays on the record with its length, and the dashboard shows which workspace keeps getting stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improvements become measurable.&lt;/strong&gt; Change a prompt, a skill or a workflow, and watch whether the typical start to close drops the next week. One fast task proves nothing. A p50 over a week of tasks does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the trade-offs?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No backfill of history.&lt;/strong&gt; History that was never recorded can't be rebuilt. Existing tasks start their timeline at their next status change. (The dashboard does backfill from whatever history exists, once, on the first boot after the upgrade.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;p50 is an estimate.&lt;/strong&gt; It comes from a mergeable histogram, not from sorting every task. That's the price of rolling up months of data cheaply.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One more write per status change.&lt;/strong&gt; It's small, and it happens inside a transaction we were already opening.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A derived state depends on every path that can answer a question.&lt;/strong&gt; "Needs input" is right only because every way a question gets asked or answered re-checks it. That's why the logic lives in the storage layer and not in the individual features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The enum is a one-way door.&lt;/strong&gt; You can add states. You can never remove, rename or reorder the stored ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why not full event sourcing?&lt;/strong&gt;&lt;br&gt;
Too much for this. The status is read in many places, including by agents over MCP. An append-only history &lt;strong&gt;beside&lt;/strong&gt; the current status gets the durations without migrating every reader.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not work out durations from the message thread?&lt;/strong&gt;&lt;br&gt;
Messages and status changes are different streams. An agent can go blocked without writing anything, and a quiet agent can be working for 30 minutes. A dedicated history records exactly what changed and when.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does "needs input" change a task's status?&lt;/strong&gt;&lt;br&gt;
No. It exists only in the history. Queues, counts, filters and agents see the same status as before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does the dashboard show p50 instead of the average?&lt;/strong&gt;&lt;br&gt;
Agent task durations have a long tail. One task blocked over a weekend drags the average far from anything typical. The median doesn't move, and max is right next to it for finding the outlier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which states can appear?&lt;/strong&gt;&lt;br&gt;
Not started, ongoing, blocked, needs input, completed, rejected, and scheduled for &lt;a href="https://agentrq.com/features/task-scheduling" rel="noopener noreferrer"&gt;recurring or one-time scheduled tasks&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The change is in &lt;a href="https://github.com/agentrq/agentrq/pull/756" rel="noopener noreferrer"&gt;agentrq/agentrq#756&lt;/a&gt;, and the &lt;a href="https://agentrq.com/features/task-timeline" rel="noopener noreferrer"&gt;Task Timeline feature page&lt;/a&gt; has the short tour. Open any task that has changed status since the update and look under the description.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question for you:&lt;/strong&gt; if you run agents against a task queue, how do you tell "the agent was slow" from "I was slow"? Do you track human wait time separately, or does it all go into one latency number?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://agentrq.com/blog/task-status-history-timeline-for-ai-agent-tasks" rel="noopener noreferrer"&gt;AgentRQ blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>observability</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Single Responsibility for AI Agents: One Workspace, One Job</title>
      <dc:creator>Mustafa Turan</dc:creator>
      <pubDate>Mon, 28 Sep 2026 04:29:21 +0000</pubDate>
      <link>https://dev.to/agentrq/single-responsibility-for-ai-agents-one-workspace-one-job-3532</link>
      <guid>https://dev.to/agentrq/single-responsibility-for-ai-agents-one-workspace-one-job-3532</guid>
      <description>&lt;p&gt;You would never ship a &lt;code&gt;God&lt;/code&gt; class that handles billing, email templates, database migrations and the marketing site. So why do so many of us run exactly that as an AI agent?&lt;/p&gt;

&lt;p&gt;I did, for months. One agent, one workspace, every repository, every note I had ever written, and a mission description trying to cover a whole company. It was never bad. It was never great at anything either. It wrote landing page copy in the tone of a commit message. It suggested a database migration in the middle of a blog post. It applied a rule from one project to another where that rule was flat-out wrong.&lt;/p&gt;

&lt;p&gt;So I refactored it the way I would refactor code: &lt;strong&gt;one workspace, one job.&lt;/strong&gt; This post covers what that means in practice, the two reasons it works, how isolated agents still collaborate (pub/sub, not DMs), and the places where I think you should disagree with me.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AI agent's memory is only useful if every note in it is true for every task it runs. Mixing jobs breaks that.&lt;/li&gt;
&lt;li&gt;Everything an agent loads at the start of a task, it pays for on every turn. A narrow job means a small starting context.&lt;/li&gt;
&lt;li&gt;Isolated workspaces coordinate through &lt;strong&gt;events&lt;/strong&gt; (publish/subscribe) and one &lt;strong&gt;supervisor&lt;/strong&gt; agent, never agent-to-agent messages.&lt;/li&gt;
&lt;li&gt;Split where the knowledge diverges, not where the task names differ.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is an isolated, single-purpose AI agent workspace?
&lt;/h2&gt;

&lt;p&gt;I build &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;AgentRQ&lt;/a&gt;, so that is the vocabulary I will use, but the idea is tool-agnostic. A &lt;strong&gt;workspace&lt;/strong&gt; is the unit an agent connects to. It holds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;mission&lt;/strong&gt; the agent reads when it starts a task,&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;task board&lt;/strong&gt; with the history of every job,&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;memory&lt;/strong&gt; the agent reads and writes (&lt;code&gt;loadMemory&lt;/code&gt; / &lt;code&gt;saveMemory&lt;/code&gt; over MCP),&lt;/li&gt;
&lt;li&gt;a set of &lt;strong&gt;skills&lt;/strong&gt; it can search and load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Single-purpose" is just a discipline on top: one workspace, one definition of done. Not "engineering". Something closer to "the static marketing site and its SEO content." If you can't describe success in one sentence, the scope is too wide.&lt;/p&gt;

&lt;p&gt;Today I run a handful: static site, core app, QA, support, social, outreach. They don't know about each other. That is the point.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21pu7vnaki0ofrkrv5a1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21pu7vnaki0ofrkrv5a1.png" alt="Four isolated AgentRQ workspaces (static site, core app, outreach and support), each with its own memory and skills" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does a shared workspace make AI agent memory go bad?
&lt;/h2&gt;

&lt;p&gt;This is the part I underestimated most.&lt;/p&gt;

&lt;p&gt;Agent memory rots in a specific way when jobs share it: a lesson that is true in one context gets applied in another where it is false.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app repo:     "Always run the migration before deploying."   ✅ gospel
# static site:  "Always run the migration before deploying."   ❌ nonsense

# static site:  "The Markdown converter has no italics; use bold."  ✅ vital
# app repo:     "The Markdown converter has no italics; use bold."  🤷 noise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put both in one pile and the agent has to guess which rules apply, on every task. Sometimes it guesses wrong, confidently. It's the agent equivalent of a global mutable config shared between services.&lt;/p&gt;

&lt;p&gt;In a single-purpose workspace, every note is about the same system. The workspace that builds our site has a memory index of about forty entries, and every one of them is about that site: the converter has no italics or blockquotes, headings render as plain text, the CSS hash changes on every build and that diff churn is expected, slugs should be long and descriptive. None of those would survive contact with another project. Here, all of them are simply true.&lt;/p&gt;

&lt;p&gt;Two side effects I didn't expect:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The agent writes memory freely.&lt;/strong&gt; I don't have to curate defensively, wondering whether a note will leak into the wrong context. The agent writes down whatever would have saved it a detour, and the next run skips the detour. Learning compounds instead of colliding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I can actually review it.&lt;/strong&gt; Opening one workspace's memory is reading the operating manual for one job. I can spot a wrong note in a minute. A mixed memory is a junk drawer, and nobody audits a junk drawer.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How much context does an AI agent really need to start a task?
&lt;/h2&gt;

&lt;p&gt;Only what the job needs, and the difference adds up.&lt;/p&gt;

&lt;p&gt;Before an agent does any work, the mission, the memory index, the skill descriptions and the instructions all go into its context window. In a stateless tool-calling loop, that prefix is re-sent on every turn.&lt;/p&gt;

&lt;p&gt;A do-everything workspace has a do-everything prefix. The mission explains five businesses. The memory index lists notes for all of them. The skill list offers a release playbook to an agent writing a tweet. Most of it is noise for the task at hand.&lt;/p&gt;

&lt;p&gt;A single-purpose workspace starts smaller because there is less to say. I haven't benchmarked the exact saving (it depends entirely on how big your notes get and how long your tasks run), so I won't invent a number. The shape is simple arithmetic, though:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cost ≈ starting_context × turns + work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Shrink the first term and you save on every turn of every task.&lt;/p&gt;

&lt;p&gt;Tokens are the smaller half. The bigger half is &lt;strong&gt;attention&lt;/strong&gt;: an agent whose window is full of relevant context makes better decisions than one that has to ignore half of what it was handed. I pair this with &lt;a href="https://agentrq.com/features/clear-context" rel="noopener noreferrer"&gt;Clear Context&lt;/a&gt;, which starts every task on a clean window, for the same reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do isolated AI agents collaborate without sharing context?
&lt;/h2&gt;

&lt;p&gt;The obvious objection: a feature has to be built, tested, released, written up and announced. No single workspace owns all of that.&lt;/p&gt;

&lt;p&gt;The workspaces are isolated from each other's &lt;strong&gt;context&lt;/strong&gt;, not from each other's &lt;strong&gt;work&lt;/strong&gt;. They coordinate in two ways, and neither involves one agent reading another's memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. A supervisor agent that sees everything
&lt;/h3&gt;

&lt;p&gt;One &lt;a href="https://agentrq.com/blog/supervisor-worker-agentic-system" rel="noopener noreferrer"&gt;supervisor agent&lt;/a&gt; connects to an account-wide &lt;a href="https://agentrq.com/docs/supervisor-mcp" rel="noopener noreferrer"&gt;Supervisor MCP&lt;/a&gt; instead of a single workspace. It can see every workspace, task and status; create tasks anywhere; and move a task that landed in the wrong place.&lt;/p&gt;

&lt;p&gt;When I want a feature shipped end to end, I brief the supervisor once. It hands the core app its half, the static site its half, and outreach its half, each written for that workspace. The workers stay narrow; the supervisor is the one place allowed to be broad. And it has a single job too: dispatching, not doing.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Events, not direct messages
&lt;/h3&gt;

&lt;p&gt;For routine hand-offs I don't want a supervisor in the middle. The workspaces talk through &lt;a href="https://agentrq.com/features/events" rel="noopener noreferrer"&gt;events&lt;/a&gt;, which is plain publish/subscribe:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A workspace finishes something and publishes a named event with a short payload.&lt;/li&gt;
&lt;li&gt;AgentRQ finds every trigger subscribed to that name.&lt;/li&gt;
&lt;li&gt;Each subscribed workspace gets a new task, with the payload in the task body.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The publisher doesn't know who is listening. The listeners don't know who published. &lt;strong&gt;The event name is the only contract.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are the events my workspaces actually run on:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Published when&lt;/th&gt;
&lt;th&gt;Who picks it up&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;code_changed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Core app merges a change&lt;/td&gt;
&lt;td&gt;QA runs its checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;qa_failed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;QA finds a regression&lt;/td&gt;
&lt;td&gt;Core app gets a fix task, failure attached&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bug_fixed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Core app lands the fix&lt;/td&gt;
&lt;td&gt;QA re-checks, Support tells the reporter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feature_released&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A release goes out&lt;/td&gt;
&lt;td&gt;Static site drafts a post, updates feature pages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;blog_published&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A post goes live&lt;/td&gt;
&lt;td&gt;Social turns it into an X thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;x_thread_created&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The thread is posted&lt;/td&gt;
&lt;td&gt;Outreach adds it to follow-ups&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every name is &lt;strong&gt;past tense&lt;/strong&gt;, on purpose. An event reports a fact any workspace can react to in its own way. &lt;code&gt;fix_the_bug&lt;/code&gt; would be a command aimed at one agent, which is just a direct message wearing an event's name.&lt;/p&gt;

&lt;p&gt;A trigger can also name the event to fire when its task completes, so the chain wires itself. Here is the release part of it as a &lt;a href="https://agentrq.com/features/workflows" rel="noopener noreferrer"&gt;workflow&lt;/a&gt; called &lt;code&gt;release_cycle&lt;/code&gt;, spanning five workspaces. Note the fan-out on &lt;code&gt;bug_fixed&lt;/code&gt;: Support notifies reporters while Core App cuts the release, in parallel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm2uhqpb2lqzmuq4ct01r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm2uhqpb2lqzmuq4ct01r.png" alt="The release_cycle workflow in AgentRQ: code_changed starts QA, which emits qa_failed; Core App fixes it and emits bug_fixed, which fans out to Support and to Core App cutting the release; feature_released starts Static Site, which emits blog_published; Social turns it into an X thread and emits x_thread_created" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I ran it once on a local dev build to check it behaves like the table says. I created exactly one task, a Core App merge that published &lt;code&gt;code_changed&lt;/code&gt;. Every task after that was created by an event. Each workspace did its part over its own connection, knowing only its own mission:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F37u6xgdqxyplmvp4zk58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F37u6xgdqxyplmvp4zk58.png" alt="Tasks from one run of the release_cycle workflow, all completed: the Core App merge, QA's regression check, the Core App fix, the Support reply, the release, the Static Site post and the Social X thread" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outreach isn't even in that workflow. It subscribes to &lt;code&gt;x_thread_created&lt;/code&gt; on its own. The chain grows at the edges without anyone rewiring the middle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not just let agents message each other?
&lt;/h3&gt;

&lt;p&gt;Same reason you put a queue between microservices instead of having every service call every other one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coupling.&lt;/strong&gt; An agent that can DM any other agent has to know who they all are and what each does. That is exactly the cross-domain context I kept out of its window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combinatorics.&lt;/strong&gt; Point-to-point links grow as &lt;code&gt;n(n-1)/2&lt;/code&gt;. Five workspaces is already 10 conversations to keep straight, each a place for a request to get lost or answered twice. With events, adding a sixth workspace is one new trigger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability.&lt;/strong&gt; Every hand-off is a task with a title, a body describing what happened upstream, and a status on the board. When a chain breaks, I'm reading tasks, not reconstructing a group chat between bots.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What does isolating AI agents actually unlock?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agents get good at one job and stay good.&lt;/strong&gt; The workspace that runs our site has closed more than ninety tasks, and lessons from the first ones are still in its memory, still true, still read before every new task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegation without re-explaining.&lt;/strong&gt; I send a one-paragraph brief from my phone. The workspace already knows the tone, the build steps, the formatting quirks and what I rejected last time. That's the difference between delegating a task and babysitting one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A small blast radius.&lt;/strong&gt; A bad note or a confused agent can only damage one job. When outreach learns something wrong, the release process doesn't notice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cheap agent swaps.&lt;/strong&gt; The knowledge lives in the workspace, not in one vendor's config file. Point a different coding agent at the workspace and it inherits the mission, memory and skills on day one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The pitfalls I actually hit
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Going too narrow.&lt;/strong&gt; After the first split I split everything: blog posts, glossary terms, feature pages, each in its own workspace. Same repo, same build, same quirks, and I was teaching three agents the same lessons. The rule now: &lt;strong&gt;split where the knowledge diverges, not where the task names do.&lt;/strong&gt; If two jobs would write the same notes, they belong together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Genuinely shared knowledge.&lt;/strong&gt; Some rules are universal: how PRs are described, which branch never gets a direct push. Copying them into every workspace is the same rot, spread thinner. Keep memory for what's local and put what's universal in something shared. In AgentRQ that's &lt;a href="https://agentrq.com/blog/distributed-agent-skills-over-mcp-across-workspaces" rel="noopener noreferrer"&gt;skills shared across workspaces&lt;/a&gt;: fix a playbook once, fixed everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Work that crosses the line.&lt;/strong&gt; A launch needs code in the app and a post on the site. I don't create a third workspace; I split it into two tasks, via the supervisor or a &lt;code&gt;feature_released&lt;/code&gt; event. A task that lands in the wrong workspace gets moved, with its history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory still goes stale.&lt;/strong&gt; Isolation keeps memory &lt;em&gt;relevant&lt;/em&gt;, not &lt;em&gt;current&lt;/em&gt;. Tools get upgraded, a limitation gets fixed, and the note warning about it becomes a lie. Tell the agent to correct or delete a note when it finds one that no longer holds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup cost.&lt;/strong&gt; A new workspace needs a mission, a connected agent and a few tasks before its memory is worth anything. Isolation pays back on work that repeats, not on one-offs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where you should push back
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Context windows are huge now, just give it everything."&lt;/strong&gt; Windows have grown, and strong models ignore a lot of noise. But every token is still billed on every turn, and ignoring noise is a skill models have, not one they are perfect at. If your contexts are small and cost isn't a concern, this argument carries real weight.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"A generalist sees connections a specialist misses."&lt;/strong&gt; The strongest objection, and true. My narrow workspaces will never notice on their own that a new feature deserves a post. The supervisor and events cover the connections I already know about, but a dispatcher over narrow workers isn't one mind holding everything. If cross-domain insight is your main value, a generalist may serve you better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Just use retrieval over one big memory."&lt;/strong&gt; Works when retrieval is good; fails &lt;em&gt;quietly&lt;/em&gt; when it isn't. The wrong note ranks high and the agent acts on it. Isolation is blunter, but it fails &lt;em&gt;loudly&lt;/em&gt;: you can always see which workspace you are in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Overkill for small projects."&lt;/strong&gt; Often, yes. One repo and one kind of work? One workspace &lt;em&gt;is&lt;/em&gt; the single-purpose workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Teams need shared context, not silos."&lt;/strong&gt; For teams, boundaries should follow ownership and on-call lines, not one person's mental model. What I describe is shaped for one person running many jobs.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is a single-purpose AI agent workspace?&lt;/strong&gt;&lt;br&gt;
A workspace scoped to one job with one definition of done, holding its own mission, memory, skills and task history, so an agent working in it only ever loads context that is relevant to that job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does isolating AI agents reduce token usage?&lt;/strong&gt;&lt;br&gt;
Usually. The mission, memory index and skill list are loaded at the start of every task and re-sent on every turn, so a narrower workspace means a smaller fixed cost per turn. The exact saving depends on your notes and task length.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do isolated AI agents hand off work?&lt;/strong&gt;&lt;br&gt;
Through publish/subscribe events (a workspace publishes a past-tense event like &lt;code&gt;bug_fixed&lt;/code&gt;; subscribed workspaces receive a new task) or through a supervisor agent with account-wide visibility that creates tasks in each workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should I keep one workspace instead of splitting?&lt;/strong&gt;&lt;br&gt;
When every note in your agent's memory is true for every task it runs. If you catch yourself writing "except in the other project" into a note, that workspace probably wants to become two.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it on one job
&lt;/h2&gt;

&lt;p&gt;None of this is a law. It's the setup that fits one person running many unrelated jobs and wanting to delegate and walk away. I know people who run one giant workspace very productively, people who spin up a workspace per feature and throw it away on ship, and teams who isolate by customer instead of function.&lt;/p&gt;

&lt;p&gt;So take the question, not my answer: &lt;strong&gt;is every note in your agent's memory true for every task it will run?&lt;/strong&gt; If not, split one job out, give it a week of tasks, and read its memory at the end.&lt;/p&gt;

&lt;p&gt;How do you scope your agents: one generalist, many specialists, or something else? I'd like to hear what's working for you in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on the &lt;a href="https://agentrq.com/blog/why-i-use-isolated-single-purpose-workspaces-for-ai-agents" rel="noopener noreferrer"&gt;AgentRQ blog&lt;/a&gt;. AgentRQ is a human-in-the-loop task manager for AI agents: &lt;a href="https://agentrq.com" rel="noopener noreferrer"&gt;agentrq.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>architecture</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
