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
- Rename the tool to a name not starting with 'cave_' (e.g. 'myapp_search')
- Namespace with your own prefix instead of the framework's
- Search your tool factory for hardcoded 'cave_' prefixes
- 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
- Treat 'cave_' as a framework-only namespace
- Use your own product prefix for custom tools
- Lint tool names against ^cave_ in CI
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
- caveman agent: duplicate tool name
- cave_agent_definition_invalid
- cave_claude_tool_contract_unsupported
- cave_subagent_definition_cycle
- cave_subagent_depth_limit
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)