How to Debug Workflow Execution Using the Logs Command and Parsing in gh-aw

The gh aw logs command downloads GitHub Actions artifacts and optionally executes engine-specific JavaScript parsers to generate human-readable markdown reports for debugging agentic workflow execution.

Debugging agentic workflows requires visibility into how runs actually executed in GitHub Actions. The github/gh-aw repository provides a comprehensive logs command that not only retrieves raw artifacts but also applies intelligent parsing to transform verbose execution data into actionable insights. This guide explains how to debug workflow execution using the logs command and parsing capabilities implemented in the Go source code.

Command Architecture and Flag Handling

The entry point for log retrieval resides in pkg/cli/logs_command.go, which defines the Cobra command gh aw logs [workflow]. This file handles workflow name resolution via workflow.FindWorkflowName and validates engine parameters against workflow.GetGlobalEngineRegistry.

Key flags include:

  • --start-date: Filter runs by execution timeframe
  • --engine: Target specific engines (copilot, claude, codex)
  • --parse: Execute JavaScript log parsers after download
  • --json: Output structured data instead of formatted tables
  • --tool-graph: Generate Mermaid diagrams of tool interactions

After validation, the command invokes DownloadWorkflowLogs at lines 94-95, passing all parsed parameters to the orchestration layer.

Downloading and Organizing Artifacts

The orchestration logic in pkg/cli/logs_orchestrator.go manages the complete retrieval pipeline. It queries the GitHub API for workflow runs matching the specified filters, then processes each run individually.

For every run, the orchestrator:

  1. Creates a dedicated subdirectory (run-<id>/)
  2. Downloads all artifacts including aw_info.json, agent_output/, and workflow-logs/
  3. Calls flattenSingleFileArtifacts to simplify single-file artifacts (referenced in logs_command.go lines 28-30)
  4. Generates summary.json aggregating duration, token usage, cost calculations, tool usage counts, and MCP failure counts

When the --parse flag is active, the orchestrator triggers the parsing engine after artifact retrieval completes.

Engine Detection and Log Discovery

Before parsing can occur, the system must identify which engine produced the logs and locate the correct file. The pkg/cli/logs_parsing_core.go file implements this discovery logic.

The extractEngineFromAwInfo function (lines 80-108) reads the aw_info.json artifact, unmarshals the engine identifier, and retrieves the corresponding implementation from the global registry. If resolution fails, the system logs a warning and skips parsing for that run.

Once the engine is identified, findAgentLogFile (lines 38-140) handles the complex task of locating the actual log file:

  • Queries engine.GetLogFileForParsing() to get the engine-specific filename
  • Handles three directory layouts: pre-flattened artifacts in agent_output/, flattened paths translated from /tmp/gh-aw/ temporary directories, and legacy recursive scans for session*.log or process*.log files
  • Falls back to agent-stdio.log when no engine-specific file is defined

Executing JavaScript Log Parsers

The actual transformation from raw logs to readable markdown occurs in pkg/cli/logs_parsing_javascript.go. The parseAgentLog function (lines 26-53) orchestrates this process.

Execution flow:

  1. Validates engine presence (aborts if engine == nil)
  2. Invokes findAgentLogFile to locate the source logs
  3. Retrieves the parser script ID via engine.GetLogParserScriptId() (e.g., "copilot_log_parser")
  4. Fetches the actual script source from workflow.GetLogParserScript
  5. Writes raw logs to a temporary file and generates a Node.js bootstrap script
  6. Executes the parser via exec.Command("node", "parser.js")
  7. Writes the resulting markdown to log.md in the run directory

The bootstrap script creates a mock @actions/core API, allowing the same parser code used in production GitHub Actions to execute locally without modification.

Practical Debugging Workflow

Combine the various flags to create targeted debugging sessions:

Step Command Purpose
1. Pull recent runs gh aw logs --start-date -1w -c 5 Downloads the last 5 runs from the past week
2. Focus on an engine gh aw logs --engine copilot --parse Downloads runs, executes the Copilot JavaScript parser, and writes log.md
3. Filter by firewall gh aw logs --firewall Shows only runs where the firewall tool was enabled
4. Inspect raw JSON gh aw logs --json > runs.json Exports the full summary.json structure for scripting or jq queries
5. Analyze tool usage gh aw logs --tool-graph > graph.mmd Generates a Mermaid diagram of tool calls across runs
6. Limit to a branch gh aw logs --ref main Restricts to runs that executed on the main branch

All flags are defined in pkg/cli/logs_command.go (lines 99-118).

Complete Debugging Example

To debug a specific Copilot workflow execution:


# Download and parse the last 3 Copilot runs from the main branch

gh aw logs my-workflow --engine copilot --parse --ref main -c 3

# Inspect the parsed markdown output

cat run-1234567890/log.md

# Query specific metrics from the summary JSON

jq '.[] | {run_id: .run_id, duration: .duration, cost: .cost}' run-1234567890/summary.json

Summary

  • The gh aw logs command in the github/gh-aw repository provides a complete pipeline for debugging workflow execution, from artifact retrieval to intelligent log parsing.
  • The command implementation in pkg/cli/logs_command.go handles flag validation and delegates to DownloadWorkflowLogs for orchestration.
  • The orchestrator downloads artifacts, generates summary.json with cost and token metrics, and optionally triggers parsing.
  • Engine detection via extractEngineFromAwInfo and log discovery via findAgentLogFile ensure the correct files are processed for each workflow engine.
  • JavaScript parsers execute in a sandboxed Node.js environment via parseAgentLog, producing readable log.md reports.
  • CLI flags like --parse, --json, --tool-graph, and --firewall enable targeted debugging workflows for specific engines, branches, or analysis formats.

Frequently Asked Questions

How does gh aw logs determine which log file to parse for different AI engines?

The command uses the findAgentLogFile function in pkg/cli/logs_parsing_core.go to locate the correct file. It first queries the engine implementation via engine.GetLogFileForParsing() to get the engine-specific filename, then handles three directory layouts: pre-flattened artifacts in agent_output/, flattened paths translated from /tmp/gh-aw/ temporary directories, and legacy recursive scans for session*.log or process*.log files. If no engine-specific file is defined, it falls back to agent-stdio.log.

What information is included in the summary.json file generated by the logs command?

The summary.json file is generated by the orchestrator in pkg/cli/logs_orchestrator.go and aggregates key execution metrics for each workflow run. It includes the total duration of the run, token usage statistics, estimated cost calculations, tool usage counts, and MCP (Model Context Protocol) failure counts. This structured data enables programmatic analysis when using the --json flag or allows for quick inspection of run health without parsing raw log files.

Can I use gh aw logs to debug workflows that used the firewall tool?

Yes, the command provides specific support for firewall debugging through the --firewall flag, defined in pkg/cli/logs_command.go. When this flag is specified, the orchestrator filters the workflow runs to show only those where the firewall tool was enabled. Additionally, when using the --parse flag, the system invokes parseFirewallLogs alongside parseAgentLog to generate a firewall.md report containing the firewall-specific execution details and security policy enforcement logs.

How does the JavaScript log parser execute locally without GitHub Actions?

The parseAgentLog function in pkg/cli/logs_parsing_javascript.go creates a sandboxed Node.js environment that mocks the GitHub Actions runtime. It retrieves the parser script ID via engine.GetLogParserScriptId(), fetches the actual script source from workflow.GetLogParserScript, and writes the raw logs to a temporary file. It then generates a bootstrap JavaScript file that creates a mock @actions/core API, allowing the same parser code used in production GitHub Actions to execute locally via exec.Command("node", "parser.js") without modification.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →