learn-ai-observability-with-phoebe / Leader session 2 of 6
Learn AI Observability with Phoebe · Leader track · Session 2 of 6

What to instrument before you need it: coverage is a decision, not a technical problem

Nobody in your organisation decided not to instrument retrieval. That is exactly the problem. Coverage arrives as a default - you get whatever the vendor SDK happened to wrap, and the parts you get free are the parts least likely to be your bug. This session turns coverage from an accident into a decision with an owner, a cost and a measurable value, so that the next incident is a twenty minute investigation instead of a four day one.

🟢 Leader track Heads of engineering · platform leads · SRE managers 45 min
0-3 · Recap 3-19 · The asymmetry + the 62% 19-34 · Coverage as a measurable property 34-45 · Decisions + Q&A
Part 0

Where session a1 left you, and the single move that follows from it

Session a1 ended with a number: the hours of senior time your last unexplained AI answer consumed. Beacon's was four days, spent proving what was not wrong. Anthropic's postmortem showed the same shape at a company with no resourcing excuse. Today has one job, which is turning "we should see more" into a written list of what specifically, owned by a named person, with the cost stated honestly rather than hidden.

Live - presented in session Self-study - read after class Official sources covered
★ What you walk out with today Why the instrumentation you get for free is the instrumentation you need least, the specific wrong conclusion each missing instrument makes your team reach, one number that reframes the whole conversation (62% of a run's wall clock inside no span at all), a definition of coverage your monitoring can check by itself, and an honest sentence about what coverage costs so nobody feels sold to.
The framing that gets this funded Coverage is not a monitoring line item. It is the difference between an incident that ends in a mechanism and an incident that ends in a hypothesis. The bill for poor coverage is never paid by the observability budget - it is paid in senior engineering weeks, in wrong model migrations, and in the specific credibility cost of telling an executive "we cannot explain what happened".
Part 1 · the asymmetry

You get the model calls free, and the model calls are rarely the bug 9 min live

There is a structural reason your traces look the way they do, and it has nothing to do with your team's judgement. Auto-instrumentation wraps what the vendor ships, and the vendor ships the model client. So the model call is instrumented by default, everywhere, in every stack - and it is the layer that fails least often.

A · What arrives for free

The model calls. Which model, how many tokens, how long it took, what finished it. Genuinely useful, genuinely well covered, and almost never the thing that broke.

B · What needs a decision

Retrieval. Caching. Tool arguments. Retry counts. Swallowed exceptions. Guardrail outcomes. Every one of these is where production actually breaks, and every one requires somebody to choose it.

That is the whole asymmetry, and it explains a pattern you have probably seen without naming: teams with real observability spend on their AI stack, whose first serious incident is still unreadable. They have excellent coverage of the safest layer. Nobody chose that. It was the default, and defaults are decisions that nobody signed.

One 6.8 second run, and the 4.2 seconds nobody could see What the team's traces showed - three spans, and all of them model calls or the root chat 1.1s chat 1.1s 4.6 seconds of real work, inside no span at all What was actually happening - the same 6.8 seconds, fully described chat 1.1s retrieve_metrics 4.2s RETRIEVER chat 1.1s chat 1.1s · tool 0.2s · retrieve_metrics 4.2s · chat 1.1s · un-spanned glue 0.2s = 6.8s total The retrieval span alone is 4.2 seconds of 6.8 = 62% of the wall clock, and it was invisible for a week. Nothing about the system changed when it appeared. Only what the system reported about itself changed. Coverage is the only variable in this picture that a leader controls directly. You cannot triage a step that emits nothing. Uninstrumented time is not slow; it is invisible.
🔍 Click to zoom - the same run, before and after somebody decided retrieval was worth a span
The 62%, and why it is the number to quote In the Beacon run, the retrieval step is 4.2 seconds of a 6.8 second wall clock. That is 62% of everything the user waited for, sitting inside no span the team emitted. Before retrieval was instrumented, only 32.4% of the run was accounted for by any span at all; adding tool spans took that to 38.2%; adding the retrieval span took it to 100% and made a four-second step appear out of nowhere. The system was identical in all three cases. The arithmetic here is computed from the course's trace simulator, which is a constructed incident with real arithmetic - not a capture from a live system.
LiveThe one metric that turns this into a standing question4 min▶

There is a single derived number that makes coverage legible to people who will never open a trace: unaccounted time. Take the total duration of a request, subtract the durations of every span you actually emit, and express the remainder as a percentage.

Unaccounted timeWhat it means operationally
Above 50%Most of what your users wait for is undescribed. Any incident in that region will be diagnosed by reading code, on a deadline, by your most expensive people
20 to 50%You can localise a problem to a region but not to a step. Investigations end in plausible hypotheses rather than mechanisms
Under 10%Duration questions are answerable off the waterfall. Attribute coverage becomes the next constraint, and that is a different decision

Ask for this number once per quarter, per AI feature. It requires no new vocabulary from the person answering, it cannot be gamed without genuinely improving coverage, and it is one of very few observability metrics that a non-engineer can interpret unaided. Session b1 walks the builder track through computing it.

Part 2 · the cost of each gap

What each missing instrument makes your team believe 8 min live

A coverage gap does not present as an absence. It presents as a confident wrong answer, arrived at by competent people reasoning correctly from incomplete evidence. This is the table to bring to a prioritisation meeting, because each row is a specific week your organisation can lose.

Instrument you skipped What you will conclude What is actually true Retrieval span "the model hallucinated" it had no grounding to work from Retry counter "this model call is expensive" you paid for the same call 4 times Cache read/create split "our cost per token is stable" the cost model is off by up to 12.5x Guardrail pass / trip "users only ask easy questions" you quietly refuse 6% of them Swallowed exception "the request succeeded" the fallback served 19.4h-old data The 6% refusal rate is the constructed Beacon case, not a published statistic. The 12.5x is arithmetic on Anthropic's published 1.25x cache-write and 0.1x cache-read multipliers, read 2026-08-13. Every row is a wrong conclusion your team can reach with a completely green dashboard.
🔍 Click to zoom - five coverage gaps, and the confident wrong answer each one produces
LiveRow by row, with the decision each one implies5 min▶
GapThe wrong turn it causesWhat it costs before you notice
No retrieval span"The model hallucinated" - so you change model, or tighten the prompt, or add a guardrail. The model was fine. It had nothing to ground onA model migration. Weeks, plus a confident negative result that means nothing
No retry counter"This model call is expensive" - so the cost conversation becomes a pricing conversation. It was one call, billed four timesA vendor negotiation aimed at the wrong number, while the retry storm continues
No cache read versus create split"Our cost per token is stable" - so nobody looks. A cache write and a cache read are priced very differently, and one number cannot represent bothA cost model wrong by a large multiple, in whichever direction flatters you
No guardrail outcome"Users only ask easy questions" - so the roadmap optimises for the questions you can see. The hard ones were refused, silently, and never reached a logA product strategy built on a survivorship-biased view of demand
No status on a caught exception"The request succeeded" - because it did, from the caller's point of view. The fallback path ran and nobody was toldBeacon. Four days, and a week of executives acting on last Monday's numbers

The 12.5x, stated precisely so nobody over-claims it. Anthropic's published prompt caching multipliers are 1.25x base input cost for a five-minute cache write and 0.1x for a cache read, read 2026-08-13. The ratio between those two token classes is therefore 12.5x. If your telemetry reports one undifferentiated input token count, your per-token cost model can be wrong by that factor for the tokens in question. This is arithmetic on published multipliers, not a published statistic, and it is a leading indicator rather than a bill - session a4 does the full cost attribution and b4 does it per span.

The 6%, stated precisely too. It is the refusal rate in the Beacon teaching case, chosen to be unremarkable. Any real number is your own to measure, and the reason to measure it is that a refusal typically returns as a successful response, so it is invisible to error-rate alerting by construction. Session a5 makes refusal rate a first-class alerting signal.

Elite case · [P] primary

The best-resourced possible team ran green evals and missed a bug affecting 16% of requests at peak. In Anthropic's published postmortem of three issues, September 2025, a context-window routing error affected a peak of 16% of Sonnet 4 requests in the worst hour, and approximately 30% of Claude Code users who made requests in that window had at least one message routed to the wrong server type. The benchmarks, in their words, "simply didn't capture the degradation users were reporting".

Two details make this the most useful case available for a coverage argument:

  • The reason detection failed was partly a virtue. Claude recovers from isolated errors, so an aggregate score over many requests barely moved while individual users were visibly harmed. Resilience suppresses exactly the signal an offline benchmark reads.
  • The remediation went towards production coverage, not smarter offline testing. More sensitive evaluation on real production traffic, and better tooling for engineers to inspect real requests. When the team with the deepest possible eval investment finds a failure class its benchmarks cannot see, it buys coverage on production traffic instead of buying more benchmarks.

Use this in exactly one way and no further: it is evidence that offline testing has a structural blind spot for intermittent, absorbed, route-dependent failures. It is not a benchmark number, not a guarantee about any product, and not a claim about what your own rates will be. The Bedrock and Vertex figures - 0.18% and under 0.0004% at peak - are the reminder that if you multi-home, one platform's telemetry does not represent the others.

Part 3 · coverage as a number

Coverage is a measurable property, not a feeling 8 min live

Everything above is an argument. This is the part that turns it into an operating practice, and it is the most under-used idea in AI observability: write down the list of span types a healthy trace of this feature is supposed to contain, then let your monitoring alert when a trace arrives without one of them.

Declare the expected steps once, and the gap becomes machine-detectable The expected step list A trace that arrived at 09:14 The alert invoke_agent invoke_agent present plan plan present chat chat present execute_tool execute_tool present retrieval retrieval MISSING db.query db.query MISSING cache.get cache.get MISSING COVERAGE INCIDENT 4 of 7 expected span types present. This is a ticket, not a hunch. It fires without anyone reading a trace. No model and no eval can produce this alert. The three missing rows ARE the incident. The list is the decision. Once the expected step list exists, a trace with four spans where the design says seven is a machine-detectable coverage incident - the rare alert that fires before a user is harmed. Coverage stops being a vibe the moment somebody writes the expected step list down.
🔍 Click to zoom - the expected step list, the trace that arrived, and the alert that writes itself
Why this is the highest-leverage ask on the page Every other signal in this course tells you about a request that already went wrong. Instrumentation coverage is the one signal that tells you your ability to diagnose has degraded, before the incident that needs it. It also degrades silently and constantly, for entirely mundane reasons: a dependency upgrade drops an auto-instrumentation hook, a refactor moves a call outside its span, a new code path ships without the wrapper, a sampling change quietly removes a span type from view. None of those produce an error. All of them produce a trace with fewer span types than the design says.
Self-studyHow to write an expected step list that survives contact with reality4 min read▶

The failure mode of this practice is a list so detailed that it is wrong within a fortnight and gets switched off. Four rules keep it alive.

  • List span types, not span counts. An agent loop legitimately runs three tool calls today and eleven tomorrow, so counts flap. "At least one retrieval span" is stable across both. Runaway loops are caught by a different signal, which is a5's subject.
  • One list per feature, not one per service. The expected shape of a document assistant is not the expected shape of a routing classifier. A single global list is either so loose it catches nothing, or so tight it fires constantly.
  • Version the list with the feature. When a step is deliberately removed, the list changes in the same change set. If updating the list is a separate ticket, it will lag, and a lagging list generates false alerts until somebody mutes it permanently.
  • Alert as a rate, not per trace. One trace missing a span type can be legitimate - a cache hit path may genuinely skip the database. A sustained share of traces missing an expected type is the signal. Per-trace alerting on a non-deterministic system is how you build alert fatigue, and a5 is entirely about not doing that.

Written this way, the artifact is short. Seven lines per feature, owned by the team that owns the feature, reviewed when the feature changes. It is the cheapest thing on this page and the only one that catches its own decay.

Part 4 · the honest part

What coverage costs, said out loud 5 min live

A session that only argues for more instrumentation is a sales pitch, and your engineers will hear it as one. Coverage is not free, the costs are real, and naming them is what makes the ask credible.

1 · Storage and ingest

More spans per trace means more bytes retained and, on volume-priced platforms, a larger bill. Content capture is the expensive part by a wide margin, and it is a separate decision from structural coverage.

2 · Engineering time

The spans you get free cost nothing. Retrieval, cache and tool-argument coverage is deliberate work by the team that owns the code, and it competes with the roadmap.

3 · Cardinality

Rich attributes on spans are cheap. The same attributes used as metric dimensions multiply time series and can dominate cost. The two look identical to a stakeholder and are priced very differently.

4 · Privacy exposure

Structural coverage - durations, counts, statuses - carries little risk. Capturing prompts, tool arguments and retrieved documents creates legal and security obligations. Do not bundle the two asks together.

Where the numbers live This session deliberately does not price coverage, because a price without arithmetic in front of it is a slogan. Session b7 prices it - sampling, retention volumes and the cardinality mechanism, with the trade computed rather than asserted. Session a4 handles cost attribution as a business problem, a5 handles what to alert on so extra coverage does not become extra noise, and a6 handles retention, lock-in and the decision about storing prompts. The one thing to carry out of today is the shape of the trade: metadata coverage is cheap and high-value, content capture is expensive and situational, and treating them as one budget line is how good proposals get rejected.
Self-studyThe trap where more coverage buys nothing3 min read▶

The course's own trace simulator makes this point against itself, and it is worth knowing before you approve a budget. Adding coverage improves diagnosis sharply up to a point: structural spans, then attributes, then the database and cache children, then error propagation, then identifiers and token counts. At that point every diagnostic question about the Beacon incident is answerable.

Then there is one more lever available - capturing the full message content of every request - and pulling it moves the diagnosis score by nothing at all, while multiplying retention volume by roughly a factor of ten and flipping a personal-data flag to true. The message content was never the problem. The retention numbers there are modelled rather than measured, and labelled as such in the simulator.

That is the honest shape of the curve: steep, then flat, then actively harmful. A leader's job on this page is not to maximise coverage. It is to get onto the steep part of the curve and to recognise the flat part before somebody buys it. Sessions b5 and b10 walk the builder track through both ends of that curve directly.

Decision exercise 1 of 2

Write the expected step list for one feature, now ★ 8 min · in pairs, on paper

This is the artifact. Eight minutes, one feature, seven lines or fewer. The point is not to get it right; it is to discover how much disagreement exists in the room about what your own system does.

Take the feature you inventoried in a1 and list every step a healthy request passes through, in order, in business language. Not function names - "look up the customer's plan", "search the policy corpus", "call the pricing service", "compose the answer".

Mark each step with whether it can fail independently. If a step can fail on its own and the request can still return something to a user, that step must be able to say so. Those are the ones that matter, and they are usually the ones nobody instrumented.

Now mark which steps you currently believe emit a span. Do not check yet - guess, and record the guess. The gap between the guess and reality is the most informative number this exercise produces, and it is the number worth reporting upward.

Have somebody verify the guess against one real trace before the next session. Two disagreements is normal. Five means the shape of your system in your head is not the shape on disk, and that is worth knowing on a calm Tuesday rather than a bad one.

What to listen for Listen for the moment two people describe the same feature with a different number of steps. That disagreement is not a documentation problem - it is the exact reason coverage drifts, because a step nobody agrees exists is a step nobody owns instrumenting. Resolving it in a meeting is dramatically cheaper than resolving it during an incident.
Decision exercise 2 of 2

Decide who owns coverage, and what happens when it drifts ★ 6 min · decide, do not discuss

Coverage decays by default, for mundane reasons, in every organisation. So the question is not whether it will drift but who finds out and what they are empowered to do. Four decisions, made in the room, written down.

The owner. Does coverage belong to the feature team or to a central platform team? Both work. What does not work is the common third answer, where the platform team owns the tooling and the feature team owns the code and neither owns the gap between them.

The gate. Is a missing expected span type a release blocker, a ticket, or neither? If a new AI code path can ship without appearing in a trace, coverage will decay at exactly the rate you ship, and that rate is your best case.

The budget. Which of the four costs in Part 4 is your actual constraint - storage, engineering time, cardinality, or privacy? Naming the real one prevents the argument where a proposal is rejected on privacy grounds when the objection was really headcount.

The review. When is coverage looked at deliberately, by whom, with what number in front of them? Quarterly, per feature, with unaccounted time and the expected-step-list result is enough. Anything less frequent and the first review will be during an incident.

★ The sentence to leave in the room Nobody in your organisation decided not to instrument retrieval. That is exactly the problem, and it is also the good news: an unmade decision is much cheaper to fix than a wrong one. Coverage becomes a decision the moment one person owns it, one list exists, and one number gets reported.
Homework

Before session a3 - this week ◐ 40-50 min total

Source material

Official sources covered

Every claim on this page is either traceable to a primary source in this course's source map, or explicitly labelled as arithmetic or as a constructed teaching figure. Prices carry the date they were read. This session covers:

✓The auto-instrumentation asymmetry: vendor SDKs wrap the model client, so the model call is the free span and the least likely bugPart 1 · framework reality in b3
✓Anthropic postmortem, Sep 2025 - green benchmarks missed a bug at 16% peak of Sonnet 4 requests; ~30% of Claude Code users affected; remediation was production coveragePart 2 · [P] primary
✓Anthropic prompt caching multipliers: 1.25x five-minute cache write, 0.1x cache read - the 12.5x ratio is arithmetic on those, read 2026-08-13Part 2 · [P] primary · full cost work in a4 and b4
✓Instrumentation coverage as an alertable signal: traces missing an expected span typePart 3 · alerting design in a5 and b8
◐The 62% figure and the 32.4% / 38.2% / 100% coverage ladder - computed from the course simulator, a constructed incident with real arithmeticPart 1 · labelled on the page · b5 is the simulator session
◐The 6% refusal rate - the constructed Beacon case, not a published statisticPart 2 · labelled on the page and in the figure
◐Content capture as the anti-lever: full message content moves diagnosis by nothing and multiplies retention by roughly ten, on modelled volumesPart 4 card · proved in b5, decided in b10
◐The price of coverage: sampling, retention and cardinality arithmeticNot covered by design · session b7 prices it
◐The exact GenAI span and attribute names used in the figuresUsed loosely here · spelled out with requirement levels in b2 · all Development status, no tagged release
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · Your platform team reports excellent trace coverage of every model call in the AI stack. What have they actually told you?

Model call coverage is the one thing nobody has to choose, because auto-instrumentation wraps what the vendor ships. It is genuinely useful and it is the layer that fails least often. Retrieval, caching, tool arguments, retry counts and swallowed exceptions each require somebody to decide they matter - which is why a team can hold real observability spend and still be unable to read its first serious incident.

2 · In the Beacon run, the retrieval step is 4.2 seconds of a 6.8 second wall clock. What changed when a retrieval span was finally emitted?

This is the cleanest illustration of why coverage is a decision rather than a technical problem. The 4.2 seconds were always there and were always the majority of what the user waited for. No code path, no dependency and no configuration changed - the only difference was that somebody decided the step deserved to be described. Uninstrumented time does not look slow. It does not look like anything at all.

3 · A trace arrives with four spans, where your expected step list for that feature says seven. Why is this the highest-value alert on the page?

Every other signal in this course reports on a request that has already gone wrong. Coverage is the one that reports on your capacity to explain the next one, and it decays silently for mundane reasons: a dependency upgrade drops a hook, a refactor moves a call outside its span, a new path ships without the wrapper. B is the trap - a missing span type usually means a missing instrument, not a broken step, and conflating the two produces the wrong ticket. Alert on the rate, not on single traces, or you have built the alert fatigue that session a5 is about avoiding.

Leader session 2 cheat sheet · pin this

The asymmetryYou get the model calls free, because that is what the vendor SDK wraps. The model calls are rarely the bug.
What needs a decisionRetrieval, caching, tool arguments, retry counts, swallowed exceptions, guardrail outcomes. All of it deliberate.
The 62%Retrieval alone is 4.2s of a 6.8s Beacon run. Coverage went 32.4% to 38.2% to 100% with no change to the system.
Unaccounted timeTotal duration minus the sum of emitted spans. One number, no jargon, cannot be gamed without real improvement.
Gaps produce wrong answersNo retrieval span reads as "the model hallucinated". No retry counter reads as "this call is expensive".
Coverage is measurableWrite the expected span types per feature. Four spans where the design says seven is a detectable coverage incident.
The elite caseAnthropic's evals ran green through a bug hitting 16% of Sonnet 4 requests at peak. The fix was production coverage.
Coverage is not freeStorage, engineering time, cardinality, privacy. Metadata is cheap and high-value; content capture is neither. b7 prices it.