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

agent({{schema}}) invalid output: {err}

Error message

agent({{schema}}) invalid output: {err}

What it means

When agent() is called with a schema, the runner is forced into StructuredOutput mode and the result is validated with SimpleJsonSchema. On the first failure the model is retried once with 'Return valid JSON.' appended; if the retry also fails validation, WorkflowInputError with the schema error text is raised. Nothing is journaled for the failed call, so a later retry re-runs the agent from scratch.

Source

Thrown at s16_workflow_runtime/code.py:496

                self.runner.run, prompt, schema, label
            )
            result = run.value
            tokens = run.tokens

        if schema is not None:
            ok, err = SimpleJsonSchema(schema).validate(result)
            if not ok:
                retry = await asyncio.to_thread(
                    self.runner.run,
                    prompt + "\n\nReturn valid JSON.",
                    schema,
                    label,
                )
                result = retry.value
                tokens += retry.tokens
                ok, err = SimpleJsonSchema(schema).validate(result)
                if not ok:
                    raise WorkflowInputError(f"agent({{schema}}) invalid output: {err}")

        self.budget.add(tokens)
        self.task.usage["agents"] += 1
        self.task.usage["tokens"] += tokens
        self.journal.record(key, result)
        self.task.progress_event("workflow_agent", label=label,
                                 phase=phase or self._phase, status="done")
        return result

    async def parallel(self, thunks):
        """BARRIER: run all thunks concurrently and fail if any thunk fails."""
        return await asyncio.gather(*[thunk() for thunk in thunks])

    async def pipeline(self, items, *stages):
        """Per-item staged flow, NO barrier between stages: item A can be in
        stage 3 while item B is still in stage 1. Each stage gets
        (prev_result, original_item, index). A throwing stage fails the workflow."""
        async def run_item(item, idx):

View on GitHub (pinned to 985456f4ad)

Solutions

  1. Simplify the schema: fewer required fields, flatter structure, relax types (e.g. accept string|number), allow additional properties.
  2. Make the prompt explicitly request every required field with the exact names and types the schema expects.
  3. Increase the runner's max output tokens so the JSON is not truncated.
  4. Re-run the workflow — the failed attempt was not journaled, so the agent gets two fresh attempts under the improved schema.

Example fix

# before
schema = {"type": "object", "required": ["findings", "severity", "citations"],
           "additionalProperties": False}

# after
schema = {"type": "object", "required": ["findings"],
           "properties": {"findings": {"type": "array"}}}
Defensive patterns

Strategy: retry

Validate before calling

from s16_workflow_runtime import SimpleJsonSchema
def schema_is_model_feasible(schema) -> bool:
    # cheap sanity: object root, <= 5 required keys, no deep nesting
    props = schema.get("properties", {})
    req = schema.get("required", [])
    return schema.get("type") == "object" and len(req) <= 5 and len(props) <= 10

Try / catch

last = None
for attempt in range(3):
    try:
        return await ctx.agent(prompt, schema=S, label=lbl)
    except WorkflowInputError as e:
        if "invalid output" not in str(e):
            raise
        last = e
        prompt += "\nRespond ONLY with JSON matching: " + json.dumps(S)
raise last

Prevention

When it happens

Trigger: ctx.agent(prompt, schema=...) where the model returns JSON that violates the schema twice in a row — e.g. missing required fields, wrong types, extra fields when additionalProperties is false, or truncated output.

Common situations: Overly strict or nested schemas the model can't satisfy; required fields the prompt never asks for; long outputs hitting max tokens and truncating the JSON; weak models on structured output.

Related errors


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