Repository navigation
Plan proposals in a sandbox before an admin approves them - #5
Merged
Merged
Conversation
A proposal of another AI agent no longer goes to genco's agent as text. A planner (same model as the agent) reads it in a read-only sandbox: root without any capability but reading, read-only file system, no network or unix sockets, no other processes, genco's secrets and other keys hidden. It writes a short plan, or refuses with NO PLAN and a reason. genco cleans and caps the plan, and the admin sees exactly what genco's agent will get, in the panel and in the mail. The admin approves the newest plan (second factor as before), sends it back to the planner with a change (a new version, no factor needed: the planner can't do anything), or rejects the proposal. genco's agent gets only the approved plan, never the proposal. Deletions the plan names in `Delete: <kind> <name>` lines are confirmed with it and run without another confirmation while the agent works on it, once each; any other deletion still asks. The small model that rewrote proposals is gone, the plan replaces it. Waiting proposals get planned after the update. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
llm::model takes the connection itself; called while the planner held it, the planner deadlocked and with it every request of the panel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ProtectSystem=strict leaves /run, /dev/shm, /dev/hugepages, /dev/mqueue and binfmt_misc writable, and root writes root's files there without any capability: a talked-into planner could drop a unit drop-in into /run/systemd/system that runs on the next reload. They are read-only or hidden now. The SMTP relay password, the runner's config, ACME account keys, database files and mailboxes are hidden too, and genco reads at most 1 MiB of a command's stdout and stderr, so `yes` can't fill its memory. The planner frees its slot before the mail goes out, so a change asked for meanwhile gets planned instead of staying in "planning"; its text goes before the tool calls, the outputs right after them; after a restart it skips expired proposals. A plan's deletion line can only be used once, also by two requests at the same time (unique index). Peers don't see who asked for a change. The shell output text and the planner setup are shared, the enum names come from as_str, and the agents' help no longer mentions the removed rewrite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A proposal of another AI agent no longer goes to genco's agent as text. A planner (the agent's model) reads it in a read-only systemd sandbox (root with only CAP_DAC_READ_SEARCH, read-only fs, no network, no unix sockets, private PIDs, genco's secrets and other keys hidden) and writes a short plan, or NO PLAN with a reason. genco cleans and caps the plan (4000 chars); the admin sees exactly what genco's agent gets, in the panel and the mail.
The admin approves the newest plan (second factor as before), asks for a change (note back to the planner, new version, no factor; max 10 versions) or rejects. genco's agent gets only the approved plan, never the proposal. Deletions named in the plan's
Delete: <kind> <name>lines run without another confirmation while the agent works on that plan, once each (pending_actions.plan_id/plan_entry); other deletions still ask. The small rewrite model is removed; waiting proposals are planned after the migration. Peers' GET /api/proposals/ hides the plans (they may contain what the planner read).Tested on gs4: a deletion plan ran A11 without a mail; an injection proposal (fake admin line + planted README with commands and Delete lines) was refused by the planner, nothing changed. Second commit fixes a deadlock found there (llm::model took the db lock while the planner held it).
🤖 Generated with Claude Code