# Cost Accounting & Observability **Status:** proposal **Owner:** agent-go **Updated:** 2025-09-23 ## Summary - Introduce a `Currency` type alias with constants (default `CurrencyUSD`) for cost reporting. - Expose `StepResult.Cost(currency)` and `TokensCached()` for per-turn budgeting insight. - Track cumulative cost and cached tokens across the engine run. - Emit observer events carrying session metrics (token deltas, cache hits). - Update documentation/examples to show cost logging and metric hooks. ## Scope **Affects:** `core/loop`, `core/budget`, observer infrastructure, docs/examples. **Non-Goals:** Dynamic pricing source changes, cross-currency conversions beyond constants. ## Motivation - Current loop provides usage data but lacks consistent cost accounting. - Cached tokens reduce spend but are not surfaced; budgeting requires manual bookkeeping. - Observer hooks need to emit meaningful metrics for monitoring. ## Success Criteria - `Currency` alias and constants defined; cost defaults to USD when unspecified. - `StepResult.Cost(CurrencyUSD)` returns per-step totals; engine exposes cumulative totals. - `StepResult.TokensCached()` available and aggregated. - Observer API emits metric events with token/cost deltas. - Examples/logging updated to show cost + cached tokens per turn. ## Workstreams & Tasks ### WS-A: Currency & Cost Plumbing - **A1.** Define `type Currency string` and constants (USD initial). - **A2.** Implement `StepResult.Cost(unit Currency)` with default fallback. - **A3.** Track cumulative cost via engine state. ### WS-B: Cached Token Metrics - **B1.** Record per-step cached token counts. - **B2.** Aggregate totals for post-run inspection. - **B3.** Integrate with session context size caching. ### WS-C: Observer Integration - **C1.** Extend observer events with cost/token metrics. - **C2.** Provide optional `WithObserver` hook to receive metrics. - **C3.** Ensure metrics emission is zero-cost when observers disabled. ### WS-D: Docs & Examples - **D1.** Update example loop logging cost/cache output. - **D2.** Document usage in `docs/loop.md`. - **D3.** Highlight currency constants in README. ### WS-E: Validation - **E1.** Unit tests for cost calculations and cumulative aggregation. - **E2.** Benchmarks verifying minimal overhead for metrics. - **E3.** Integration tests ensuring observer events fire as expected. ## Risks & Mitigations - **Incorrect Cost Calculations:** Use pricing tables + tests to validate results. - **Observer Overhead:** Guard metrics emission when observers unset. - **Currency Drift:** Keep alias simple; extend only when needed. ## Timeline - **Phase 1:** Currency alias and cost plumbing (WS-A). - **Phase 2:** Cached token metrics + observer integration (WS-B/C). - **Phase 3:** Docs/tests/benchmarks (WS-D/E). ## Dependencies - Pricing data used by budget tracker (static tables). - Observer infrastructure available in `core/observe` (if reused). ## Acceptance & Exit - Cost/cached token metrics implemented and tested. - Observer events documented and working. - Examples/logs show cost usage. - No significant performance regression. ## Example Usage ```go step, _ := engine.Step(ctx) usage := step.Usage() log.Printf("prompt=%d completion=%d cached=%d cost=%.4f %s", usage.PromptTokens, usage.CompletionTokens, step.TokensCached(), step.Cost(loop.CurrencyUSD), loop.CurrencyUSD, ) if obs := engine.Observer(); obs != nil { obs.Emit(loop.EventMetrics{TokensCached: step.TokensCached()}) } ``` ## Progress Log ### 2025-09-23 - proposal - **Completed:** Captured cost/metrics plan. - **In Progress:** Awaiting alignment with loop engine changes. - **Blockers:** None. - **Discoveries:** Currency alias keeps API simple; observer integration essential for monitoring. - **Next Steps:** Implement currency plumbing and cached token metrics.