JuliusBrussee/caveman · error · Error

caveman agent: entry must export default agent()

Error message

caveman agent: entry must export default agent()

What it means

Thrown by `agentFromImported` while loading the agent entry module (`loadAgent`). The module must export the agent definition as `default` or as a named `agent` export, and that object must carry `kind: "agent"`. Anything else — a module exporting a function, a builder result without the kind tag, or no relevant export at all — fails with this message.

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 27d5a3981a)

Solutions

  1. Change the entry to `export default agent({...})` — call the builder and export its returned definition.
  2. If using a named export, use exactly `export const agent = ...`.
  3. Only use the framework's `agent()` builder to produce definitions; hand-made objects lack the `kind: "agent"` tag.
  4. Confirm `config.entry` points at the intended file and that any barrel re-export preserves `default`.

Example fix

// before
export const myAgent = agent({ ... });

// after
export default agent({ ... });
// or: export const agent = agent({ ... });
Defensive patterns

Strategy: type-guard

Validate before calling

function moduleExportsAgentDefinition(mod: Record<string, unknown>): boolean {
  const def = (mod.default ?? mod.agent) as { kind?: unknown } | undefined;
  return !!def && def.kind === "agent";
}
// const mod = await import(entryPath); assert moduleExportsAgentDefinition(mod);

Type guard

function isAgentDefinition(v: unknown): v is { kind: "agent" } {
  return typeof v === "object" && v !== null && (v as { kind?: unknown }).kind === "agent";
}

Try / catch

try {
  await build(args);
} catch (error) {
  if (error instanceof Error && error.message === "caveman agent: entry must export default agent()") {
    // change entry to `export default agent({...})` (call the builder) and retry
  } else throw error;
}

Prevention

When it happens

Trigger: `config.entry` points at a module whose exports are neither `default` nor `agent`, or whose exported value lacks `kind === "agent"` — e.g. `export const agent = () => buildAgent(...)` (exports a factory function, not a definition) or `export default tool({...})`.

Common situations: Exporting the factory instead of calling it (`export default agent` vs `export default agent()`); renaming exports; an entry file that re-exports from a barrel that drops the default; definitions built by hand rather than the `agent()` builder so `kind` was never set.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/3131f1737691531a. Report an issue: GitHub.