Skip to content

[agentic-token-optimizer] Daily XKCD Comic — Eliminate 60-turn iteration drift with deterministic setup-step pre-selection #160

@github-actions

Description

@github-actions

Target Workflow

Daily XKCD Comic (daily-xkcd.md)
Selected as the highest-spend eligible workflow (979 AIC, 2 runs in 7 days) with no prior optimization entry and clear structural causes for its extreme turn variance.


Analysis Period & Runs Analyzed

Period Runs Window
2026-06-18 2 Last 7 days

Spend Profile

Metric Run 1 (baseline) Run 2 (high-AIC) Total / Avg
Event workflow_dispatch schedule
AIC 89 890 979 total / 490 avg
Tokens 251,624 2,595,370 2,846,994 total
Turns 9 62 avg 35.5
Action minutes 7 min 17 min 24 min total
Cache efficiency 86.5% 96.7%

The two runs show a 10× AIC divergence driven entirely by a 6.9× turn spike (9 → 62). Both runs concluded successfully; the output was a single GitHub Discussion. The high cache efficiency in Run 2 confirms the expensive turns are LLM reasoning over an already-loaded context, not repeated large fetches.


Root Cause: Iterative Comic-Selection Loop

The setup step pre-fetches latest.json and latest_num.txt. The agent prompt then instructs the agent to:

  1. Check if the latest comic is relevant.
  2. If not, pick from a 50-item curated list using date +%j mod list_size.
  3. Fetch the chosen comic via web_fetch or curl and verify relevance.
  4. If not relevant, pick the next comic and retry (max 3 attempts).

In the baseline run (dispatch), the agent used the pre-fetched latest comic directly — 9 turns. In the scheduled run, the latest comic was not deemed relevant, triggering the curated-list path. Firewall logs confirm the agent spent 57 of 62 turns deliberating before its first external xkcd.com call. Only 3 curl calls hit xkcd.com (all for comic #1319), but those happened at turn 58 — the preceding 57 turns were entirely LLM reasoning about which comic to pick and evaluating list options.

The CompactionProcessor kicked in at turn 15 (context 31K → 4K tokens), indicating the conversation grew unexpectedly long even mid-task. The context then rebuilt to 66K by turn 62.

References:


Ranked Recommendations

1. Pre-select the comic in a setup step (eliminate the selection loop)

Estimated savings: ~340–390 AIC/run on scheduled runs (≈80% of the scheduled-run cost)

The current design leaves comic selection entirely to the agent. Since the curated list is static and the selection formula is deterministic (date +%j mod list_size), this computation belongs in a steps: block — not inside the LLM session.

Proposed change — extend the existing steps: block with a second step that selects and pre-fetches the comic:

steps:
  - name: Fetch latest XKCD comic number
    run: |
      set -euo pipefail
      mkdir -p /tmp/gh-aw/agent/xkcd
      curl -sSfL "(xkcd.com/redacted) -o /tmp/gh-aw/agent/xkcd/latest.json
      LATEST=$(jq -r '.num' /tmp/gh-aw/agent/xkcd/latest.json)
      echo "$LATEST" > /tmp/gh-aw/agent/xkcd/latest_num.txt
  - name: Pre-select comic for today
    run: |
      set -euo pipefail
      COMICS=(303 327 353 386 456 519 664 705 722 737 844 859 936 1068 1168 1205 \
              1319 1425 1443 1537 1739 55 135 174 687 712 715 881 882 1236 1261 \
              1379 1478 1754 2048 2100 1838 1875 2050 2173 2347 2440 2501 2545 \
              2581 2674 2746 2785 2860 2916 2925)
      DOY=$(date +%j)
      IDX=$(( DOY % ${#COMICS[@]} ))
      SELECTED="${COMICS[$IDX]}"
      curl -sSfL "(xkcd.com/redacted) \
        -o /tmp/gh-aw/agent/xkcd/selected.json
      echo "Selected comic: #$SELECTED ($(jq -r '.title' /tmp/gh-aw/agent/xkcd/selected.json))"

Also add -L to the first curl to follow the HTTP→HTTPS 301 redirect (firewall logs showed 3 failed HTTP GETs before a successful HTTPS CONNECT). This fixes the redirect issue for both steps.

Prompt update — replace the ## Comic Selection section with a direct read instruction:

## Comic Selection

The pre-selected comic for today is in `/tmp/gh-aw/agent/xkcd/selected.json`.
Read it directly — no additional fetching is needed unless the file is missing.

This eliminates the iterative verification loop entirely, capping the agent at the same ~9-turn profile as the baseline dispatch run.


2. Add -L flag to existing setup curl to fix HTTP→HTTPS redirects

Estimated savings: 1–5 turns per scheduled run (avoids retry loops when latest comic check is attempted with HTTP)

The existing setup step uses curl -sSf without -L, so if xkcd.com ever redirects from HTTP to HTTPS, the step gets a 301 and the fetched file is incomplete. This can cause the agent to re-fetch later inside its session. Change to curl -sSfL.

Evidence: Firewall log for run §27753927403 shows:

GET 301 TCP_MISS:HIER_DIRECT (xkcd.com/redacted) "curl/8.5.0"
GET 301 TCP_MISS:HIER_DIRECT (xkcd.com/redacted) "curl/8.5.0"
GET 301 TCP_MISS:HIER_DIRECT (xkcd.com/redacted) "curl/8.5.0"
CONNECT 200 TCP_TUNNEL:HIER_DIRECT xkcd.com:443

Three HTTP attempts before the redirect was followed via CONNECT.


3. Simplify the prompt body (remove the 50-item curated list from agent context)

Estimated savings: ~15–25 AIC/run (reduces ambient context ~1,500–2,000 tokens across all turns)

Once pre-selection moves to a setup step, the 50-item curated list in the prompt body serves no purpose and adds ~1,500 tokens to every turn's context. Remove the list and the selection formula from the prompt. The agent only needs to know where to read the pre-selected comic.


4. Remove unused tools from the allow-list

Estimated savings: 2–5 AIC/run (marginal — reduces tool schema in ambient context)

The workflow configures bash: [curl, jq, bash, echo, date, expr]. The actual runner allow-list for run §27753927403 included additional tools inherited from defaults: cat, grep, head, ls, printf, pwd, sort, tail, uniq, wc, yq. None of these were observed in external I/O. Once the comic selection moves to a setup step, expr and date are also no longer needed inside the agent session.

Tool configuration analysis
Tool In workflow config Observed used Recommendation
curl Yes Yes (3 calls, after fix: 0) Keep for fallback / Remove post-fix
jq Yes Likely yes (JSON parsing) Keep
bash Yes Yes Keep
echo Yes Yes Keep
date Yes Yes (in current; not needed post-fix) Remove after Rec 1
expr Yes Unclear Remove after Rec 1
yq Inherited No external signal Remove
ls, cat, head, tail, etc. Inherited Not observed in external calls Consider removing from explicit allow-list

Caveats

  • Only 2 runs are available in the 7-day window; the baseline (dispatch) and the high-AIC run (schedule) may not cover edge cases where the latest comic is relevant (which would skip the curated list and should be fast).
  • The "max 3 attempts" guard in the current prompt has not been hit in available data — the high-AIC run did not exceed 3 external comic fetches, but used many internal reasoning turns before fetching.
  • Recommendation 1 assumes the curated list and rotation formula are stable. If the list changes frequently, the setup step will need to be kept in sync.
  • The -L flag fix (Rec 2) is low-risk and should be applied regardless of Rec 1.

Generated by Agentic Workflow AIC Usage Optimizer · 1K AIC · ⊞ 21.6K ·

  • expires on Jun 25, 2026, 3:49 PM UTC

Metadata

Metadata

Assignees

No one assigned

    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