[eric] agents: read-only session flag for the unattended onboarding audit (Edit/Bash hard-blocked)

This commit is contained in:
ciregenz
2026-07-19 12:07:00 -07:00
parent 8710c651b2
commit 74309a7cef
4 changed files with 22 additions and 0 deletions
+6
View File
@@ -17,6 +17,10 @@ class AgentConfig(BaseModel):
workflow_edit_id: Optional[str] = None
# App cards the user picked to edit. When exactly one resolves, launch binds the chat's cwd to that app instead of seeding a new "Untitled App".
selected_app_output_ids: Optional[list[str]] = None
# Onboarding auto-launches an audit over the user's REAL files with nobody watching, so it runs
# read-only: Read/Grep/Glob + Write (its one report) allowed, Edit/Bash/NotebookEdit hard-blocked
# so "modify or delete an existing file" is unrepresentable, not just discouraged by the prompt.
read_only: bool = False
class ApprovalRequest(BaseModel):
id: str = Field(default_factory=lambda: uuid4().hex)
@@ -84,6 +88,8 @@ class AgentSession(BaseModel):
sdk_session_id: Optional[str] = None
system_prompt: Optional[str] = None
allowed_tools: list[str] = Field(default_factory=list)
# Hard-block the mutation/exec tools for this session (onboarding's unattended audit); see AgentConfig.read_only.
read_only: bool = False
max_turns: Optional[int] = None
cwd: Optional[str] = None
# Resolved at session start so resume reattaches to the same repo even after the user cd's elsewhere.
@@ -110,6 +110,7 @@ class AgentLaunch(AgentManagerProtocol):
mode=config.mode,
system_prompt=config.system_prompt,
allowed_tools=tools,
read_only=config.read_only,
max_turns=config.max_turns,
cwd=effective_cwd,
repo_url=repo_url,
@@ -19,6 +19,10 @@ from backend.apps.tools_lib.tools_lib import (
sanitize_server_name as sanitize_server_name,
)
# Mutation/exec tools a read-only session must never reach: Edit (rewrites files), Bash (rm/mv/overwrite),
# NotebookEdit (rewrites notebooks). Write is intentionally NOT here, the audit needs its one report.
READ_ONLY_BLOCKED_TOOLS = ("Edit", "Bash", "NotebookEdit")
@typechecked
def build_effective_tool_lists(
@@ -108,4 +112,13 @@ def build_effective_tool_lists(
# The claude_code preset ships its own bare `Skill` tool that reads ~/.claude/skills directly; always withhold it so skills only ever load through our provider-agnostic mcp__openswarm-skill__Skill (or not at all).
if "Skill" not in effective_disallowed:
effective_disallowed.append("Skill")
# Read-only session (onboarding's unattended audit over the user's real files): the mutation/exec
# tools are HARD-blocked, not just left out of allowed, so a background agent can never modify or
# delete an existing file. Write stays permitted for its single report. Also drop them from allowed
# in case a preset seeded them, disallowed wins in the SDK but keep the two lists coherent.
if getattr(session, "read_only", False):
for dt in READ_ONLY_BLOCKED_TOOLS:
if dt not in effective_disallowed:
effective_disallowed.append(dt)
effective_allowed = [t for t in effective_allowed if t not in READ_ONLY_BLOCKED_TOOLS]
return effective_allowed, effective_disallowed
+2
View File
@@ -137,6 +137,8 @@ export interface AgentConfig {
target_directory?: string;
dashboard_id?: string;
selected_app_output_ids?: string[];
// Onboarding's unattended audit runs read-only over the user's real files (Edit/Bash hard-blocked).
read_only?: boolean;
}
export interface HistorySession {