Skip to main content

Debugging Agents

Agent failures are rarely obvious from error messages alone. This page covers how to inspect traces, analyse tool calls, iterate on prompts, and diagnose the most common failure modes.

Toolbox

Before debugging, confirm you have access to these tools:
ToolPurpose
LangfuseTrace inspection, span hierarchy, token usage, LLM input/output
ADK Web (adk web)Interactive ADK agent debug UI — replay conversations, inspect tool calls
curl / jqDirect A2A JSON-RPC invocation for isolated testing
Agent Card (/.well-known/agent-card.json)Verify capabilities and skills are declared correctly
Application logsStructured JSON logs with task_id, context_id, user_id for correlation

Reading a Trace in Langfuse

Every agent request produces a trace in Langfuse. The span hierarchy for a Pydantic AI agent looks like:
Key attributes to check:
  • agent.response_length — if 0, the agent produced no output (likely an error)
  • mcp.tool.statussuccess or error classification
  • mcp.tool.result_size_bytes — large values (>50KB) indicate context bloat risk
  • gen_ai.usage.input_tokens / gen_ai.usage.output_tokens — token budget

Symptom Index

Most likely causes:
  1. Task validation failure — the request is missing task_id, context_id, or authenticated user context. Check application logs for ValueError: Task ID and Context ID must be provided.
  2. Authentication error — the JWT token is missing or invalid. If your executor validates the Authorization header before processing the task, a missing or invalid token raises before emitting any events.
  3. MCP connection failure — the StreamableHttpTransport cannot connect to the MCP server. Check that MCP_SERVER_URL is set and the MCP pod is healthy.
Diagnostics:
Most likely causes:
  1. MCP server returning errors — the tool call reaches the MCP server but returns a structured error. Check mcp.tool.status in the trace span.
  2. Iteration limit hit — the agent has exceeded max_code_failures. Look for log line: Iteration limit reached for task {task_id}.
  3. Forbidden operation — the tool call uses a restricted pattern (e.g., filesystem access, blocked import). Look for LINT_ERROR in the tool result.
  4. Tool schema mismatch — the LLM is passing incorrect argument types. Check the mcp.tool.param_fingerprint across calls — if it’s consistent and always failing, the tool schema is wrong.
Diagnostics:
Symptoms: Agent responses become shorter, less accurate, or the LLM refuses to call tools. Token usage approaches the model’s context limit.Most likely causes:
  1. Tool results too large — a tool is returning large payloads (DataFrames, Plotly figures) directly to the LLM. Your toolset should strip large fields and store them in the Assets API, passing only the resource URI.
  2. Conversation history too long — the task store is loading the full conversation history. Check agent.context_metrics.history_messages in the trace.
  3. System prompt too large — the instruction builder is including too much context. Check agent.context_metrics.instruction_length.
Diagnostics:
Fix: Implement side payload interception in your toolset. Strip large data blobs (DataFrames, images, Plotly figures) before they reach the LLM context window; store them in the Assets API and pass only the resource URI.
Symptoms: A single agent request consumes 10x the expected tokens. The LLM is looping on tool calls or generating excessively long responses.Most likely causes:
  1. Missing iteration limit — no max_code_failures guard on code execution tool. The LLM keeps trying different code variations.
  2. Tool always returning errors — the LLM keeps retrying a broken tool. Check mcp.tool.status across the trace — all error with the same tool name is a signal.
  3. Infinite delegation loop — two agents are delegating to each other. Check the orchestrator’s sub_agents list for circular references.
  4. Large system prompt being rebuilt per turn — the instruction builder is fetching context on every LLM round-trip. Check agent.context_metrics.instruction_build_duration_s.
Diagnostics:
Fix:
Symptoms: state=failed with message “No datasource DataPart found” or “resource_uri resolution failed”.Most likely causes:
  1. Missing DataPart in the message — the caller did not include a DataPart with type: "datasource". The A2A message must include both a TextPart and a DataPart.
  2. Wrong resource_uri format — the resource_uri must be in the full four-segment format: data:{org_id}:{project_id}:{name}. The simplified format (data:my-db) is not accepted.
  3. Missing selected_schemasselected_schemas is empty or absent. Text2SQL requires exactly one schema entry.
Diagnostics:

Prompt Iteration

The fastest way to improve agent quality is iterating on the system prompt. Use ADK Web or direct A2A calls to test prompt changes without redeploying.

ADK Web — Interactive Replay (Google ADK)

ADK Web shows each tool call, its arguments, and the LLM’s reasoning before and after. Use it to observe exactly how the prompt influences routing and tool selection.

Claude Agent SDK — Prompt Replay

For Claude-based agents, replay prompt variations using the Anthropic SDK directly without running the full A2A server:
Trace inspection: look for anthropic.messages.create spans in Langfuse. Tool use blocks appear as child spans with input and output fields.

LangGraph — Debug with debug=True

LangGraph’s astream supports verbose debug output and LangSmith/Langfuse tracing:
For production tracing, pass the langfuse_handler callback (see Eval Harness) — spans appear as langgraph:node:<name> entries in Langfuse.

Minimal Repro with Direct curl

For non-ADK agents, replay failing conversations directly:

Prompt Change Checklist

Before changing the system prompt:
  1. Identify the specific behaviour to change (use a Langfuse trace as evidence)
  2. Write a test case that captures the failure
  3. Make the minimum prompt change needed to fix the test case
  4. Run the full regression suite to check for new regressions
  5. Re-check token usage — prompt changes can inflate or deflate input token cost

Structured Logging for Correlation

All CRAFT agents log structured JSON with task_id and context_id. Use these to correlate logs with Langfuse traces:

Next Steps

Eval Harness

Build regression suites to catch issues before they reach production.

Langfuse Setup

Configure Langfuse tracing for your agent.