Skip to content
Everything Agents

Lesson 7 of 14 · 6 min

Reading session traces

Traces are the truth. EnabledToolsStep tells you what the LLM saw; VariableUpdateStep tells you why state changed.

The dev loop ends with "read traces." This lesson is the rest of that step. Traces are the single most useful debugging artifact, and every preview session writes them to disk:

.sfdx/agents/<bundle_name>/sessions/<session_id>/traces/<plan_id>.json

A trace is an ordered list of typed steps. The handful that matter:

The shape of one trace, in orderA vertical timeline of the seven trace step types written for a single planner turn. EnabledToolsStep and LLMStep are highlighted: together they show what the LLM saw and what it picked.TRACE STEP TIMELINEUserInputStepwhat the user actually typedNodeEntryStateStepwhich subagent the planner pickedVariableUpdateStepinstructions resolveEnabledToolsStepwhich actions this turn could usewhat the LLM sawLLMStepthe model's choice for this turnwhat the LLM pickedVariableUpdateStepset clauses fire (post-action)PlannerResponseStepreply to the user
Step typeWhat it answers
UserInputStepWhat the user actually typed
NodeEntryStateStepWhich subagent the planner picked
EnabledToolsStepWhich actions the LLM could see this turn
LLMStepWhat the LLM chose to do
VariableUpdateStepHow variables changed and why
PlannerResponseStepThe final reply to the user

Diagnostic recipes

"My action isn't being called." Find EnabledToolsStep for the relevant topic. Is the action listed?

  • Not listed: available when is too restrictive, or perms missing, or action not in reasoning.actions:.
  • Listed but not called: action description does not match user intent enough. Tighten the description.

"My variables are getting wrong values." Find every VariableUpdateStep for that variable. Note directive_context:

  • after_action: came from set clauses or after_reasoning.
  • on_message: came from before_reasoning or start_agent.

"The agent stalled, replied without acting." Look for LLMStep that returned an Inform response with no preceding ActionInvocationStep. The LLM chose to talk instead of act. Usually the action description is unclear or instructions: does not tell the LLM when to invoke vs. when to ask.

Walking a trace in code

import json
d = json.load(open('traces/<plan_id>.json'))
for s in d['plan']:
    t = s.get('type')
    if t == 'EnabledToolsStep':
        print(s['data']['agent_name'], '->', s['data']['enabled_tools'])
    elif t == 'VariableUpdateStep':
        for u in s['data']['variable_updates']:
            n = u['variable_name']
            if not n.startswith('__') and not n.startswith('AgentScriptInternal'):
                print(f"{n}: {u['variable_past_value']!r} -> "
                      f"{u['variable_new_value']!r} ({u['directive_context']})")

This 8-line script answered every "why did it do that?" question we had.

If you take one habit away from this tutorial, it is this: never debug an Agent Script bug from the assistant's reply alone. Always look at the trace.

Quick check

Your agent replies 'I am verifying your identity now' but never actually calls your VerifyCustomer Apex. Which trace step do you check first?