rohitg00/ai-engineering-from-scratch · error · ToolLoopError

maximum turns exceeded

Error message

maximum turns exceeded

What it means

Error "maximum turns exceeded" thrown in rohitg00/ai-engineering-from-scratch.

Source

Thrown at certifications/claude/lessons/10-tool-use-and-agentic-loops/code/main.py:265

        messages: list[dict[str, Any]] = [{"role": "user", "content": request}]
        for _ in range(self.max_turns):
            response = self.model.create(messages)
            blocks = response.get("content")
            if not isinstance(blocks, list):
                raise ToolLoopError("response content must be a list")
            messages.append({"role": "assistant", "content": copy.deepcopy(blocks)})
            reason = response.get("stop_reason")
            if reason == "end_turn":
                text = "".join(block.get("text", "") for block in blocks if block.get("type") == "text")
                return text, messages
            if reason != "tool_use":
                raise ToolLoopError(f"unsupported stop reason: {reason}")
            calls = [block for block in blocks if block.get("type") == "tool_use"]
            if not calls:
                raise ToolLoopError("tool_use stop without calls")
            results = [self.registry.execute(block, self.approve) for block in calls]
            messages.append({"role": "user", "content": results})
        raise ToolLoopError("maximum turns exceeded")


def demo() -> tuple[str, list[dict[str, Any]]]:
    add = Tool(
        "add",
        "Add two integers.",
        {"type": "object", "required": ["a", "b"], "additionalProperties": False, "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}}},
        lambda data: data["a"] + data["b"],
    )
    model = ScriptedModel([
        {"stop_reason": "tool_use", "content": [{"type": "tool_use", "id": "call_1", "name": "add", "input": {"a": 7, "b": 8}}]},
        {"stop_reason": "end_turn", "content": [{"type": "text", "text": "The total is 15."}]},
    ])
    return ToolLoop(model, ToolRegistry([add])).run("Add 7 and 8")


def decision_lab() -> dict[str, Any]:
    """Return checked architecture decisions without importing an SDK."""

View on GitHub (pinned to 39ea8a1c6d)

When it happens

Trigger: Thrown at certifications/claude/lessons/10-tool-use-and-agentic-loops/code/main.py:265 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/ac12dd39a73c863c. Report an issue: GitHub.