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:
- Creates a dedicated subdirectory (
run-<id>/) - Downloads all artifacts including
aw_info.json,agent_output/, andworkflow-logs/ - Calls
flattenSingleFileArtifactsto simplify single-file artifacts (referenced inlogs_command.golines 28-30) - Generates
summary.jsonaggregating 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 forsession*.logorprocess*.logfiles - Falls back to
agent-stdio.logwhen 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:
- Validates engine presence (aborts if
engine == nil) - Invokes
findAgentLogFileto locate the source logs - Retrieves the parser script ID via
engine.GetLogParserScriptId()(e.g.,"copilot_log_parser") - Fetches the actual script source from
workflow.GetLogParserScript - Writes raw logs to a temporary file and generates a Node.js bootstrap script
- Executes the parser via
exec.Command("node", "parser.js") - Writes the resulting markdown to
log.mdin 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 logscommand in thegithub/gh-awrepository provides a complete pipeline for debugging workflow execution, from artifact retrieval to intelligent log parsing. - The command implementation in
pkg/cli/logs_command.gohandles flag validation and delegates toDownloadWorkflowLogsfor orchestration. - The orchestrator downloads artifacts, generates
summary.jsonwith cost and token metrics, and optionally triggers parsing. - Engine detection via
extractEngineFromAwInfoand log discovery viafindAgentLogFileensure the correct files are processed for each workflow engine. - JavaScript parsers execute in a sandboxed Node.js environment via
parseAgentLog, producing readablelog.mdreports. - CLI flags like
--parse,--json,--tool-graph, and--firewallenable 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →