JuliusBrussee/caveman · error · Error

caveman agent: subagent maxCalls must be a positive integer

Error message

caveman agent: subagent maxCalls must be a positive integer

What it means

Thrown by createSubagent (the tool factory that wraps an agent definition as a callable tool) when the maxCalls option is not a safe positive integer. maxCaps caps how many times the wrapped subagent may be invoked per tool call, so zero or fractional values are meaningless. The check runs at tool-definition time, before any agent execution starts.

Source

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

   */
  maxCostUsd?: number;
  /**
   * This child's wallet in tokens — the denomination sibling of `maxCostUsd`,
   * used by a token-metered run. A token-metered run cannot fund a subagent
   * that declares no token wallet.
   */
  maxTokens?: number;
  maxContextTokens?: number;
}): ToolDefinition {
  const maxInputChars = options.maxInputChars ?? 32_768;
  if (!Number.isSafeInteger(maxInputChars) || maxInputChars <= 0) {
    throw new Error("caveman agent: subagent maxInputChars must be a positive integer");
  }
  const maxCalls = options.maxCalls ?? 1;
  const maxCostUsd = options.maxCostUsd ?? 1;
  const maxContextTokens = options.maxContextTokens ?? 128_000;
  if (!Number.isSafeInteger(maxCalls) || maxCalls <= 0) {
    throw new Error("caveman agent: subagent maxCalls must be a positive integer");
  }
  if (!Number.isFinite(maxCostUsd) || maxCostUsd <= 0) {
    throw new Error("caveman agent: subagent maxCostUsd must be positive");
  }
  if (options.maxTokens !== undefined &&
      (!Number.isSafeInteger(options.maxTokens) || options.maxTokens <= 0)) {
    throw new Error("caveman agent: subagent maxTokens must be a positive integer");
  }
  if (!Number.isSafeInteger(maxContextTokens) || maxContextTokens <= 0) {
    throw new Error("caveman agent: subagent maxContextTokens must be a positive integer");
  }
  return tool({
    name: options.name,
    description: options.description,
    input: schema.object({ task: schema.string() }),
    effect: "read",
    result: "auto",
    ...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs }),

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Pass an explicit safe integer >= 1, e.g. maxCalls: 3
  2. If the value comes from config/env, coerce and validate first: const maxCalls = Number(raw); Number.isSafeInteger(maxCalls) && maxCalls > 0 ? maxCalls : 1
  3. Round budget-derived floats explicitly: Math.max(1, Math.floor(computed))
  4. Leave maxCalls undefined to accept the default of 1

Example fix

// before
const tool = subagentTool({ agent, name: "worker", maxCalls: Number(cfg.maxCalls) }); // cfg.maxCalls = "5" or 0

// after
const raw = Number(cfg.maxCalls);
const tool = subagentTool({
  agent,
  name: "worker",
  maxCalls: Number.isSafeInteger(raw) && raw > 0 ? raw : 1,
});
Defensive patterns

Strategy: validation

Validate before calling

const maxCalls = Number(cfg.maxCalls);
if (!Number.isSafeInteger(maxCalls) || maxCalls <= 0) {
  throw new Error(`config maxCalls must be a positive integer, got ${JSON.stringify(cfg.maxCalls)}`);
}
const t = subagentTool({ agent, name: "worker", maxCalls });

Type guard

const isPositiveInt = (v: unknown): v is number =>
  Number.isSafeInteger(v) && (v as number) > 0;

Try / catch

try {
  subagentTool({ agent, name: "worker", maxCalls });
} catch (e) {
  if (e instanceof Error && e.message.includes("maxCalls")) { /* fix config, fail startup */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling the subagent tool factory with options.maxCalls = 0, a negative number, a non-integer like 1.5, NaN, Infinity, or a numeric string such as "3". Note the default is 1; the error only fires when you pass an explicit invalid value.

Common situations: Computing maxCalls from an env var or config file (strings like process.env.MAX_CALLS arrive as "5"), passing a budget-derived float (e.g. cost/price = 2.5), or copying an example that used 0 to mean 'unlimited' (this library has no unlimited mode).

Related errors


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