{"record":{"id":"fe543803de2afa1e","repo":"Hmbown/CodeWhale","slug":"tool-web-is-limited-to-search-fetch-in-the-read-on","errorCode":null,"errorMessage":"Tool Web is limited to search/fetch in the read-only evidence profile","messagePattern":"Tool Web is limited to search/fetch in the read-only evidence profile","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/mod.rs","lineNumber":17492,"sourceCode":"\n    async fn execute_full(\n        &self,\n        agent_id: &str,\n        tool_id: &str,\n        name: &str,\n        input: Value,\n    ) -> Result<RichToolResult> {\n        if self.role_blocks_unhardened_process_tool(name) {\n            return Err(anyhow!(\n                \"Tool {name} is not available to this read-only worker because its process path does not share the hardened evidence boundary. Use read/search, classifier-bounded bash reads, or the verifier's bounded Run tool instead.\"\n            ));\n        }\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()","sourceCodeStart":17474,"sourceCodeEnd":17510,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/crates/tui/src/tools/subagent/mod.rs#L17474-L17510","documentation":"In the read-only evidence profile, Scout and Reviewer roles may use the Web tool only with `action` = `search` or `fetch`. Any other Web action is rejected, because catalog shaping alone is not authority — the per-action gate is re-checked at dispatch to stop hand-written calls from reaching restricted actions.","triggerScenarios":"A Scout or Reviewer sub-agent calls the Web tool with an action other than search/fetch (e.g. `post`, `download`, `submit`) — whether from the model improvising or from a hand-constructed tool call.","commonSituations":"A child attempts to submit a form or authenticate to a site while doing research; a parent with full web access had its task delegated to a read-only child that tries the same Web verbs; action name typo causes a match failure.","solutions":["Restrict the Web call to `action: \"search\"` or `action: \"fetch\"`.","If a non-read action is genuinely required, delegate to a role with write authority (implement/general).","Check the action string for typos or unsupported verbs.","Update the orchestrating instructions to state read-only web constraints up front."],"exampleFix":"// before\nWeb.call({ action: \"post\", url: \"https://api.example.com\" })\n// after\nWeb.call({ action: \"fetch\", url: \"https://api.example.com\" })","handlingStrategy":"validation","validationCode":"if ((role === 'scout' || role === 'reviewer') && toolName === 'Web' &&\n    !['search','fetch'].includes(input.action)) {\n  throw new Error('web action not allowed in read-only profile');\n}","typeGuard":"const isReadOnlyWebAction = (a) => a === 'search' || a === 'fetch';","tryCatchPattern":"try { web.call(input); } catch (e) { if (String(e).includes('search/fetch')) { input.action = 'fetch'; retry(); } }","preventionTips":["Restrict generated web calls to search/fetch when delegating to read-only roles","Route any web write/submission to a role with write authority","Validate the action string against the allowed set before dispatch"],"tags":["subagent","permissions","web","read-only"],"backgroundTag":"permission-denied","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}