Skip to main content

348 posts tagged with "observability"

View all tags

The Model Is Already Talking to Your Customers

· 10 min read
Tian Pan
Software Engineer

Somewhere, right now, an AI assistant is explaining your product to a prospect. It is quoting a price you changed eighteen months ago, recommending an integration you sunset last quarter, and suggesting an API endpoint that returns 410 Gone. You will never see this conversation. No analytics event fires. No session recording exists. The prospect either believes the wrong answer and files a confused support ticket, or believes the wrong answer and quietly buys from the competitor the model mentioned in the same breath.

This is not a hypothetical future problem. AI referrals already account for meaningful traffic — up to 5–8% for some technology and e-commerce sites — and the answers behind those referrals are generated from whatever the model absorbed about you, whenever it absorbed it. Your marketing team spent a decade learning to monitor brand search, review sites, and social mentions. Almost nobody is monitoring the surface that is growing fastest: what the models say when someone asks about you.

The Single Quality Number That Doesn't Exist

· 11 min read
Tian Pan
Software Engineer

Somewhere in your company there is a slide with one number on it. "AI quality: 87." Last quarter it said 85, so the slide is green. Meanwhile, your on-call channel is full of screenshots of the assistant confidently inventing refund policies for your largest enterprise customer. Both things are true at once, and the slide is the one lying.

The executive request behind that slide is completely reasonable: give me one score I can track, so I know whether the thing is getting better or worse. It works for revenue. It works for uptime. It does not work for an AI feature, because an AI feature's quality is not a scalar — it is a distribution over inputs, users, and time. Averaging that distribution into a single number doesn't summarize it; it destroys precisely the information a decision-maker needs.

This post is about the gap between those two facts: why the mean of your eval suite hides the regressions that actually hurt you, what to report instead, and how to present a legitimately noisy metric to a board-deck audience without torching your credibility the first week it moves down.

Your Agent's Memory Needs Two Clocks

· 11 min read
Tian Pan
Software Engineer

Somewhere in your agent's memory store sits a fact like "the billing API returns XML." It reads as timeless truth. But it is actually two claims welded together: the API returned XML during some window of the past, and your agent observed this at some moment — possibly a different window, possibly long after the migration to JSON. The memory record keeps neither timestamp. When the agent acts on that fact and breaks something, you will ask the only question that matters in a post-incident review: what did the agent believe at the moment it acted? And your memory layer, having collapsed both timelines into one flat string, cannot answer.

Database engineers solved this problem decades ago and gave it an unglamorous name: bitemporal modeling. Every fact carries two independent clocks — when it was true in the world (valid time) and when the system learned it (transaction time). Financial systems, insurance ledgers, and audit-grade databases have run on this distinction for years. Agent memory systems, almost universally, ignore it. That omission is now the root cause of a whole family of failures we keep misdiagnosing as "hallucination."

Temperature Zero Is Not Determinism: Reproducing the Incident You Can't Re-Run

· 9 min read
Tian Pan
Software Engineer

A model gives a customer a wrong, expensive answer. You open the post-mortem, paste the exact prompt back into the exact same endpoint with temperature=0, and you get a different answer. Not a worse one, not a better one — a different one. The bug you are supposed to root-cause refuses to reproduce on demand, and the one knob everyone told you guarantees reproducibility just lied to your face.

This is the moment most teams discover that "set temperature to zero" is folklore, not an engineering control. Temperature zero changes how the model samples — it forces greedy decoding, always taking the highest-probability token. It says nothing about whether the probabilities themselves come out the same twice. And in a production serving stack, they frequently don't.

The Pager Doesn't Ring for a 3% Regression: On-Call for Statistical Failures

· 10 min read
Tian Pan
Software Engineer

Your on-call rotation was designed to catch a different kind of failure than the one that will actually take down your AI product. It watches for the service that stops responding, the latency curve that spikes, the error rate that crosses 1%. These are step functions: something was working, then it wasn't, and the discontinuity is loud enough to page a human at 3 a.m. The entire apparatus — thresholds, runbooks, escalation policies — assumes failure announces itself.

The failure mode that matters for a system with a model in the loop is the opposite. Last Tuesday your extraction pipeline was 94% accurate. This Tuesday it's 91%. Nothing crashed. Every request returned a 200. Latency is flat. The output is still well-formed JSON. But three percent of your users are now getting subtly wrong answers, and they will not file a bug, because the answer looks right. The pager stayed silent because there was nothing for it to fire on. By the time someone notices — usually a customer, usually angry, usually weeks later — the regression has been quietly compounding the whole time.

The Demo-to-Production Tax: The 90% of AI Work the Prototype Hid

· 9 min read
Tian Pan
Software Engineer

The demo worked. You typed a question, the agent called three tools, reasoned through a multi-step plan, and produced an answer that made the room lean forward. Someone said "ship it." Three months later you're still not shipped, and nobody can quite explain where the time went.

Here is where it went: the demo was 10% of the work. It was the brain. The other 90% is the plumbing — the evals, guardrails, observability, cost controls, and fallback paths that nobody claps for because they're invisible when they work and catastrophic when they don't. That 90% is the demo-to-production tax, and most teams budget for it as if it were a rounding error.

The numbers say otherwise. MIT's 2025 study of enterprise AI found that 95% of generative-AI pilots delivered no measurable P&L impact. A separate analysis put it more bluntly: for every 33 proofs of concept an enterprise starts, four reach production. That's an 88% mortality rate, and the cause of death is almost never the model. It's everything the demo let you skip.

The Agent Wall-Clock Budget That Raced Your Tool's Own Timeout

· 11 min read
Tian Pan
Software Engineer

There is a class of agent bug that does not appear in any single component when you look at it in isolation. The model is fine. The tool is fine. The retry policy is fine. The timeout values are even, on paper, generous. And yet a tool that consistently completes in eight seconds keeps landing against an agent that has already declared it a failure at seven point nine, replanned around an "error" that never happened, and started a second call that the first call's result is about to collide with.

The bug is not in any of the boxes. It is in the gap between two clocks that nobody agreed should be the same clock.

The Citation Index Your Chunker Shifted by One When It Started Prefixing Line Numbers

· 11 min read
Tian Pan
Software Engineer

The chunker started prepending [line N] to every chunk. The eval went green. Every citation the model produced after that day pointed to the paragraph one position before the actual evidence, on every document, in the regulated industry the product serves. The team did not find out from the eval. The team found out from an auditor who looked at the cited sentence, read it, and pointed out that it contradicted the claim it was supposed to support.

This is the kind of regression that survives a code review, a manual QA pass on three sample documents, and a feature-flag rollout. None of those checks were wrong in isolation. They were all asking the same question — does a citation appear where one is expected — and none of them were asking the question the auditor asked, which is whether the citation points at the sentence the claim came from. The gap between those two questions is where the off-by-one lived for as long as it lived.

What makes this failure mode worth a separate write-up is not the bug itself. Off-by-one errors are old news. The interesting part is that the failure was produced by two systems that continued to agree on the structure of an integer while silently disagreeing about what the integer meant.

The Conversation Summary Your Agent Regenerated Each Turn Because the Cache Key Included a Timestamp

· 11 min read
Tian Pan
Software Engineer

A cache that is being written to but never read from is not a cache. It is a logging system with extra latency, billed by the kilobyte. And the cruelest version of this failure mode is the one where the cache looks healthy from every angle except the one that matters: the set calls succeed, the get calls return quickly, the keys are well-formed, the values are valid, the TTLs are sensible. The only thing wrong is that no get call ever finds the key a previous set call wrote, because a single field in the key changes every time it is computed.

This is the story of a debugging session that added a timestamp to a cache key "so I can tell which cache entry I'm looking at," and the system that quietly paid for fourteen extra LLM calls per conversation for two weeks before anyone noticed.

The Debug Logger That Put Your System Prompt in a Customer-Readable Audit Feed

· 10 min read
Tian Pan
Software Engineer

A security-conscious customer pulled their tenant's audit export, opened the JSON, and read the verbatim refusal policy, retrieval pipeline structure, and a handful of internal product identifiers from a field called llm.request.system. No exploit. No prompt injection. No jailbreak. Just a log field your platform team added six months earlier so engineers could correlate prompt versions with incidents — surfaced through a feed your enterprise team had separately opened to tenants for SOC 2 reasons.

The disclosure happened during a normal Wednesday afternoon. Your security team got paged by the customer, not by an alert. The incident timeline doesn't show a deploy on the day of the leak — the misconfiguration shipped on the day the audit feed expanded its field allowlist, which was a different team, a different sprint, and a different ticket. Both reviewers signed off on what they were looking at. Neither was looking at the composition.

The Embedding Deprecation That Halved Your Retrieval Recall Without a Deploy

· 10 min read
Tian Pan
Software Engineer

The most expensive embedding bug a RAG system can ship is the one where nothing in your repository changes. Your retrieval code is the same. Your index is the same. Your query path is the same. And one Tuesday in week six, somebody notices that the answers used to be better.

The provider posted a sunset notice for the embedding family your index was built against twelve months ago. The platform team filed it in a deprecations dashboard with a year of runway and moved on. The sunset path wasn't a hard cutoff — it was a quiet quality regression where the deprecated endpoint started routing to a "compatibility" successor that returned vectors in the same dimensionality and a subtly different semantic geometry. Query embeddings began drifting against the corpus you embedded a year ago. Recall@10 on your standing eval slid by 47% over six weeks. The team only traced it back when an unrelated quality dashboard crossed a threshold, dragging a senior engineer into a root-cause exercise that ended at an embedding endpoint no one on the call had touched in a year.

The Eval Harness That Ran on Yesterday's Prompt Template After Your Team Shipped a New One

· 9 min read
Tian Pan
Software Engineer

The incident timeline reads cleanly. At 9:02 your platform team pushed prompt-template@v38 to the config service. At 11:14 your dashboards showed everything green. At 16:51 someone in support flagged a spike in escalations. At 17:03 you opened the eval suite, found a regression score of 0.34, and rolled back. The post-mortem says "caught in eight hours, no customer harm beyond the 0.04% who saw it." Engineering leadership applauds the response time.

It is wrong. The regression was caught in zero hours. The eval suite running at 17:03 was the same eval suite running at 09:03. It had been pointed at v37 the entire time. The harness loaded the template from your config service at process startup, cached the rendered prompts as Python objects in module-level scope, and never reread the source. Your live traffic moved to v38 at 9am. Your eval moved at 17:03, when someone restarted the worker pool to "rerun the regression." Eight hours of customer interactions ran against a prompt that no eval had ever scored, while the eval kept grading a prompt that no production request was using.