Skip to content

Docs: base-action README example for parsing execution_file uses stale e.role === 'assistant'; current SDK output has top-level e.type #1296

@TrueBurn

Description

@TrueBurn

Summary

The example in base-action/README.md for parsing execution_file walks the array looking for e.role === 'assistant'. That field doesn't exist at the top level of any event the action currently emits, so the example matches zero events and silently falls through.

Where the example is

base-action/README.md (the "Claude Code Review" / "Extract and Comment PR Review" example):

const executionLog = JSON.parse(fs.readFileSync(executionFile, 'utf8'));
let review = '';
for (let i = executionLog.length - 1; i >= 0; i--) {
  if (executionLog[i].role === 'assistant') {     //  <-- never matches
    review = executionLog[i].content;
    break;
  }
}

Why it doesn't work

base-action/src/run-claude-sdk.ts writes the file as:

await writeFile(EXECUTION_FILE, JSON.stringify(messages, null, 2));

…where messages: SDKMessage[] from @anthropic-ai/claude-agent-sdk. SDK events use type at the top level; role only exists nested inside message:

[
  { "type": "system",    "subtype": "init", "session_id": "..." },
  { "type": "user",      "message": { "role": "user", "content": [ ... ] } },
  { "type": "assistant", "message": { "role": "assistant", "content": [ { "type": "text", "text": "..." } ] } },
  { "type": "result",    "subtype": "success", "result": "<final text>", "is_error": false, "total_cost_usd": ..., ... }
]

So e.role is always undefined and the loop falls through. Downstream steps then post nothing (or in my case, log "no assistant message found") and the user can't tell the example is wrong without reading the source.

Reproduction

Minimal workflow that follows the README example verbatim:

- id: claude
  uses: anthropics/claude-code-action@v1
  with:
    use_bedrock: "true"        # or anthropic_api_key for the 1P provider
    prompt: "Reply with: hello"
    claude_args: --max-turns 1

- uses: actions/github-script@v9
  with:
    script: |
      const fs = require('fs');
      const log = JSON.parse(fs.readFileSync('${{ steps.claude.outputs.execution_file }}', 'utf8'));
      for (let i = log.length - 1; i >= 0; i--) {
        if (log[i].role === 'assistant') {
          core.info('found: ' + log[i].content);
          return;
        }
      }
      core.info('no assistant message found');   // <-- this is what fires on every run

core.info('no assistant message found') fires on every successful run.

Suggested fix (docs)

Update the example to match the actual SDK shape. The canonical "final answer" event is type: "result" with a plain result string:

const log = JSON.parse(fs.readFileSync(executionFile, 'utf8'));

// Preferred: the SDK's documented final-answer event.
const result = log.find(e => e && e.type === 'result' && typeof e.result === 'string');
let review = result ? result.result : '';

// Fallback: last assistant text block (covers runs that abort before `result`).
if (!review) {
  for (let i = log.length - 1; i >= 0; i--) {
    const e = log[i];
    if (e && e.type === 'assistant' && e.message && Array.isArray(e.message.content)) {
      review = e.message.content
        .filter(c => c && c.type === 'text' && typeof c.text === 'string')
        .map(c => c.text)
        .join('\n');
      if (review) break;
    }
  }
}

It might also be worth adding a one-line pointer to --json-schema + outputs.structured_output for users who want a typed surface and don't want to parse the file at all.

Environment

  • Action: anthropics/claude-code-action@v1
  • Provider: AWS Bedrock (use_bedrock: "true"), but the file shape is provider-independent (it's whatever the SDK emits).
  • Confirmed against base-action/src/run-claude-sdk.ts at main.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentationp2Non-showstopper bug or popular feature request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions