{"record":{"id":"b59bd3073c3951f6","repo":"Hmbown/CodeWhale","slug":"agent-action-claim-widens-an-enforced-write-scope-and-the","errorCode":null,"errorMessage":"agent action=claim widens an enforced write scope, and the Fleet role `{role}` has no write authority to widen. Use an `implement` or `general` role.","messagePattern":"agent action=claim widens an enforced write scope, and the Fleet role `(.+?)` has no write authority to widen\\. Use an `implement` or `general` role\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":17504,"sourceCode":"        }\n        let action = input.get(\"action\").and_then(Value::as_str);\n        if matches!(&self.agent_type, FleetRole::Scout | FleetRole::Reviewer)\n            && name == \"Web\"\n            && !matches!(action, Some(\"search\" | \"fetch\"))\n        {\n            return Err(anyhow!(\n                \"Tool Web is limited to search/fetch in the read-only evidence profile\"\n            ));\n        }\n        // Catalog shaping is not authority. `agent` clears both name-keyed\n        // gates below by design, so the per-action gate has to be repeated\n        // here or a hand-written call would reach an action the role's own\n        // catalog withheld.\n        if name == \"agent\"\n            && matches!(parse_agent_tool_action(&input), Ok(AgentToolAction::Claim))\n            && !self.agent_action_permitted(\"claim\")\n        {\n            return Err(anyhow!(\n                \"agent action=claim widens an enforced write scope, and the Fleet role `{role}` has no write authority to widen. Use an `implement` or `general` role.\",\n                role = self.agent_type.as_str()\n            ));\n        }\n        let family_action_allowed = if !Self::ACTION_ALIASES\n            .iter()\n            .any(|(family, _, _)| *family == name)\n        {\n            true\n        } else if let Some(action) = action {\n            self.is_action_allowed(name, action)\n        } else {\n            self.allowed_tools\n                .as_ref()\n                .is_none_or(|list| list.iter().any(|allowed| allowed == name))\n        };\n        if !self.is_tool_allowed(name) || !family_action_allowed {\n            return Err(anyhow!(\"Tool {name} not allowed for this sub-agent\"));","sourceCodeStart":17486,"sourceCodeEnd":17522,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/subagent/mod.rs#L17486-L17522","documentation":"`agent action=claim` widens an enforced write scope (claiming work items). A Fleet role without write authority cannot widen any scope, so when the action gate `agent_action_permitted(\"claim\")` fails, the dispatch layer rejects the call before it runs, independent of what the role's catalog withheld.","triggerScenarios":"A sub-agent whose `agent_type` lacks write authority (e.g. scout, reviewer) issues `agent` with `action=claim`, and `parse_agent_tool_action` resolves it to `AgentToolAction::Claim` while `agent_action_permitted(\"claim\")` returns false.","commonSituations":"A read-only worker tries to claim a work-graph item; the prompt template includes claim instructions written for implement roles; action alias parsing maps an ambiguous input onto `claim`.","solutions":["Re-spawn the worker with an `implement` or `general` role that has write authority.","Have the read-only worker request the claim through the parent agent instead of calling `agent action=claim` itself.","Verify the input action field actually means claim (check `ACTION_ALIASES`) and correct it if the worker intended a different action.","Grant claim permission to the role in fleet configuration if this is an intended workflow change."],"exampleFix":"// before\n// scout role:\nAgent.call({ action: \"claim\", task_id: 42 })\n// after\n// delegate to implement role or ask parent to claim:\nAgent.call({ action: \"claim\", task_id: 42 }) // run by an 'implement' role","handlingStrategy":"validation","validationCode":"const action = parseAgentAction(input);\nif (action === 'claim' && !roleCanWrite(agentType)) {\n  throw new Error('claim requires implement/general role');\n}","typeGuard":"const hasWriteAuthority = (role) => ['implement','general'].includes(role);","tryCatchPattern":"try { agent.call(input); } catch (e) { if (String(e).includes('no write authority to widen')) { parentClaim(taskId); } }","preventionTips":["Only emit agent action=claim from roles with write authority","Have read-only workers request claims through the parent","Document which fleet roles may claim work-graph items in delegation prompts"],"tags":["subagent","permissions","write-scope","security"],"backgroundTag":"insufficient-permissions","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}