Why Your aI Agent Burns 4x the Tokens on a Simple pR Review

gh pr view --comments doesn’t return thread replies. That breaks an agent workflow.

Four months ago, while running agents on SWE-bench Verified, I noticed they were completely ignoring inline comments in GitHub PRs.

The reason turned out to be simple. gh pr view --comments only returns top-level comments. Thread replies — where the actual code review conversation happens — never show up.

For any agent doing code review, thread replies are the context. Without them, the agent is blind to the most important part of the review.

The Deeper Problem: gh api Is Not Agent-Friendly

The workaround is gh api. But that turns a basic question like “show me unresolved comments” into a multi-step chain:

  1. Agent constructs a GraphQL query with gh api. Pipes results through --jq to filter
  2. Gets IDs it runs a query again
  3. Gets it wrong on the first attempt (wrong field path, missed pagination)
  4. Retries and finally gets the answer

I recorded this happening with Claude Code — it took multiple gh calls and roughly 4x more tokens than necessary to answer a basic question about unresolved threads.

The core issue isn’t that gh api lacks functionality. It’s that the response shape is wrong for agents:

  • Too many fields. URLs, hashes, optional metadata — all inflate the prompt. Every extra field is a token spent and a potential source of misinterpretation.
  • No server-side filtering. The agent fetches everything, then filters client-side. Wasteful and error-prone.
  • Non-deterministic chains. The agent has to decide how to query, how to filter with jq, how to reshape — three decision points where it can fail.

gh pr-review: A Purpose-Built Alternative

We built gh pr-review as a GitHub CLI extension that collapses multi-step review tasks into single commands with compact, deterministic JSON.

The design follows Anthropic’s guidance on writing tools for agents: single-command aggregation, minimal payloads, and deterministic output shapes.

Before: Chained gh api + jq

gh api graphql 
  -f query='
    query($owner:String!, $repo:String!, $number:Int!) {
      repository(owner:$owner, name:$repo) {
        pullRequest(number:$number) {
          reviewThreads(first:100) {
            nodes {
              id isResolved
              comments(last:10) {
                nodes { id author { login } body }
              }
            }
          }
          reviews(first:100, states:[CHANGES_REQUESTED]) {
            nodes { author { login } state }
          }
        }
      }
    }' 
  -F owner=owner -F repo=repo -F number=42 
| jq '
  .data.repository.pullRequest
  | {
      threads: (
        .reviewThreads.nodes
        | map(select(.isResolved==false)
          | .comments.nodes[-2:])),
      reviews: .reviews.nodes
    }'

After: One Command

gh pr-review review view 42 -R owner/repo 
  --reviewer octocat 
  --states CHANGES_REQUESTED 
  --unresolved 
  --tail 2 
  --include-comment-node-id

Output:

{
  "pull_request_number": 42,
  "filters": {
    "reviewer": "octocat",
    "states": ["CHANGES_REQUESTED"],
    "unresolved": true,
    "tail": 2
  },
  "reviews": [
    { "author": "octocat", "state": "CHANGES_REQUESTED" }
  ],
  "threads": [
    {
      "id": "PRRT_123456",
      "resolved": false,
      "comments": [
        { "author": "octocat", "body": "Nit: naming is inconsistent.", "node_id": "RVWC_abc123" },
        { "author": "octocat", "body": "Please update the tests.", "node_id": "RVWC_def456" }
      ]
    }
  ]
}

No nested data.repository.pullRequest paths. No cursor pagination to handle. No fields the agent will never use.

Design Decisions

GraphQL-only, no REST fallback. Mixing REST and GraphQL means two data models, two ID schemes (numeric vs node ID), and shape mismatches between endpoints. We use GraphQL exclusively. The tradeoff is no fallback if the GraphQL schema changes, but in practice this eliminates an entire class of bugs.

Server-side filtering. --reviewer--states--unresolved--tail N are all applied before the response is built. The agent never sees data it didn’t ask for. This matters because agent context windows are finite — every irrelevant thread is a thread that displaces useful context.

Deterministic output shape. Same filters, same PR state → same JSON structure. Field names are stable, ordering is consistent. This is the contract between a non-deterministic agent and a deterministic tool, and it needs to be tight.

Minimal fields. No createdAt, no updatedAt, no url, no databaseId unless you explicitly ask for IDs with --include-comment-node-id. The default output contains only what’s needed to decide and act.

Full Workflow

The extension covers the entire review lifecycle — view, reply, resolve, start/add/submit:

# View unresolved threads from a specific reviewer
gh pr-review review view 42 -R owner/repo 
  --reviewer octocat --unresolved --tail 2

# Reply to a thread
gh pr-review comments reply 42 -R owner/repo 
  --thread-id PRRT_123456 
  --body "Fixed in latest push."

# Resolve a thread
gh pr-review threads resolve 42 -R owner/repo 
  --thread-id PRRT_123456

# Start a pending review
gh pr-review review --start 42 -R owner/repo

# Add an inline comment on a specific line
gh pr-review review --add-comment 42 -R owner/repo 
  --path src/foo/bar.ts --line 128 
  --body "Consider extracting to a helper."

# Submit
gh pr-review review --submit 42 -R owner/repo 
  --event COMMENT --body "Looks good overall."

Each command maps to one review action. No intermediate state for the agent to track or reconstruct.

Caveats

  • Pagination on large PRs. Very large PRs may need multiple review view calls. --tail N helps cap comment payload size deterministically.
  • Reviewer matching is by login only. Team-based filters aren’t supported yet.
  • Commit scoping. --commit <sha> pins review context to a specific commit. If the SHA doesn’t match the PR head, you’ll get stale context.
  • Auth. Requires gh auth login. Prebuilt linux-arm64 binaries are available; other platforms build from source.

Installation

gh extension install agynio/gh-pr-review

As a Claude Code skill:

npx skills add agynio/gh-pr-review -a claude-code

GitHub: github.com/agynio/gh-pr-review


We use this daily and it’s currently in the top 5% of GitHub CLI extensions. If you’re building agent workflows around GitHub, feedback and contributions are welcome via the repo.

Liked Liked