# Every task my fleet completes now carries its cost

Source: https://www.andrewzigler.com/feed/every-task-my-fleet-completes-now-carries-its-cost
Published: 2026-08-22

import BeadGraph from '@components/BeadGraph';
import SeatSpend from '@components/SeatSpend';
import TapSpend from '@components/TapSpend';

export const beads = [
  {
    "id": "dotfiles-9kq2",
    "type": "research",
    "status": "closed",
    "priority": 1,
    "created": "2026-07-28",
    "closed": "2026-08-02",
    "closed_by": "my research desk",
    "title": "Can a local model hold a real coding session",
    "summary": "Four candidate local models against week-old bug beads from the actual backlog, scored on whether the fix landed, not on a benchmark.",
    "close_reason": "Two of four viable; one pinned as the fallback.",
    "deps": [],
    "requests": 412,
    "tokens": 486000,
    "dollars": 61.8
  },
  {
    "id": "dotfiles-w4nx",
    "type": "research",
    "status": "closed",
    "priority": 2,
    "created": "2026-07-28",
    "closed": "2026-07-31",
    "closed_by": "my research desk",
    "title": "How the fleet actually fails today",
    "summary": "A fault taxonomy pulled from the request log: what the errors were, when they clustered, and which seats were mid-session when they hit.",
    "close_reason": "Taxonomy fed straight into the spec.",
    "deps": [],
    "requests": 168,
    "tokens": 174000,
    "dollars": 18.4
  },
  {
    "id": "dotfiles-3tzp",
    "type": "spec",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-01",
    "closed": "2026-08-05",
    "closed_by": "the infrastructure-operations seat",
    "title": "Brownout policy: what degrades, what stops",
    "summary": "The rules table. Every class of work gets one of three verdicts when the primary is unavailable: degrade, queue, or stop and say so.",
    "close_reason": "Approved after the policy-table review.",
    "deps": [
      "dotfiles-9kq2",
      "dotfiles-w4nx"
    ],
    "requests": 301,
    "tokens": 352000,
    "dollars": 47.1
  },
  {
    "id": "dotfiles-qm71",
    "type": "decision",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-04",
    "closed": "2026-08-05",
    "closed_by": "the infrastructure-operations seat",
    "title": "Seats are demotable by work class, not by name",
    "summary": "Eligibility keys off what the launch is doing, so a new seat inherits the right behavior without being added to a list.",
    "close_reason": "Recorded; the alternative list-based design was rejected.",
    "deps": [
      "dotfiles-3tzp"
    ],
    "requests": 64,
    "tokens": 61000,
    "dollars": 7.85
  },
  {
    "id": "dotfiles-h5vd",
    "type": "decision",
    "status": "closed",
    "priority": 2,
    "created": "2026-08-04",
    "closed": "2026-08-04",
    "closed_by": "the front-desk seat",
    "title": "Failover is opt-in per launch, never fleet-wide",
    "summary": "No global switch. A launch that hasn't declared its tolerance gets the old behavior, which is to fail loudly.",
    "close_reason": "Ruled in-session; matches the sentinel philosophy.",
    "deps": [
      "dotfiles-3tzp"
    ],
    "requests": 38,
    "tokens": 33000,
    "dollars": 4.2
  },
  {
    "id": "dotfiles-2f9c",
    "type": "feature",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-05",
    "closed": "2026-08-10",
    "closed_by": "the infrastructure-operations seat",
    "title": "Gateway route: secondary backend behind a health probe",
    "summary": "One route, two backends, a probe that decides which is live. The client never learns which one served it.",
    "close_reason": "Merged; fault-injection suite green.",
    "deps": [
      "dotfiles-3tzp",
      "dotfiles-qm71"
    ],
    "requests": 356,
    "tokens": 402000,
    "dollars": 44.6
  },
  {
    "id": "dotfiles-8bra",
    "type": "feature",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-05",
    "closed": "2026-08-09",
    "closed_by": "the seat that tends the fleet's own tooling",
    "title": "Launcher advertises its degradation tolerance",
    "summary": "One more header on every launch, carrying the work class the policy table reads.",
    "close_reason": "Rolled out across all launcher scripts.",
    "deps": [
      "dotfiles-qm71",
      "dotfiles-h5vd"
    ],
    "requests": 214,
    "tokens": 231000,
    "dollars": 28.6
  },
  {
    "id": "dotfiles-vx03",
    "type": "feature",
    "status": "closed",
    "priority": 2,
    "created": "2026-08-07",
    "closed": "2026-08-11",
    "closed_by": "the seat that tends the fleet's own tooling",
    "title": "The meter reads the fallback the same as the primary",
    "summary": "Degraded traffic lands in the same ledger with the same columns, so a week that failed over is still one comparable week.",
    "close_reason": "Verified against a forced-failover window.",
    "deps": [
      "dotfiles-2f9c"
    ],
    "requests": 189,
    "tokens": 198000,
    "dollars": 24.1
  },
  {
    "id": "dotfiles-j7ln",
    "type": "feature",
    "status": "closed",
    "priority": 2,
    "created": "2026-08-06",
    "closed": "2026-08-10",
    "closed_by": "the infrastructure-operations seat",
    "title": "Local box: pinned model and a warm start",
    "summary": "The fallback is useless if it takes ninety seconds to answer the first call, so the model stays resident.",
    "close_reason": "First-token latency inside the probe budget.",
    "deps": [
      "dotfiles-3tzp"
    ],
    "requests": 172,
    "tokens": 205000,
    "dollars": 22.8
  },
  {
    "id": "dotfiles-r6ke",
    "type": "task",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-08",
    "closed": "2026-08-12",
    "closed_by": "the overnight-drain seat",
    "title": "Fault-injection harness: kill the primary on purpose",
    "summary": "A switch that makes the primary return the three failures the taxonomy said were real, on demand.",
    "close_reason": "All three faults reproducible.",
    "deps": [
      "dotfiles-2f9c"
    ],
    "requests": 231,
    "tokens": 249000,
    "dollars": 26.4
  },
  {
    "id": "dotfiles-pd48",
    "type": "task",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-09",
    "closed": "2026-08-13",
    "closed_by": "the overnight-drain seat",
    "title": "Tests: every work class against every fault",
    "summary": "The policy table as an executable matrix, so a future edit to it cannot quietly change behavior.",
    "close_reason": "Matrix green; two spec ambiguities found and fixed.",
    "deps": [
      "dotfiles-r6ke",
      "dotfiles-8bra"
    ],
    "requests": 198,
    "tokens": 214000,
    "dollars": 19.7
  },
  {
    "id": "dotfiles-c1wy",
    "type": "task",
    "status": "closed",
    "priority": 2,
    "created": "2026-08-10",
    "closed": "2026-08-12",
    "closed_by": "the overnight-drain seat",
    "title": "Tests: a retried call is not billed twice",
    "summary": "Failover means a call can appear once on each backend. The ledger has to count the work, not the attempts.",
    "close_reason": "Regression test added at the ledger boundary.",
    "deps": [
      "dotfiles-r6ke",
      "dotfiles-vx03"
    ],
    "requests": 96,
    "tokens": 88000,
    "dollars": 8.15
  },
  {
    "id": "dotfiles-t0mz",
    "type": "bug",
    "status": "closed",
    "priority": 0,
    "created": "2026-08-11",
    "closed": "2026-08-15",
    "closed_by": "the infrastructure-operations seat",
    "title": "Failover threw away the prompt cache and the bill tripled",
    "summary": "Every failover started a cold context on the other backend. The work still finished; it cost about three times as much per token while it did.",
    "close_reason": "Cache affinity added; degraded-mode cost now within 20% of normal.",
    "deps": [
      "dotfiles-2f9c",
      "dotfiles-j7ln"
    ],
    "requests": 344,
    "tokens": 371000,
    "dollars": 53.9
  },
  {
    "id": "dotfiles-k9sf",
    "type": "bug",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-11",
    "closed": "2026-08-13",
    "closed_by": "the infrastructure-operations seat",
    "title": "Health probe flapped and ping-ponged mid-session",
    "summary": "A primary recovering under load crossed the threshold repeatedly and dragged sessions back and forth.",
    "close_reason": "Hysteresis plus a minimum dwell time.",
    "deps": [
      "dotfiles-2f9c"
    ],
    "requests": 121,
    "tokens": 128000,
    "dollars": 13.9
  },
  {
    "id": "dotfiles-y2hb",
    "type": "bug",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-16",
    "closed": "2026-08-17",
    "closed_by": "the adversarial-review seat",
    "title": "A degraded session reported success it hadn't earned",
    "summary": "Found in review, not in testing: the fallback finished the loop and closed the bead without noting it had run degraded.",
    "close_reason": "Degraded runs now stamp the close reason.",
    "deps": [
      "dotfiles-b5jt"
    ],
    "requests": 87,
    "tokens": 79000,
    "dollars": 9.4
  },
  {
    "id": "dotfiles-n83q",
    "type": "review",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-13",
    "closed": "2026-08-14",
    "closed_by": "the adversarial-review seat",
    "title": "Adversarial pass on the policy table",
    "summary": "Read the rules table looking for a work class that falls through it. Found one.",
    "close_reason": "Default verdict added for unclassified work.",
    "deps": [
      "dotfiles-pd48",
      "dotfiles-qm71"
    ],
    "requests": 92,
    "tokens": 84000,
    "dollars": 10.2
  },
  {
    "id": "dotfiles-b5jt",
    "type": "review",
    "status": "closed",
    "priority": 0,
    "created": "2026-08-14",
    "closed": "2026-08-16",
    "closed_by": "the adversarial-review seat",
    "title": "Adversarial pass on the failover path",
    "summary": "The merge gate. Everything downstream of the route, the probe, and the ledger had to survive this read.",
    "close_reason": "One real defect surfaced and filed; rest held.",
    "deps": [
      "dotfiles-t0mz",
      "dotfiles-k9sf",
      "dotfiles-c1wy"
    ],
    "requests": 108,
    "tokens": 101000,
    "dollars": 11.75
  },
  {
    "id": "dotfiles-x4rp",
    "type": "review",
    "status": "closed",
    "priority": 2,
    "created": "2026-08-17",
    "closed": "2026-08-17",
    "closed_by": "the adversarial-review seat",
    "title": "Cold read of the runbook",
    "summary": "A context with no history of the epic tried to follow the runbook and said where it stalled.",
    "close_reason": "Two steps rewritten for a reader with no context.",
    "deps": [
      "dotfiles-g7vu"
    ],
    "requests": 44,
    "tokens": 38000,
    "dollars": 4.05
  },
  {
    "id": "dotfiles-m2ed",
    "type": "task",
    "status": "closed",
    "priority": 2,
    "created": "2026-08-12",
    "closed": "2026-08-15",
    "closed_by": "the seat that tends the fleet's own tooling",
    "title": "Mark degraded rows so cost comparisons stay honest",
    "summary": "A column on the row, so a cheap week and a degraded week are never averaged together by accident.",
    "close_reason": "Column live; backfilled for the test window.",
    "deps": [
      "dotfiles-vx03",
      "dotfiles-t0mz"
    ],
    "requests": 83,
    "tokens": 91000,
    "dollars": 9.6
  },
  {
    "id": "dotfiles-g7vu",
    "type": "task",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-15",
    "closed": "2026-08-17",
    "closed_by": "the front-desk seat",
    "title": "Runbook: what a human does when brownout fires",
    "summary": "Short, and written for the version of me who is not awake.",
    "close_reason": "Passed the cold read after two edits.",
    "deps": [
      "dotfiles-h5vd",
      "dotfiles-b5jt"
    ],
    "requests": 71,
    "tokens": 66000,
    "dollars": 6.3
  },
  {
    "id": "dotfiles-f0ai",
    "type": "decision",
    "status": "closed",
    "priority": 1,
    "created": "2026-08-16",
    "closed": "2026-08-16",
    "closed_by": "the front-desk seat",
    "title": "Ship without the queue-and-resume half",
    "summary": "Queueing stopped work is a second feature. Degrade and stop are enough to be useful now.",
    "close_reason": "Scoped out; filed as its own epic.",
    "deps": [
      "dotfiles-n83q",
      "dotfiles-b5jt"
    ],
    "requests": 27,
    "tokens": 24000,
    "dollars": 2.85
  },
  {
    "id": "dotfiles-s6ow",
    "type": "task",
    "status": "open",
    "priority": 3,
    "created": "2026-08-16",
    "title": "Retire the retry loop this replaced",
    "summary": "The old client-side retry is dead code now, and dead code in a failure path is worse than most dead code.",
    "deps": [
      "dotfiles-b5jt"
    ],
    "requests": 39,
    "tokens": 34000,
    "dollars": 3.1
  },
  {
    "id": "dotfiles-lq5v",
    "type": "task",
    "status": "in_progress",
    "priority": 2,
    "created": "2026-08-17",
    "title": "Write up what the failover cost",
    "summary": "The draft this dataset is for, which is also the cheapest way I have found to check whether I understood my own work.",
    "deps": [
      "dotfiles-f0ai",
      "dotfiles-x4rp"
    ],
    "requests": 118,
    "tokens": 129000,
    "dollars": 14.3
  },
  {
    "id": "dotfiles-brnt.0",
    "type": "task",
    "status": "closed",
    "priority": 2,
    "created": "2026-07-28",
    "closed": "2026-08-18",
    "closed_by": "the seat that tends the fleet's own tooling",
    "title": "Coordination: the orchestrator sessions that spanned beads",
    "summary": "Dispatch, merges, and the sessions that touched several beads at once. Charged here on purpose rather than smeared across whichever bead was nearby.",
    "close_reason": "Closed with the epic; the honest overhead line.",
    "deps": [],
    "requests": 287,
    "tokens": 312000,
    "dollars": 38.9
  }
];

export const seats = [
  {
    "id": "tooling",
    "label": "fleet tooling",
    "name": "the seat that tends the fleet's own tooling",
    "note": "The harness working on the harness: hooks, launchers, schedulers. The fleet's largest appetite is itself.",
    "fleet": {
      "tokens": 28400000,
      "requests": 34100,
      "dollars": 2940.0
    },
    "epic": {
      "tokens": 832000,
      "requests": 773,
      "dollars": 101.2
    }
  },
  {
    "id": "infra",
    "label": "infra ops",
    "name": "the infrastructure-operations seat",
    "note": "Machines, routes, deploys. It owns the gateway, so it owned most of this.",
    "fleet": {
      "tokens": 19600000,
      "requests": 22800,
      "dollars": 2180.0
    },
    "epic": {
      "tokens": 1519000,
      "requests": 1358,
      "dollars": 190.15
    }
  },
  {
    "id": "research",
    "label": "research desk",
    "name": "my research desk",
    "note": "Reads and benchmarks. Two beads here decided what the other twenty-three were building on.",
    "fleet": {
      "tokens": 9850000,
      "requests": 11900,
      "dollars": 965.0
    },
    "epic": {
      "tokens": 660000,
      "requests": 580,
      "dollars": 80.2
    }
  },
  {
    "id": "drain",
    "label": "overnight",
    "name": "the overnight-drain seat",
    "note": "Claims approved work while nobody is watching. It wrote the tests and the fault harness.",
    "fleet": {
      "tokens": 7420000,
      "requests": 8600,
      "dollars": 742.0
    },
    "epic": {
      "tokens": 585000,
      "requests": 564,
      "dollars": 57.35
    }
  },
  {
    "id": "desk",
    "label": "front desk",
    "name": "the front-desk seat",
    "note": "The single ingress. Its whole contribution here was two decisions and a runbook.",
    "fleet": {
      "tokens": 6340000,
      "requests": 7900,
      "dollars": 733.0
    },
    "epic": {
      "tokens": 123000,
      "requests": 136,
      "dollars": 13.35
    }
  },
  {
    "id": "critic",
    "label": "review",
    "name": "the adversarial-review seat",
    "note": "Read-only. It cannot write code, which is the point.",
    "fleet": {
      "tokens": 4180000,
      "requests": 5300,
      "dollars": 468.0
    },
    "epic": {
      "tokens": 302000,
      "requests": 331,
      "dollars": 35.4
    }
  },
  {
    "id": "ambassador",
    "label": "ambassador",
    "name": "this ambassador seat",
    "note": "The only one aimed outward. It writes the posts about what the others did.",
    "fleet": {
      "tokens": 2910000,
      "requests": 3400,
      "dollars": 301.0
    },
    "epic": {
      "tokens": 129000,
      "requests": 118,
      "dollars": 14.3
    }
  },
  {
    "id": "tail",
    "label": "everything else",
    "name": "the long tail — six smaller seats",
    "note": "Six named seats with their own jobs, none of which this epic ever touched.",
    "fleet": {
      "tokens": 9300000,
      "requests": 12000,
      "dollars": 571.0
    },
    "epic": {
      "tokens": 0,
      "requests": 0,
      "dollars": 0
    }
  }
];

export const taps = [
  {
    "id": "primary",
    "label": "primary plan",
    "note": "The subscription most seats launch against. It ran out on Thursday.",
    "window": {
      "dollars": 1658.66
    },
    "segments": {
      "seat": [
        {
          "id": "tooling",
          "label": "fleet tooling",
          "dollars": 596.17
        },
        {
          "id": "infra",
          "label": "infra ops",
          "dollars": 388.94
        },
        {
          "id": "research",
          "label": "research desk",
          "dollars": 246.83
        },
        {
          "id": "drain",
          "label": "overnight",
          "dollars": 177.68
        },
        {
          "id": "desk",
          "label": "front desk",
          "dollars": 109.14
        },
        {
          "id": "critic",
          "label": "review",
          "dollars": 87.64
        },
        {
          "id": "ambassador",
          "label": "ambassador",
          "dollars": 45.02
        },
        {
          "id": "none",
          "label": "unattributed",
          "dollars": 7.24
        }
      ],
      "bead": [
        {
          "id": "dotfiles-p2xk",
          "label": "harness: hook refactor",
          "dollars": 355.37
        },
        {
          "id": "dotfiles-v8qd",
          "label": "harness: scheduler rewrite",
          "dollars": 245.82
        },
        {
          "id": "dotfiles-t0mz",
          "label": "the cache bug",
          "dollars": 190.15
        },
        {
          "id": "dotfiles-pd48",
          "label": "the policy matrix tests",
          "dollars": 135.07
        },
        {
          "id": "dotfiles-lq5v",
          "label": "the write-up",
          "dollars": 57.49
        },
        {
          "id": "dotfiles-k9sf",
          "label": "the flapping probe",
          "dollars": 49.85
        },
        {
          "id": "dotfiles-m2ed",
          "label": "the degraded-row column",
          "dollars": 38.59
        },
        {
          "id": "dotfiles-y2hb",
          "label": "the unearned success",
          "dollars": 37.79
        },
        {
          "id": "dotfiles-b5jt",
          "label": "the merge gate",
          "dollars": 35.98
        },
        {
          "id": "dotfiles-g7vu",
          "label": "the runbook",
          "dollars": 25.33
        },
        {
          "id": "none",
          "label": "no bead named",
          "dollars": 487.22
        }
      ]
    }
  },
  {
    "id": "secondary",
    "label": "secondary plan",
    "note": "The overflow. Quiet until the primary went dry, then it carried the week.",
    "window": {
      "dollars": 516.36
    },
    "segments": {
      "seat": [
        {
          "id": "infra",
          "label": "infra ops",
          "dollars": 236.78
        },
        {
          "id": "tooling",
          "label": "fleet tooling",
          "dollars": 137.28
        },
        {
          "id": "drain",
          "label": "overnight",
          "dollars": 78.79
        },
        {
          "id": "research",
          "label": "research desk",
          "dollars": 37.79
        },
        {
          "id": "critic",
          "label": "review",
          "dollars": 20.9
        },
        {
          "id": "none",
          "label": "unattributed",
          "dollars": 4.82
        }
      ],
      "bead": [
        {
          "id": "dotfiles-t0mz",
          "label": "the cache bug",
          "dollars": 167.23
        },
        {
          "id": "dotfiles-p2xk",
          "label": "harness: hook refactor",
          "dollars": 89.85
        },
        {
          "id": "dotfiles-pd48",
          "label": "the policy matrix tests",
          "dollars": 73.16
        },
        {
          "id": "dotfiles-lq5v",
          "label": "the write-up",
          "dollars": 24.52
        },
        {
          "id": "none",
          "label": "no bead named",
          "dollars": 161.6
        }
      ]
    }
  },
  {
    "id": "work",
    "label": "work account",
    "note": "Employer-funded, and only the seats doing employer work may touch it.",
    "window": {
      "dollars": 791.14
    },
    "segments": {
      "seat": [
        {
          "id": "infra",
          "label": "infra ops",
          "dollars": 291.05
        },
        {
          "id": "tooling",
          "label": "fleet tooling",
          "dollars": 222.31
        },
        {
          "id": "desk",
          "label": "front desk",
          "dollars": 133.06
        },
        {
          "id": "critic",
          "label": "review",
          "dollars": 86.43
        },
        {
          "id": "research",
          "label": "research desk",
          "dollars": 50.65
        },
        {
          "id": "none",
          "label": "unattributed",
          "dollars": 7.64
        }
      ],
      "bead": [
        {
          "id": "job-r4c1",
          "label": "day job: pipeline triage",
          "dollars": 258.08
        },
        {
          "id": "job-m9dt",
          "label": "day job: dashboard fix",
          "dollars": 195.17
        },
        {
          "id": "job-q2wl",
          "label": "day job: data backfill",
          "dollars": 121.0
        },
        {
          "id": "none",
          "label": "no bead named",
          "dollars": 216.89
        }
      ]
    }
  }
];

In late July I want to experiment with some open models on a spare Mac Studio in my house (a symptom of the times, I know), to see what they could achieve alongside my foundation model usage.

By the end, I knew what the experiment had burned in tokens. After all, every model call from every agent I run crosses a single [agentgateway](https://agentgateway.dev) process on its way to the API, so the token count was never in doubt. But what the count couldn't tell me was what the tokens had *accomplished*.

- Which task was the expensive one?
- Did that bug cost more than the feature that shipped it?

Tokens are a fact about my usage; what they bought is a fact about my work, and the two live in different systems on my machines. So I set out to join them in one view.

## The token count answers a question I stopped needing to ask

The cost conversation still runs on volume. The vernacular has split into tokenmaxxers, and even tokenminmaxers now, arguing about which direction the token spend should go: up or down.

Luis Morales, Head of AI at Super.com, gave me a shape for why that stalls. In ["We Stopped Counting Tokens"](https://www.linkedin.com/pulse/we-stopped-counting-tokens-luis-morales-swfre/) he lays measurement out as a ladder, utilization then output then outcome, and puts an expiry date on each rung:

> Utilization metrics are the first rung of the ladder. You need them early. Then you need to outgrow them fast.

His test for an expired metric landed hard here: "A question that always returns the same answer has retired itself." Am I using tokens? Yes. Tomorrow: yes. I kept asking it because it was the question my tooling could answer.

## The spenders and the work already had names

I borrowed both halves from Steve Yegge, who has been writing about what it is like to run a crew of agents day to day. In ["Model Welfare for Agentic Engineers"](https://yegge.ai/essays/model-welfare/) he portrays what I do, as well:

> Sessions are days, and seats are people.

A seat, on my machines, is a session I keep handing the same name and the same memory file, pointed at the same kind of work.

The work has names too. Every unit of it is a bead, a small linkable record in an agent-native issue tracker. The concept is Yegge's ([Beads](https://github.com/gastownhall/beads)); the engine I run is [beads_rust](https://github.com/Dicklesworthstone/beads_rust), a fast Rust port from Jeffrey Emmanuel. A seat claims a bead, works it, closes it with a reason, and the beads link into a graph that remembers what the fleet did.

So I already had two graphs, one of identity and one of work, with the gateway's receipts sitting between them.

## Cost breakdown for an actual epic in beads

Here's that actual experiment, broken down by bead and cost. The goal was to find out whether a local model can hold a real coding session, write the rules for what degrades and what stops, wire the second backend, and learn what a failover does to the bill:

<BeadGraph beads={beads} />

Each node is one task with its own record:

- who claimed it
- why it closed
- what it depended on

The epic is the parent; research, specs, decisions, features, bugs, and reviews hang under it, each carrying its own work and its own review, the way any epic you have ever scoped does.

## The gateway stamps every request with a seat and a task

Each seat's launcher stamps two identity headers on its traffic, and the gateway lifts them into columns on its request log with one line of CEL apiece:

```yaml
standardAttributes:
  user:  'default(request.headers["x-session-identity"], "")'
  group: 'default(request.headers["x-billing-origin"], "")'
```

CEL is Common Expression Language, a small rule language proxies use for jobs exactly this size; the line reads as *take this header, or fall back to an empty string*. Anything that cannot identify itself lands in one bucket of unknown spenders. When I started, that bucket collected 1000+ requests a week. Last week it collected only 15 unidentified sessions. Effectively all the inference is identified and labeled now, letting me do some pretty interesting observations on what the seats accomplish day to day.

The second header names the task, which is a node in a graph of tasks. The value of pivoting on this graph cannot be understated: the entire graph of planned and finished work can be pinned to each inference call, at whatever stage is the focus of the task. This allows me to not only understand what tasks cost, but also which specific parts of the task were expensive. Then you start to learn things, like failure modes you'd otherwise miss, or the model doing something that should be hardened in a script.

For each subagent, the Claude process has the ID of the bead it is working in its exports, so the header rides every call that session makes, and the gateway writes it onto the row next to the dollars it derives from token usage. On a subscription those dollars are list-rate equivalents, which is great, it shows how much value I get from my flat subscription each week (I wouldn't be able to afford this on API costs, I'll just say that).

## Each bead comes back wearing its cost

<BeadGraph beads={beads} showCosts />

The same graph, with the dollars written on. Reading it takes no spreadsheet:

- Each task's number is its own spend, the calls made under that task and nothing else.
- The epic's figure is the plain total of the tasks underneath it.
- Coordination, the sessions that dispatch and merge everything else, carries its own line instead of being smeared across the work it touched.

The most expensive task in the experiment wrote no code at all: the research that benchmarked local models against real bugs from my own backlog, at $61.80, and it decided what everything else was built on.

## Seat totals show where the three weeks went

<SeatSpend seats={seats} view="fleet" windowLabel="21 days" />

Zoom out and the ranking is predictable, at least for an AI explorer who is constantly refining his own harness. The seat that tends the fleet's tooling leads, infrastructure follows, and the whole fallback epic is a thin sliver inside each box. My invoice already knew this much. It is where I used to stop, because it was as far as my numbers went.

## Filter to one epic and the leaderboard flips

<SeatSpend seats={seats} view="epic" windowLabel="21 days" epicLabel="Fallback" />

Filter the same seats down to the fallback work alone and the ranking inverts:

- The infrastructure seat jumps to 1st, which is what owning the gateway route costs.
- The fleet's biggest spender drops to 2nd, and more than a third of what it spent here was coordination rather than code.

My front desk turns out to be the epic's cheapest line: two decisions and a runbook on the process. The read-only critic bought the merge gate.

This is still an early experiment, and I only run one machine on this practice. But it opens an opportunity for you, as the harness operator, to ask higher-order questions about the efficiency of the system, because the entire thing is a feedback loop. Any session can connect work to tasks to inference to the seat responsible for owning it, and reason and act on it. Some of these questions for me have been:

- Is my research desk cheap because it is efficient, or because I under-use it?
- Why is the seat that makes my decisions the cheapest line on the graph?
- What opportunity am I missing?
- What is taking up most of my time and tokens?
- Of what I completed, what had the biggest impact?

I can picture these numbers across a whole engineering org, but I haven't gotten there yet.

## The taps are the layer I actually pay

Steve Yegge named this layer too. His fleet drinks from what he calls a [token tap](https://yegge.ai/essays/the-shape-of-things-to-come/), a pool of flat-rate subscription accounts his agents rotate through instead of metered API billing, and he runs a dozen of them.

I only have 3. (😇)

Since all of the inference is labelled even by tap in the gateway, I can segment any given week to find how much of each tap was consumed by which seat:

<TapSpend taps={taps} view="seat" windowLabel="7 days" />

I can split that same tap across beads as well to find which bead epics took up my time and precious tokens that week:

<TapSpend taps={taps} view="bead" windowLabel="7 days" />

## Put a cost on a unit of your own work

If you're a software leader right now trying to map inference to outcomes, you really need a context layer to capture this same level of insight but across all of your engineers.

What surprised me is how loose the unit of work can be when you attribute cost to a bead. Our industry tends to ask for *cost per PR*, but my agents spend most of their time doing work that doesn't end up as a PR. That didn't stop me from trying to valuate it, however.

I found that attributing the cost to a bead, a unit of work that can be defined as truly *anything*, is the right tempo of scale to match the inference pattern used by models.

And even better: a PR can neatly contain a record of all the beads that produced it, thus earning the *cost per PR* by adding the cumulative work inside it. Because you're tracking at the inference level, you're getting a much more accurate sense of cost anyways, compared to the PR which is only going to capture costs associated with tasks around code gen.

I had my infra agent cut up some examples for you to study below, if you want to try running this experiment yourself. Be sure to try out [agentgateway](https://agentgateway.dev) and [beads_rust](https://github.com/Dicklesworthstone/beads_rust) regardless. I also wrote a tutorial on [how to stand a gateway like this up](https://www.andrewzigler.com/feed/if-you-give-a-goose-an-mcp-server) that's a good place to start after learning the tools.

gl;hf! 😎

---

## Appendix: the pieces worth copying

**1: lift two headers into columns.** `standardAttributes` is read at startup only, so this is a restart, not a hot reload. Validate first, and watch the validator reject a deliberately broken control before you trust it.

```yaml
config:
  database:
    url: "sqlite:///var/lib/agentgateway/requests.db?mode=rwc"
  standardAttributes:
    user:  'default(request.headers["x-session-identity"], "")'
    group: 'default(request.headers["x-billing-origin"], "")'
```

```sh
agentgateway --validate-only -f config.yaml   # non-zero exit names the bad field
```

**2: the sanitizer that makes the unknown-spender bucket structural.** The filter cannot emit `?`, which frees `?` to mean "nothing was derived here" and nothing else.

```sh
sanitize() { printf '%s' "${1:-}" | tr -s '[:space:]' '-' | tr -cd '[:alnum:]._-'; }

seat=$(sanitize "${MY_SEAT_NAME:-}")
export SEAT_ADDRESS="${seat:-?}"      # a real name can never contain '?'
```

**3: group by seat, last 7 days.** Read a snapshot, never the file the gateway is writing.

```sh
sqlite3 requests.db "VACUUM INTO '/tmp/snap.db'"
```

```sql
-- datetime() is load-bearing: started_at is ISO8601 with a 'T', and a bare
-- string compare matches every row with today's date without erroring.
SELECT agentgateway_user               AS seat,
       count(*)                        AS requests,
       sum(coalesce(total_tokens, 0))  AS tokens
FROM request_logs
WHERE datetime(started_at) >= datetime('now', '-7 days')
GROUP BY seat
ORDER BY tokens DESC;
```

**4: the bead join.** The identity schema is closed at two columns, so the per-task header rides the access log's attribute JSON, which is the path that hot-reloads. The sentinel lives in the config, not the client: a launch that never heard of beads still lands as `none`, honestly.

```yaml
frontendPolicies:
  accessLog:
    database:
      add:
        bead_id: 'default(request.headers["x-bead"], "none")'
```

```sql
-- per-task spend, sentinel excluded; keep the extraction parenthesized
SELECT (attributes_json ->> '$.bead_id') AS bead,
       count(*)                          AS requests,
       round(sum(cost), 2)               AS dollars
FROM request_logs
WHERE (attributes_json ->> '$.bead_id') IS NOT NULL
  AND (attributes_json ->> '$.bead_id') != 'none'
GROUP BY bead
ORDER BY dollars DESC;
```

---

*Andrew Zigler is a 2026 AAIF Ambassador. Find the cohort at [aaif.io/ambassadors](https://aaif.io/ambassadors). I wrote up [how to stand a gateway like this up](https://www.andrewzigler.com/feed/if-you-give-a-goose-an-mcp-server) in July; this piece is what its receipts taught me to ask for.*
