fix(agent): end the additional_permissions retry loop - #864
fix(agent): end the additional_permissions retry loop#864Vasanthdev2004 wants to merge 1 commit into
Conversation
Asking the agent to run an ordinary read-only command on Windows could leave it
oscillating between two rejections instead of executing:
additional_permissions requires sandbox_permissions set to "with_additional_permissions"
additional_permissions must include at least one of network or file_system, ...
Both come from inlineAdditionalPermissionsProfile, and each names only the fix
that ADDS something. The first pushes the model toward setting the flag; the
second pushes it back toward requesting a permission the command does not need.
Neither ever says to omit the field, which is the correct action for a read-only
command, so the two messages form a two-state oscillator. Every rejection now
carries that remedy.
The schema half is why the object is attached at all. Neither field description
said to omit them for ordinary commands, so a model that legitimately used
with_additional_permissions once in a session had nothing telling it to stop
attaching a permission object to the next command. Both descriptions now lead
with "omit", and they are shared constants rather than duplicated verbatim in
bash.go and exec_command.go, where they were free to drift.
Rejection is still rejection. Nothing that was refused is now accepted on the
strength of an empty or mismatched payload, and sandbox_permissions is never
upgraded on the model's behalf; only the guidance changed.
The one behavioural change is that an explicit additional_permissions: null is
now treated as the omitted field, since a null grants nothing and carries no
flag. That flips three shapes from reject to execute: null with use_default,
with require_escalated, and with no mode at all. The escalated one still routes
through the normal escalation prompt and is not a new capability — the identical
request without the null key already behaved that way. A FLAGGED null still
errors, so with_additional_permissions plus null is not silently downgraded.
Fixes #845. Fixes #847.
WalkthroughThe change normalizes explicit ChangesPermission validation and tool guidance
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@internal/tools/args.go`:
- Around line 152-155: Update sandboxPermissionsDescription so omission is
described as appropriate only for commands that require no additional sandbox
access, rather than implying all read-only commands can omit the override.
Preserve the guidance for using with_additional_permissions with non-empty
additional_permissions when read-only commands need sandboxed network or file
access.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 96535456-6df2-423b-9144-b7e9716c8509
📒 Files selected for processing (6)
internal/agent/additional_permissions_validation_test.gointernal/agent/loop.gointernal/tools/args.gointernal/tools/bash.gointernal/tools/exec_command.gointernal/tools/sandbox_permissions_schema_test.go
| sandboxPermissionsDescription = "Per-command sandbox override. Omit it for ordinary commands, including every " + | ||
| "read-only one; use `with_additional_permissions` with a non-empty `additional_permissions` for sandboxed " + | ||
| "file/network access, or `require_escalated` only when the command must run outside the sandbox, such as " + | ||
| "host/global process, socket, service, or desktop state hidden by sandbox namespaces." |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Do not state that every read-only command needs no sandbox override.
Line 153 conflicts with commands that are read-only but require sandboxed network access, such as gh issue view. This wording can cause the agent to omit the required network permission. Describe omission as appropriate only when the command needs no extra sandbox access.
Proposed fix
- sandboxPermissionsDescription = "Per-command sandbox override. Omit it for ordinary commands, including every " +
- "read-only one; use `with_additional_permissions` with a non-empty `additional_permissions` for sandboxed " +
+ sandboxPermissionsDescription = "Per-command sandbox override. Omit it when the command needs no extra sandbox " +
+ "access, such as `git branch --show-current`; use `with_additional_permissions` for sandboxed " +📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| sandboxPermissionsDescription = "Per-command sandbox override. Omit it for ordinary commands, including every " + | |
| "read-only one; use `with_additional_permissions` with a non-empty `additional_permissions` for sandboxed " + | |
| "file/network access, or `require_escalated` only when the command must run outside the sandbox, such as " + | |
| "host/global process, socket, service, or desktop state hidden by sandbox namespaces." | |
| sandboxPermissionsDescription = "Per-command sandbox override. Omit it when the command needs no extra sandbox " + | |
| "access, such as `git branch --show-current`; use `with_additional_permissions` for sandboxed " + | |
| "file/network access, or `require_escalated` only when the command must run outside the sandbox, such as " + | |
| "host/global process, socket, service, or desktop state hidden by sandbox namespaces." |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@internal/tools/args.go` around lines 152 - 155, Update
sandboxPermissionsDescription so omission is described as appropriate only for
commands that require no additional sandbox access, rather than implying all
read-only commands can omit the override. Preserve the guidance for using
with_additional_permissions with non-empty additional_permissions when read-only
commands need sandboxed network or file access.
Zero automated PR reviewVerdict: No blockers found Blockers
Validation
ScopeHead: This deterministic review checks validation status and basic diff hygiene. A human reviewer still owns product judgment and design quality. |
|
@jatmn could you take this one when you have a moment? It closes #845 and #847, which are the same bug — #847 was actually filed by the agent while it was stuck in the loop the issue describes. The part worth your eye is the null handling, since it's the only behavioural change and it touches the escalation path. An explicit A flagged null still errors, deliberately — Everything else is guidance-only: the two rejection messages now name "omit the field" as a remedy, which neither did, and the schema descriptions lead with omit so the object stops being attached to ordinary commands in the first place. Nothing previously refused is accepted now, and Reverting only One version note so the repro doesn't confuse you: the reporter was on 0.6.0 where both legs of the loop were live. On current main, #838's |
Summary
git branch --show-current— an ordinary read-only command — could leave the agent bouncing between two rejections instead of running, burning turns without converging.Both errors come from
inlineAdditionalPermissionsProfile, and each names only the fix that adds something. One pushes toward setting the flag, the other back toward requesting a permission the command doesn't need. Neither ever says to omit the field, which is the correct action here — so together they form a two-state oscillator. Every rejection now carries that remedy.The schema half is why the object gets attached at all: neither field description said to omit them for ordinary commands, so a model that legitimately used
with_additional_permissionsonce had nothing telling it to stop. Both descriptions now lead with "omit", and they're shared constants instead of being duplicated verbatim acrossbash.goandexec_command.go.This does not loosen the sandbox
Nothing previously refused is now accepted on the strength of an empty or mismatched payload, and
sandbox_permissionsis never upgraded on the model's behalf. Only the guidance changed.The one behavioural change: an explicit
additional_permissions: nullis treated as the omitted field, since a null grants nothing and carries no flag. That flips three shapes from reject to execute — null withuse_default, withrequire_escalated, and with no mode at all. The escalated case still routes through the normal escalation prompt and is not a new capability; the identical request without the null key already behaved that way. A flagged null still errors, sowith_additional_permissions+ null isn't silently downgraded.Note on versions
The reporter was on 0.6.0, where both legs of the loop were live. On current
main, #838'snormalizeNoopAdditionalPermissionsalready absorbs the empty payload, so only the first error reproduces today. Both legs were reproduced and fixed.Test plan
TestAdditionalPermissionsRejectionsConvergereplays exec_command repeatedly requests incorrect sandbox permissions and fails before using the required network permission #845's step-1/step-2 sequence and Sandbox tool invocation fails when additional_permissions is empty or mismatched #847's two inconsistent states in one testTestExecuteToolCallMissingAdditionalPermissionsErrorIsActionable,TestEmptyAdditionalPermissionsErrorNamesOmitRemedypin that the errors name the omit remedyTestExecuteToolCallTreatsNullAdditionalPermissionsAsOmitted,TestExecuteToolCallRejectsFlaggedNullAdditionalPermissionscover the null splitinternal/agent/loop.goturns all five red on message text, and reproduces both issue strings verbatimgo build ./...,go vet,gofmtclean;internal/agent,internal/tools,internal/sandboxgreenFixes #845
Fixes #847
Summary by CodeRabbit
Bug Fixes
nullvalues.Documentation
Tests