Search⌘ K
AI Features

Debugging the Agent Transcript

Explore methods to debug agent loops built with the Claude Client SDK by implementing structured logging at each iteration stage. Learn how to trace failing runs, interpret logs of API calls, tool usage, and stop reasons, and identify common bugs like missing assistant turns. This lesson equips you to produce readable, comprehensive error diagnostics to improve reliability and maintainability of Claude-powered AI agents.

The loop from the previous lessons works, but when it breaks, there is nothing to inspect. The messages array changes on every iteration, tool calls come and go, and errors surface only as wrong output or silent None returns. Without visibility into what happened between the first API call and the final answer, debugging is guesswork.

In this lesson, we instrument the loop with structured logging that prints state at each decision point. We then use that output to trace a failing run and identify the exact turn where it went wrong.

By the end of this lesson, we will have:

  • A logging helper that formats message-array turns in human-readable form

  • Turn-level log output for every API call, stop reason, tool call, and tool result

  • A failing transcript annotated to show where and why it breaks

  • A methodology for reading agent transcripts that applies to any loop

What to log and why

A loop produces four types of events worth capturing, each at a different moment in the iteration:

Event

When It Fires

What to Capture

API call

Before client.messages.create()

Turn count, message count, input token estimate

Stop reason

After the response arrives

stop_reason, response id, output token count

Tool dispatch

Before each tool function runs

Tool name, input arguments

Tool result

After each tool function returns

Tool name, result string (truncated if long)

These four points cover the full life cycle of one iteration. Any failure in the loop, wrong stop reason handling, missing tool result, ID mismatch, or truncation will be visible in at least one of these log lines.

The logging helper

Rather than scattering print() calls throughout the loop, we write one helper that formats any event as a consistent, scannable line:

import json
def log(event: str, **kwargs) -> None:
parts = [f"[{event}]"]
for key, value in kwargs.items():
if isinstance(value, (dict, list)):
parts.append(f"{key}={json.dumps(value, default=str)[:120]}")
else:
parts.append(f"{key}={value}")
print(" ".join(parts))
A minimal logging helper. It formats an event name and key-value pairs into a single scannable line, truncating long values to keep output readable.
  • Line 1: We import json to serialize dicts and lists inline.

  • Line 3: log takes an event name and any number of keyword arguments. The caller decides what context to attach.

  • Lines 4–8: We build a ...