JuliusBrussee/caveman · error · Error

caveman agent: invalid agent id ${JSON.stringify(options.id)

Error message

caveman agent: invalid agent id ${JSON.stringify(options.id)}

What it means

Thrown by the agent() builder (packages/agent/src/index.ts:99): options.id fails the pattern ^[a-z0-9][a-z0-9_-]{0,95}$ — it must start with a lowercase letter or digit, contain only lowercase letters, digits, underscore, and hyphen, and be at most 96 characters. Agent ids appear in locks, ledgers, and tracing, so the format is enforced strictly.

Source

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

const SANDBOX_MODES: readonly AgentDefinition["sandbox"][] = [
  "required",
  "fixture",
  "host",
];

export function agent(options: {
  id: string;
  instructions: string | FileSource;
  model: Auto | string | Model<Api>;
  reasoning?: AgentDefinition["reasoning"];
  tools?: ToolDefinition[];
  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,

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Rename the id to lowercase kebab/snake case, e.g. 'research-agent'.
  2. If the id is derived from user input, sanitize it (lowercase, replace invalid chars with '-', enforce length) before calling agent().
  3. Keep ids under 96 characters.

Example fix

// before
agent({ id: "Research.Agent/v2", /* ... */ });

// after
agent({ id: "research-agent-v2", /* ... */ });
Defensive patterns

Strategy: validation

Validate before calling

const AGENT_ID_RE = /^[a-z0-9][a-z0-9_-]{0,95}$/;
function toAgentId(raw: string): string {
  const id = raw.toLowerCase().replace(/[^a-z0-9_-]/g, "-").replace(/^-+/, "").slice(0, 96);
  if (!AGENT_ID_RE.test(id)) throw new Error(`cannot derive valid agent id from '${raw}'`);
  return id;
}

Type guard

function isValidAgentId(id: unknown): id is string {
  return typeof id === "string" && /^[a-z0-9][a-z0-9_-]{0,95}$/.test(id);
}

Prevention

When it happens

Trigger: Calling agent({ id, ... }) with an id containing uppercase letters, dots, slashes, spaces, or other symbols; an empty id; an id starting with '-' or '_'; or an id longer than 96 characters.

Common situations: Using a human-readable name with spaces or capitals ('Research Agent'); deriving the id from a file path or package name containing dots; trimming/generating ids from user input without sanitization; very long generated ids.

Related errors


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