From 07ef98f7e52dfb0e71fcb9d4248a9f78253c2b68 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Tue, 16 Jun 2026 04:00:08 -0700 Subject: [PATCH] [eric] approvals: persist tool policy on Always-approve (set_always_allow through the approval path) --- backend/apps/agents/agent_manager.py | 12 ++++++++++++ backend/apps/agents/agents.py | 1 + backend/apps/agents/core/models.py | 4 ++++ 3 files changed, 17 insertions(+) diff --git a/backend/apps/agents/agent_manager.py b/backend/apps/agents/agent_manager.py index c5fe744e..46e744d6 100644 --- a/backend/apps/agents/agent_manager.py +++ b/backend/apps/agents/agent_manager.py @@ -23,6 +23,7 @@ from backend.apps.tools_lib.tools_lib import ( refresh_airtable_token, refresh_google_token, refresh_hubspot_token, + save_builtin_permissions, save_trusted_sensitive_paths, ) from backend.config.paths import SESSIONS_DIR @@ -788,6 +789,17 @@ class AgentManager: except Exception: logger.exception("Failed to persist trusted sensitive path") + # "Always approve" button: persist the tool's policy so it stops + # prompting. The guards above (sensitive/catastrophic) re-fire even + # on always_allow, so this can't disarm an rm -rf or a key-path write. + if decision.get("behavior") == "allow" and decision.get("set_always_allow"): + try: + perms = load_builtin_permissions() + perms[tool_name] = "always_allow" + save_builtin_permissions(perms) + except Exception: + logger.exception("Failed to persist always-allow for %s", tool_name) + approval_latency_ms = int((datetime.now() - approval_req.created_at).total_seconds() * 1000) try: # Append to the session's approval log so a reload diff --git a/backend/apps/agents/agents.py b/backend/apps/agents/agents.py index 96746f02..3a84dae3 100644 --- a/backend/apps/agents/agents.py +++ b/backend/apps/agents/agents.py @@ -123,6 +123,7 @@ async def handle_approval(response: ApprovalResponse): "message": response.message, "updated_input": response.updated_input, "trust_pattern": response.trust_pattern, + "set_always_allow": response.set_always_allow, }) return {"ok": True} diff --git a/backend/apps/agents/core/models.py b/backend/apps/agents/core/models.py index 972e9beb..de1e0832 100644 --- a/backend/apps/agents/core/models.py +++ b/backend/apps/agents/core/models.py @@ -42,6 +42,10 @@ class ApprovalResponse(BaseModel): # (from ApprovalRequest.sensitive_pattern) to disk so future writes # against the same pattern skip the modal. trust_pattern: bool = False + # "Always approve" button: persist this tool's policy to always_allow so + # the same tool stops prompting (the catastrophic/sensitive guards still + # fire, so this can't blanket-approve an rm -rf or a sensitive-path write). + set_always_allow: bool = False class Message(BaseModel): id: str = Field(default_factory=lambda: uuid4().hex)