JuliusBrussee/caveman · error
cave_sandbox_agent_export_missing
cave_sandbox_agent_export_missing
Error message
cave_sandbox_agent_export_missing
What it means
After importing the entry module, the worker looks for the agent definition as the module's `default` export or named `agent` export. If neither is present, or the found object is not an object with `kind: "agent"`, it throws `cave_sandbox_agent_export_missing`. The sandbox can only run a definition it can locate and recognize in the entry module.
Solutions
- Export the agent definition as the default export: `export default myAgent;` in the entry file.
- Alternatively name the export exactly `agent`: `export const agent = myAgent;`.
- Ensure the exported value is the built definition object with `kind: "agent"`, not a factory or builder instance.
- Verify request.entry points at the file that actually holds the definition.
Example fix
// before
export const researcher = agent("researcher").tool(search).build();
// after
const researcher = agent("researcher").tool(search).build();
export default researcher; Defensive patterns
Strategy: validation
Validate before calling
const mod = await import(entryPath);
const def = (mod as { default?: unknown; agent?: unknown }).default ?? (mod as { agent?: unknown }).agent;
if (!def || (def as { kind?: string }).kind !== "agent") {
throw new Error(`${entryPath} must default-export (or export 'agent' as) a built agent definition`);
} Type guard
const isAgentExport = (mod: unknown): mod is { default: AgentDefinition } | { agent: AgentDefinition } =>
typeof mod === "object" && mod !== null &&
(Boolean((mod as any).default && (mod as any).default.kind === "agent") ||
Boolean((mod as any).agent && (mod as any).agent.kind === "agent")); Prevention
- Always `export default` the built agent definition from the sandbox entry file (or name it exactly `agent`).
- Export the built definition object, never a builder or factory function.
- Verify the built object's `kind` is "agent" before exporting.
- Add an import smoke test that loads each entry module and asserts the export shape.
When it happens
Trigger: The request.entry module exports the agent under a custom name (not `default` or `agent`), has no export at all, exports only a factory function, or exports an object whose `kind` is not "agent" (e.g. a tool or workflow definition).
Common situations: Refactoring renamed the export (e.g. `export const myAgent = ...`); building the agent via a builder call assigned to a differently named const; exporting a factory `createAgent()` result directly instead of the built definition; tree-shaking or bundling dropping the expected export.
Related errors
- cave_sandbox_request_invalid
- cave_sandbox_subagent_definition_invalid
- cave_sandbox_unknown_subagent
- cave_sandbox_unknown_tool
- caveman agent: entry must export default agent()
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/ba966bd1b63b5e5e.
Report an issue: GitHub.
Appendix: source
Thrown at packages/agent/src/tool-worker.ts:106
const request = await readRequest();
if (typeof request.entry !== "string" || !Array.isArray(request.agentPath) ||
request.agentPath.length > 8 ||
request.agentPath.some((item) => typeof item !== "string" ||
!/^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/.test(item)) ||
typeof request.rootDefinitionSha256 !== "string" ||
!/^[a-f0-9]{64}$/.test(request.rootDefinitionSha256) ||
typeof request.toolDefinitionSha256 !== "string" ||
!/^[a-f0-9]{64}$/.test(request.toolDefinitionSha256) ||
typeof request.tool !== "string" ||
!/^[a-zA-Z][a-zA-Z0-9_-]{0,127}$/.test(request.tool) ||
typeof request.allowSideEffects !== "boolean" ||
typeof request.allowNetwork !== "boolean") {
throw new Error("cave_sandbox_request_invalid");
}
if (request.allowNetwork !== true) installNetworkDeny();
const imported = await import(request.entry) as { default?: AgentDefinition; agent?: AgentDefinition };
let definition = imported.default ?? imported.agent;
if (!definition || definition.kind !== "agent") throw new Error("cave_sandbox_agent_export_missing");
validateAgentGraph(definition);
if (agentDefinitionSHA256(definition) !== request.rootDefinitionSha256) {
throw new Error("cave_sandbox_definition_mismatch");
}
const visited = new Set<AgentDefinition>([definition]);
for (const name of request.agentPath) {
const delegated = definition.tools.filter((item) =>
item.name === name && item.runtime?.kind === "subagent"
);
if (delegated.length !== 1) throw new Error("cave_sandbox_unknown_subagent");
const child = delegated[0]!.runtime!.definition as AgentDefinition;
if (!child || child.kind !== "agent") {
throw new Error("cave_sandbox_subagent_definition_invalid");
}
if (visited.has(child)) throw new Error("cave_sandbox_subagent_cycle");
visited.add(child);
definition = child;
}View on GitHub (pinned to 3ee70a1026)