{"record":{"id":"c9278e87c68c6b05","repo":"JuliusBrussee/caveman","slug":"cave-subagent-framework-runner-required","errorCode":null,"errorMessage":"cave_subagent_framework_runner_required","messagePattern":"cave_subagent_framework_runner_required","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/index.ts","lineNumber":204,"sourceCode":"  }\n  return tool({\n    name: options.name,\n    description: options.description,\n    input: schema.object({ task: schema.string() }),\n    effect: \"read\",\n    result: \"auto\",\n    ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),\n    runtime: {\n      kind: \"subagent\",\n      definition: options.agent,\n      maxInputChars,\n      maxCalls,\n      maxCostUsd,\n      ...(options.maxTokens === undefined ? {} : { maxTokens: options.maxTokens }),\n      maxContextTokens,\n    },\n    async execute() {\n      throw new Error(\"cave_subagent_framework_runner_required\");\n    },\n  });\n}\n","sourceCodeStart":186,"sourceCodeEnd":208,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/index.ts#L186-L208","documentation":"The subagent tool factory returns a ToolDefinition whose runtime is { kind: \"subagent\", ... }; a host framework that understands that runtime replaces execute(). The stub execute() that throws cave_subagent_framework_runner_required exists so that running the tool through a plain tool executor (which would call execute directly) fails loudly instead of silently doing nothing.","triggerScenarios":"Registering the subagent tool with a generic tool-runner that invokes definition.execute() itself, rather than passing the ToolDefinition to the caveman agent runtime that recognizes the subagent runtime kind. Also triggered by test harnesses that call tool.execute() directly.","commonSituations":"Mixing primitives from this library into a custom executor, unit tests that stub the runtime layer and call execute, or upgrading the agent package while the host runner stays on an older version that predates subagent runtime support.","solutions":["Run the tool through the caveman agent runtime that handles runtime.kind === \"subagent\" instead of calling execute() yourself","If you need a plain executable tool, supply your own execute in the options rather than relying on the factory stub","In tests, mock at the runtime boundary (the framework runner), not at execute()","Check that @caveman-ai host packages (agent runner) are version-matched with this primitives package"],"exampleFix":"// before\nconst def = subagentTool({ agent, name: \"worker\" });\nconst out = await def.execute({ task: \"do it\" }); // throws cave_subagent_framework_runner_required\n\n// after\n// Register the definition with the agent runtime; the framework installs the real runner\nconst runner = createAgentRunner({ tools: [subagentTool({ agent, name: \"worker\" })] });\nconst out = await runner.callTool(\"worker\", { task: \"do it\" });","handlingStrategy":"type-guard","validationCode":"const def = subagentTool({ agent, name: \"worker\" });\nif (def.runtime?.kind === \"subagent\") {\n  // must be executed by the framework runner, never def.execute() directly\n  registerWithAgentRuntime([def]);\n} else {\n  await def.execute(input); // safe only for plain tools\n}","typeGuard":"const hasSubagentRuntime = (\n  d: ToolDefinition,\n): d is ToolDefinition & { runtime: { kind: \"subagent\" } } =>\n  (d as { runtime?: { kind?: string } }).runtime?.kind === \"subagent\";","tryCatchPattern":"try {\n  await def.execute(input);\n} catch (e) {\n  if (e instanceof Error && e.message === \"cave_subagent_framework_runner_required\") {\n    throw new Error(\"subagent tools must run through the agent runtime, not execute()\");\n  }\n  throw e;\n}","preventionTips":["Never call execute() on tools you did not construct with your own execute","Centralize tool dispatch in one place that checks runtime.kind first","Version-lock the primitives and runner packages so runtime kinds stay understood"],"tags":["subagent","runtime","framework-integration","architecture"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}