Plugin agent safety floor (what a plugin's AI agents can and cannot do)
Every new AI agent session a plugin starts runs locked down by default: none of your own setup, a folder of its own, Claude-family engines only, and never more tools than the plugin was granted. A hidden background session answers in text (or searches the web if its plugin asks), and a visible one asks you before every command and web request. Two switches give a plugin more: one in Settings → Plugins, one on the plugin's Marketplace card. You or an agent can change them; a plugin can't.
What it is
Some plugins start their own AI agents to do work for you: building a deck, working on a form response, or fixing a GitHub issue. To do that work, a plugin hands its agent content from outside: a form answer, a web page, an email, an issue. Anyone can write that content. A hidden instruction inside it could try to steer the agent, for example into running a command on your computer. An agent with your full setup and access would be a real risk.
So every AI agent session a plugin starts runs on a safety floor: a locked-down setup that gives it only what its job needs. The floor is on by default, for every plugin. It is written onto the session once, when the session is created, and it holds for the session's whole life, so a restart, a resume or a later message never brings it back with more power. Only its two switches loosen it, for one plugin or for all of them.
On the floor, a plugin's agent:
- gets none of your own setup: not your instructions, memory, skills, hooks, saved permission rules or add-on tool servers;
- gets none of the app's extra add-ons for ordinary sessions either, such as its standing reminders and extra tool servers;
- works in its own folder, kept outside the app's data folder;
- runs only on a Claude-family engine: Claude, or a Claude-compatible engine such as DeepSeek or GLM;
- runs only on this computer, never over SSH or in the cloud;
- has only the tools its job needs, as the next sections explain, and never more than the plugin's own install granted.
The floor only ever narrows what a plugin already had. A plugin that was never granted tools when you installed it still gets no tools on the floor.
Sessions you start yourself are not plugin agents, so the floor does not touch them. That includes a session you start with + New session in a plugin's Sessions pane, and a draft a plugin puts in your message box for you to send.
Where to find it
The floor has no screen of its own. It applies by itself to every agent a plugin starts. You meet it in three places:
- The switch for every plugin is in Settings → Plugins: the toggle Lock down plugins' AI agents, just above the Developer Mode section. It is on by default.
- The switch for one plugin is on that plugin's card in the Marketplace (the store icon in the sidebar). The plugin must be installed and turned on. Expand Settings on the card to find Give this plugin's AI agents my full access (not recommended). It is off by default. Hover it for a short explanation.
- Approval cards appear in a plugin agent's session when it is one you can see and it wants to run a command, reach the web, or change something outside its own folder. The card's lead line reads "A plugin's AI agent wants your approval:".
Neither switch has a keyboard shortcut.
How it behaves
Hidden sessions: background work nobody watches
A hidden session is a plugin's background work, such as a Decks build. Nobody is watching it, so it never asks you anything and never waits on you.
- By default it has no tools at all. It works only with what the plugin gave it, and answers in text. The app locks it the same way it locks any session that can only talk: if it ever starts up with a tool anyway, the app stops it before its first turn.
- If its plugin asks for web access, it can search the web and read public web pages, and nothing else. A page on this computer or on your local network is refused.
- Anything else it tries is refused on the spot. It never turns into a question for you.
Visible sessions: ones you can see and answer
A visible session is one you can open and reply to, such as a Forms routed response, a GitHub Integration fix, a build a plugin starts in one of your projects, or a session a plugin starts on an AI agent's behalf (it shows up in your sidebar, and the Agent Firewall screens what it reads). If its plugin was granted tools, it keeps Claude's own tools for files, commands and the web, plus its to-do list. On the floor:
- it asks you before every command and before every web request;
- it asks you before changing anything outside its own folder; inside its folder, your trust level applies, but never more freely than Guarded;
- no trust level and no saved rule of yours stops it asking, so you decide each request on its own;
- it can't commit or push to the default branch (main or master): that is refused before you are even asked, so a fix always lands on a branch of its own. A git command whose target the app can't work out is refused too, with a message telling the agent to spell out the folder and the branch;
- its commits and pull requests carry no AI attribution;
- it gets no helper agents, skills, schedulers or messaging tools, and no add-on tool servers.
If the session starts up with a tool outside that set, an add-on tool server, or a permission mode that would stop asking, the app stops it before its first turn.
"Continue in chat"
A plugin can move one of its hidden sessions into view so you can carry on the conversation. A hidden text-only session then becomes a visible one: it gets the visible rules above, so it asks you before each command and web request. A hidden session with web access stays on its web-only rules. A session its plugin locked on purpose (an AI that can only talk, such as Database Studio's Ask agent) stays locked after it moves into view.
What a plugin agent can never touch
These are refused for every plugin agent on the floor, hidden or visible, even when your own trust level is Full trust:
- the app's own key folder;
- the app's data folder, which holds every plugin's code, settings and data;
- your own Claude folder, wherever you keep it, and the Claude program's own settings file;
- the list of sensitive files, such as SSH keys and cloud credentials;
- any file search that starts at your home folder or above one of these folders, because it would walk into them.
Engines, batches, asides and remote runs
- A plugin can start its agents only on Claude or a Claude-compatible engine. If it asks for another engine, or names none while your own default engine is outside the Claude family, the app refuses with a plain message instead of quietly moving the work to a different AI. The list of engines the app gives the plugin marks those engines as not ready, and tells the plugin its agents are locked down.
- A plugin can't start a batch of agents at once while its agents are locked down.
- You can't send an aside to a plugin's agent session while it is locked down. Send a regular message instead.
- A plugin's agent session can't run over SSH or on a cloud machine.
What Decks, Forms and GitHub Integration users notice
- Decks. Its background sessions are hidden and Decks was never granted tools, so they already had none. On the floor they are also locked the strict way and start without your own setup. They answer in text, as before.
- Forms. A routed response session is one you can see. It now starts without your own setup and in its own folder. Forms was never granted tools, so it still has none. If Forms is set to route to an engine outside the Claude family, that session is refused with the engine message above.
- GitHub Integration. A fix session is one you can see, and GitHub Integration was granted tools. It now asks you before every command and every web request, and it can't commit or push to main or master, so its work always goes to a branch of its own.
Your two switches
- Lock down plugins' AI agents (in Settings → Plugins) is on by default. Turning it off is the emergency rollback for every plugin: their agents get your full setup and access again.
- Give this plugin's AI agents my full access (not recommended) (on the plugin's Marketplace card, under Settings) is off by default. Turning it on lifts the floor for that one plugin: its agents start with your own setup, your trust level and any engine, as they did before the floor existed. Every other plugin stays locked down. It is not recommended because that plugin's agents still read outside content that could steer them.
Both take effect the next time each agent session starts. Neither one ever unlocks a session its plugin locked on purpose. You can change them, and so can an AI agent, like any other setting; a plugin can't change them at all.
Limits worth knowing
- Sessions from before this update are not floored. The floor is written when a session is created, so a plugin agent session that already existed keeps running the way it always did.
- A visible session can still read files outside its folder that are not on the protected list, and it could put what it read into its reply to the plugin. Every way it could send something out on its own (a command or a web request) asks you first.
- Git inside a script file is not checked for main or master: running the script only asks you first.
- The protected list is checked by path, so a shortcut or link that leads into a protected folder is not followed.
- Two identical requests from a plugin that differ only in whether they ask for web access are treated as one, so the second gets the first one's session.
- The two switches have not been checked at phone width. They use the app's standard toggles.
For agents
- The rules live in
plugin-session-floor-contract.md.
The tool lock the floor reuses, and the plugin's own
locked: trueoption, are in plugin-session-lock-contract.md. - The floor value is
{ pluginId, visible, access }withaccess'text' | 'web', stored in the nullableplugin_floor_jsonsession column. Its helpers (pluginFloorAppliesTo,effectiveToolLock,activePluginFloor) and every refusal and deny message live insrc/shared/plugin-session-floor.ts. A stored value that does not parse reads as the strictest floor (hidden, text), never as "not a plugin session". There is no backfill: rows created before the column have no floor. - Stamping, once, at create (
src/main/services/plugin/plugin-session-floor.ts): while the floor applies, a hidden text session gets the app's tool lock written asfloor:<pluginId>(unless the create already asked for the plugin's ownplugin:<pluginId>lock) plus the floor JSON; a hidden web or visible session gets the floor JSON only; with the floor off or full access, nothing is stamped beyond what the plugin asked for. - Which sessions are visible. A webview
AgentMC.sessions.createwith noscopeis hidden; one with ascopeis visible. A workerctx.sessions.create, with or without ascope, is hidden unless it passesuserInitiated: true, whether it saysstartedBy: 'me'orstartedBy: 'agent': every source except the managedplugin:<pluginId>one gets the visible floor.launchBuildis always visible. - Launch (
src/main/process/plugin-session-launch.ts): an effective tool lock launches with the tool-lock flags only (--safe-mode --tools '' --strict-mcp-config --setting-sources '' --permission-mode manual); otherwise an active web or visible floor launches with the same shape and--tools WebSearch,WebFetchor the visible tool set. Never both, and exactly one--safe-mode. The existing no-tools rule (--disallowedTools '*') for a plugin withoutsessionToolsstill applies on top, except to a hidden web session of a plugin holdingnetwork, which carries no no-tools tag. The floor stamp and the launch choice read one settings snapshot. A floored session's settings file carriesattribution: { commit: '', pr: '' }. - The broker checks, in order: protected paths (
src/main/process/plugin-floor-fence.tsplus the sensitive-file list) for every floored session; a hidden session's call is then allowed only if its floor grants it (plugin-session-access-policy.ts), and refused with one log line naming the plugin, the tool and the reason, never the input. A visible session's git command passes the default-branch rail (plugin-git-rail.ts, built on the git-guardrails parser, failing closed unless its sibling checks loaded);Bash,WebFetchandWebSearchalways ask; other tools in its set follow the trust level capped at Guarded. The ask reasonpluginis one no level stops. - Reveal (
pluginSessionReveal) writes the visible floor first, then clears only afloor:lock; aplugin:lock is never cleared. - Refused while floored:
fanout, an aside fork, SSH and cloud runs, and any engine outside the Claude binary family (at create, atlaunchBuildand on every plugin-driven turn). While the floor applies to the asking plugin,ai.listEngines()returnsready: falsefor those engines andagentsLocked: true. The sentences a plugin receives:- engine: "This plugin's AI agents can only run on Claude or a Claude-compatible engine (such as GLM or DeepSeek), where the app can keep them locked down. Pick one of those for this plugin, or give this plugin full access in Settings.";
- fan-out: "A plugin can't start a batch of AI agents while its agents are locked down. Give this plugin full access in Settings to allow it.";
- aside: "A plugin's AI agent sessions don't support asides while they are locked down. Send a regular message instead.";
- remote: "A plugin's AI agent can only run on this computer, where the app can keep it locked
down." (a session holding a tool lock gets the tool lock's own remote sentence instead).
Inside a running session, a refused tool call reaches the agent as a
Blocked: …deny it is told to carry on without, never as an error to the plugin.
- The two settings are
pluginSessionFloorEnabled(defaulttrue) andpluginSessionFullAccess(plugin ids, default[]). Both are ordinary settings: an agent can change them through the CLI settings route like every other setting, no plugin call writes them, and neither has a hotkey. - Folders (
src/main/utils/plugin-room-paths.ts): a session in the plugin's own project works in<userData>/../amc-plugin-rooms/<data folder name>/<pluginId>/, insharedfor hidden sessions and a per-session folder for visible ones. A session started with ascopeor bylaunchBuildkeeps its real project folder. Uninstalling the plugin removes its rooms. - Behaviour changes against the older lock: a session locked with
locked: truenow also skips the per-session add-ons the floor skips, and the external-launcher create path now stamps that lock too.
Related
The bridge methods a plugin uses to start and drive these sessions, including the option that gives a hidden session web access, are on Plugin Bridge Capabilities. Picking an engine from the engine list is on Plugin Bridge Capabilities (part 2). The Sessions pane where you start your own sessions inside a plugin, and the sessions a plugin locks on purpose, are described on Plugin AI-Native Sessions. Installing plugins and their Marketplace cards are covered on Plugin Marketplace. The trust levels a visible session is capped against are on Agent Permission Level, and the side questions a locked plugin session does not take are explained on Asides. Each switch also has its own settings entry: Lock down plugins' AI agents and Plugins whose AI agents have your full access.
Last verified 2026-10-17