JuliusBrussee/caveman · error

caveman agent: tool prefix cave_ is reserved by framework

Error message

caveman agent: tool prefix cave_ is reserved by framework (${reserved.name})

What it means

agent() reserves the tool-name prefix 'cave_' for framework-provided tools and throws if any user-supplied tool's name starts with it, reporting the offending tool's name. This prevents collisions with internal tools the kernel injects.

Solutions

  1. Rename the tool to a name not starting with 'cave_' (e.g. 'myapp_search')
  2. Namespace with your own prefix instead of the framework's
  3. Search your tool factory for hardcoded 'cave_' prefixes
  4. If you intended a built-in tool, import and use the framework's tool rather than redefining it

Example fix

// before
agent({ id: "bot", tools: [{ name: "cave_lookup", run: lookup }] });
// after
agent({ id: "bot", tools: [{ name: "app_lookup", run: lookup }] });
Defensive patterns

Strategy: validation

Validate before calling

if (tools.some(t => t.name.startsWith("cave_"))) throw new Error("tool uses reserved cave_ prefix");

Type guard

const usesReservedPrefix = (tools) => tools.some(t => typeof t.name === "string" && t.name.startsWith("cave_"));

Try / catch

try { def = agent(opts); } catch (err) { if (String(err.message).includes("prefix cave_ is reserved")) { opts.tools = opts.tools.map(renameReserved); def = agent(opts); } else throw err; }

Prevention

When it happens

Trigger: agent({ tools: [{ name: 'cave_search', ... }] }) or any custom tool named like 'cave_*'.

Common situations: Mimicking the naming style of built-in tools; wrapping a framework tool under a similar name; generated tool names that concatenate a 'cave_' namespace prefix.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/918f50e5c43a14f6. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/index.ts:111

  contexts?: ContextDefinition[];
  memory?: MemoryDefinition;
  output?: OutputDefinition;
  sandbox?: AgentDefinition["sandbox"];
}): AgentDefinition {
  if (!/^[a-z0-9][a-z0-9_-]{0,95}$/.test(options.id)) {
    throw new Error(`caveman agent: invalid agent id ${JSON.stringify(options.id)}`);
  }
  const tools = Object.freeze([...(options.tools ?? [])]);
  if (new Set(tools.map((item) => item.name)).size !== tools.length) {
    throw new Error("caveman agent: duplicate tool name");
  }
  const sandbox = options.sandbox ?? "required";
  if (!SANDBOX_MODES.includes(sandbox)) {
    throw new Error(`caveman agent: unknown sandbox mode ${JSON.stringify(sandbox)}`);
  }
  const reserved = tools.find((item) => item.name.startsWith("cave_"));
  if (reserved) {
    throw new Error(
      `caveman agent: tool prefix cave_ is reserved by framework (${reserved.name})`,
    );
  }
  const definition: AgentDefinition = {
    kind: "agent",
    id: options.id,
    instructions: options.instructions,
    model: options.model,
    reasoning: options.reasoning ?? "low",
    tools,
    contexts: Object.freeze([...(options.contexts ?? [])]),
    sandbox,
    ...(options.memory === undefined ? {} : { memory: options.memory }),
    ...(options.output === undefined ? {} : { output: options.output }),
  };
  return Object.freeze(definition);
}

View on GitHub (pinned to 3ee70a1026)