JuliusBrussee/caveman · error
caveman agent: entry must export default agent()
Error message
caveman agent: entry must export default agent()
What it means
agentFromImported in packages/agent/src/cli.ts loads the entry module given to 'caveman agent' and accepts either a default export or a named `agent` export that must have kind === 'agent'. If the module has neither export, the export is undefined/null, or the object is not an agent definition, it throws 'caveman agent: entry must export default agent()'.
Solutions
- Add `export default { kind: "agent", ... }` to the entry file, or export it as `export const agent = { kind: "agent", ... }`.
- Verify the exported object includes kind: "agent" (not a factory function returning it).
- Confirm you passed the correct entry file path to `caveman agent` — one that actually defines the agent.
- Log the module's keys (`Object.keys(await import(path))`) to see what is actually exported after transpilation.
- If using a bundler/TS config, ensure the export is preserved (e.g. no tree-shaking of the default export).
Example fix
// before
const helper = { kind: "tool", name: "x" };
export { helper };
// after
const agent = { kind: "agent", name: "my-agent", tools: [helper] };
export default agent; Defensive patterns
Strategy: type-guard
Validate before calling
const mod = await import(entryPath);
if (!(mod.default ?? mod.agent)) throw new Error(`Entry ${entryPath} has no default/agent export`); Type guard
const isAgentDefinition = (x: unknown): x is AgentDefinition => typeof x === "object" && x !== null && (x as any).kind === "agent";
Try / catch
try {
await runAgent(entryPath);
} catch (e) {
if (e.message.includes("must export default agent()")) {
console.error(`Entry ${entryPath} must ` + "export default { kind: 'agent', ... }");
} else throw e;
} Prevention
- Always use `export default` (or `export const agent`) for agent entry files.
- Export the definition object itself, not a factory function returning it.
- Include kind: "agent" on the exported object.
- Point caveman at the module that defines the agent, not a helper module.
When it happens
Trigger: Running `caveman agent <path>` where the entry file has no default export and no `agent` export, exports something that is not an AgentDefinition (e.g. a plain object without kind: 'agent', or a function), or exports the agent under a different name.
Common situations: Authoring an agent file with only `export const myAgent = {...}`; forgetting `export default`; using `export function agent()` (a function, not an object with kind 'agent'); transpilation/bundler output stripping or renaming the export; pointing caveman at a utility module instead of the agent entry.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- at least one report path and the canonical span fixture…
- at least one sink id is required
- base and head must be full Git object IDs
- cave_live_eval_sandbox_profile_invalid
- cave_sandbox_agent_export_missing
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/3131f1737691531a.
Report an issue: GitHub.
Appendix: source
Thrown at packages/agent/src/cli.ts:1383
const configured = [
process.env.ANTHROPIC_API_KEY && "anthropic/claude-haiku-4-5",
process.env.OPENAI_API_KEY && "openai/gpt-5.4-mini",
(process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) && "google/gemini-2.5-flash",
].filter((value): value is string => typeof value === "string");
if (configured.length !== 1) {
throw new Error("caveman build: set CAVE_MODEL when zero or multiple provider credentials exist");
}
return configured[0]!;
}
async function loadAgent(path: string): Promise<AgentDefinition> {
return agentFromImported(await importFresh(path));
}
function agentFromImported(imported: unknown): AgentDefinition {
const exported = imported as { default?: AgentDefinition; agent?: AgentDefinition };
const definition = exported.default ?? exported.agent;
if (!definition || definition.kind !== "agent") throw new Error("caveman agent: entry must export default agent()");
return definition;
}
async function readLock(root: string): Promise<CaveBuildLock> {
return parseCaveBuildLock(JSON.parse(await readFile(resolve(root, ".caveman/agent.lock.json"), "utf8")));
}
function importFresh(path: string): Promise<unknown> {
return import(`${pathToFileURL(path).href}?cave=${Date.now()}-${crypto.randomUUID()}`);
}
function isEval(value: unknown): value is EvalDefinition {
return value !== null && typeof value === "object" && (value as { kind?: unknown }).kind === "eval";
}
function fixtureInput(value: unknown): string {
return typeof value === "string" ? value : JSON.stringify(value);
}View on GitHub (pinned to 3ee70a1026)