shareAI-lab/learn-claude-code · error · WorkflowInputError

token budget exceeded

Error message

token budget exceeded

What it means

ExecutionState.agent() checks Budget.remaining() before spawning each subagent and raises WorkflowInputError('token budget exceeded') when the run-wide token budget is already exhausted. The budget is shared across the whole workflow, including nested child workflows and parallel/pipeline agents, and only successful runs add their tokens via budget.add(). This is a hard stop so a workflow cannot silently overspend.

Source

Thrown at s16_workflow_runtime/code.py:461

    def phase(self, title):
        """Start a phase; subsequent agent()s group under it. Upsert: emitting the
        same phase again (e.g. from each pipeline item) does not re-announce it."""
        self._phase = title
        if title not in self._phases_seen:
            self._phases_seen.add(title)
            self.task.progress_event("workflow_phase", title=title)

    def log(self, message):
        """Emit a workflow_log progress line."""
        self.task.progress_event("workflow_log", message=message)

    async def agent(self, prompt, schema=None, label=None, phase=None):
        """Spawn one subagent. With a schema, force StructuredOutput + validate
        (retry once). On resume, a cached key short-circuits the run."""
        label = label or (prompt[:24] + "...")
        self._limits.claim_agent()
        if self.budget.remaining() <= 0:
            raise WorkflowInputError("token budget exceeded")

        key = self.journal.key("agent", label, prompt, schema)
        cached = self.journal.cached(key)
        if cached is not MISS:
            if schema is not None:
                ok, err = SimpleJsonSchema(schema).validate(cached)
                if not ok:
                    raise WorkflowInputError(
                        f"cached agent output failed schema validation: {err}"
                    )
            self.task.progress_event("workflow_agent", label=label,
                                     phase=phase or self._phase, status="cached")
            return cached

        async with self._limits.semaphore:
            run = await asyncio.to_thread(
                self.runner.run, prompt, schema, label
            )

View on GitHub (pinned to 985456f4ad)

Solutions

  1. Raise the token budget total configured for the workflow (e.g. meta's budget field) so remaining() stays positive for all planned agent() calls.
  2. Reduce agent count: batch items, shrink pipeline dimensions, or reuse one agent call for multiple inputs.
  3. Shrink prompts/outputs: tighten the JSON schema (fewer/lower max lengths) and trim the text embedded into prompts.
  4. If mid-run: fix the budget and resume from the last runId — cached agents replay without new token spend, but the budget total must be > 0 at each call site.

Example fix

// before
meta = {"name": "review", "tokenBudget": 5000}
// 20 pipeline agents x ~400 tokens each exhausts it

// after
meta = {"name": "review", "tokenBudget": 50000}
// or reduce fan-out:
for dimension in ["security", "correctness"]:  # was 6 dimensions
    ...
Defensive patterns

Strategy: validation

Validate before calling

async def agent_guarded(ctx, prompt, schema=None, label=None):
    if ctx.budget.remaining() <= 0:
        raise InsufficientBudget(f"remaining={ctx.budget.remaining()}")
    return await ctx.agent(prompt, schema=schema, label=label)

Type guard

def has_budget(ctx) -> bool:
    return ctx.budget.remaining() > 0

Try / catch

from s16_workflow_runtime import WorkflowInputError
try:
    out = await ctx.agent(prompt, schema=S)
except WorkflowInputError as e:
    if "budget" in str(e):
        checkpoint_and_report_budget(ctx)  # surface spent/remaining, stop cleanly
    raise

Prevention

When it happens

Trigger: Calling ctx.agent() (directly or inside pipeline/parallel stages) after prior agent runs have consumed >= the budget total configured for the workflow run. Note the check runs BEFORE the journal cache lookup, so even a resume that would only replay cached agents fails if the fresh Budget object is created with an already-exhausted total.

Common situations: Budget total in workflow meta set too low for the number of agent calls; a pipeline fan-out over many items multiplying token usage; resuming a large run with the same tight budget; a verbose schema causing big outputs.

Related errors


AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14). Data as JSON: /api/errors/c4bddd686571ee87. Report an issue: GitHub.