{"record":{"id":"5ee36cfe291589c7","repo":"JuliusBrussee/caveman","slug":"cave-sandbox-unknown-tool","errorCode":"cave_sandbox_unknown_tool","errorMessage":"cave_sandbox_unknown_tool","messagePattern":"cave_sandbox_unknown_tool","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/agent/src/tool-worker.ts","lineNumber":127,"sourceCode":"    throw new Error(\"cave_sandbox_definition_mismatch\");\n  }\n  const visited = new Set<AgentDefinition>([definition]);\n  for (const name of request.agentPath) {\n    const delegated = definition.tools.filter((item) =>\n      item.name === name && item.runtime?.kind === \"subagent\"\n    );\n    if (delegated.length !== 1) throw new Error(\"cave_sandbox_unknown_subagent\");\n    const child = delegated[0]!.runtime!.definition as AgentDefinition;\n    if (!child || child.kind !== \"agent\") {\n      throw new Error(\"cave_sandbox_subagent_definition_invalid\");\n    }\n    if (visited.has(child)) throw new Error(\"cave_sandbox_subagent_cycle\");\n    visited.add(child);\n    definition = child;\n  }\n  const selectedTools = definition.tools.filter((item) => item.name === request.tool);\n  if (selectedTools.length !== 1 || selectedTools[0]!.runtime?.kind === \"subagent\") {\n    throw new Error(\"cave_sandbox_unknown_tool\");\n  }\n  const selected = selectedTools[0]!;\n  if (toolDefinitionSHA256(selected) !== request.toolDefinitionSha256) {\n    throw new Error(\"cave_sandbox_tool_definition_mismatch\");\n  }\n  if (selected.effect !== \"read\" && request.allowSideEffects !== true) {\n    throw new Error(\"cave_sandbox_side_effect_denied\");\n  }\n  const value = await selected.execute(request.params as never, AbortSignal.timeout(selected.timeoutMs));\n  writeResult({ ok: true, value });\n} catch (error) {\n  writeResult({ ok: false, code: failureCode(error) });\n}\n","sourceCodeStart":109,"sourceCodeEnd":141,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/tool-worker.ts#L109-L141","documentation":"After descending agentPath, the worker looks up request.tool in the final definition's tools. It requires exactly one match whose runtime.kind is NOT \"subagent\" (you cannot invoke a subagent slot directly as a tool). Zero matches, multiple matches, or a match that is itself a subagent all produce this error.","triggerScenarios":"request.tool names a nonexistent tool in the resolved agent; the name resolves only to a subagent-runtime entry; two tools share the name; the tool lives on a different agent in the path than agentPath reached.","commonSituations":"Tool renamed or removed while a queued worker request still names the old identifier; agentPath too short/long so resolution lands on the wrong agent; invoking a subagent by its tool name instead of going through normal delegation.","solutions":["Confirm request.tool matches exactly one non-subagent tool name in the agent that agentPath resolves to.","Fix agentPath so it terminates at the agent that actually owns the tool.","To run a subagent's tool, extend agentPath with the subagent name and target its inner tool; never point request.tool at a subagent slot."],"exampleFix":"// before: tool \"search\" lives inside subagent \"research\"\n{ agentPath: [], tool: \"search\" } // cave_sandbox_unknown_tool\n\n// after\n{ agentPath: [\"research\"], tool: \"search\" }","handlingStrategy":"validation","validationCode":"function toolResolves(def: AgentDefinition, toolName: string): boolean {\n  const matches = def.tools.filter((t) => t.name === toolName);\n  return matches.length === 1 && matches[0].runtime?.kind !== \"subagent\";\n}","typeGuard":"function isExecutableTool(t: { runtime?: { kind?: string } }): boolean {\n  return t.runtime?.kind !== \"subagent\";\n}","tryCatchPattern":null,"preventionTips":["Validate (agentPath, tool) pairs against the current definition before enqueueing worker requests.","Never point the tool field at a subagent slot; extend agentPath instead."],"tags":["sandbox","tool-resolution","cave"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}