Skip to main content

383 posts tagged with "ai-agents"

View all tags

Your Agent Needs a Supervisor, Not a Retry Loop

· 10 min read
Tian Pan
Software Engineer

Your agent died at step seven of a twelve-step task. The framework caught the exception, waited with exponential backoff, and retried. It retried the step — with the same context window that had accumulated three failed tool calls, a half-parsed error message, and a plan the model had already abandoned. The retry failed too, of course, because a retry is a bet that the world changed, and nothing about that agent's world had changed. What needed to change was the agent's state — and no retry policy in any agent framework makes that decision.

Erlang's OTP libraries codified this exact decision thirty years ago, for telephone switches that had to run for decades. The insight behind supervisor trees was never "restart things when they crash." It was that how to recover is a separate concern from doing the work, owned by a separate process, arranged in a hierarchy where each level knows a little more about what recovery means. Most agent frameworks today bolt retries onto individual calls, which is like putting a try/catch around every line of a telephone switch. What they need is the hierarchy.

Your Agent Read the Page. Nobody Saw the Ad.

· 9 min read
Tian Pan
Software Engineer

The web's economics rest on an assumption so old nobody wrote it down: the thing loading the page has eyeballs. A human arrives, an ad impression fires, an affiliate cookie drops, an analytics event attributes the visit — and that chain of tiny monetization events pays for the content. Every part of that chain is now breaking at once, because a growing share of your site's readers aren't people. They're agents, and an agent doesn't see ads. It extracts the answer, hands it to a user somewhere else, and leaves nothing behind but a log line.

This isn't a distant publisher problem you can watch from the engineering sidelines. If you build anything on retrieval — a RAG pipeline, an agent that browses, a product that summarizes the web — you are on the demand side of a market whose supply side just discovered it's been giving away inventory for free. The correction is underway, it has infrastructure and standards behind it, and it lands on your architecture as a new cost line and a new failure mode: upstream sources that were free and open last quarter going paywalled, licensed, or dark this quarter.

Your Agents Are Cheap. Maintainer Attention Isn't.

· 9 min read
Tian Pan
Software Engineer

In January 2026, curl shut down its bug bounty program. Six years, $86,000 in payouts, and a steady stream of real vulnerabilities — ended not because the money ran out, but because the signal did. Historically, more than 15% of submissions turned out to be confirmed vulnerabilities. By late 2025 the rate was closer to one in twenty or one in thirty, and submission volume had spiked to eight times normal. The queue was full of long, confident, completely fabricated reports — one came with GDB sessions and register dumps referencing a function that doesn't exist in curl at all.

Here's the uncomfortable part: the people generating that flood aren't villains. Many of them are engineers like you, running agents like yours, pointed at repositories like the ones your product depends on. AI collapsed the cost of producing a contribution to near zero. It did nothing to the cost of reviewing one. Every economic system with that shape — cheap to emit, expensive to absorb — turns into a spam problem, and the absorbing side is a volunteer who was already unpaid before your agent showed up.

Your Agent's Memory Needs a Garbage Collector

· 10 min read
Tian Pan
Software Engineer

Persistent memory is the feature everyone adds to their agent and almost nobody maintains. The pitch is irresistible: the agent remembers your schema, your preferences, the decision from last Tuesday, and every session starts smarter than the last. The failure mode is quieter: memory grows monotonically by default, and an append-only store of facts about a changing world is a slow poisoning. The API that got migrated, the team that got reorged, the architectural decision that got reversed — all of it sits in the store next to fresh facts, retrieved with equal authority, injected into context with equal confidence.

A stateless agent makes isolated mistakes. A memory-equipped agent can turn one mistake into a recurring one, because it stores the error and then retrieves it later as evidence. One confidently-written wrong memory — "the payments service owns refund logic" — contaminates every future run that recalls it, and each run that acts on it may write new memories derived from it. That's not a storage problem. That's a garbage collection problem, and most agent memory systems ship without a collector.

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."

Your Context Has Mass: Data Gravity and the Return of Move-Compute-to-Data

· 9 min read
Tian Pan
Software Engineer

The Hadoop generation learned one lesson so thoroughly it became a reflex: moving data is expensive, so move the computation to the data. Every MapReduce scheduler, every HDFS block placement decision, every "data locality" dashboard existed to serve that principle. Then, somewhere between the rise of managed model APIs and the agent boom, we quietly inverted it — and nobody repriced the decision.

Look at what a modern agent loop actually does. It retrieves a stack of documents from a vector store, pulls a repo snapshot from object storage, collects tool results from half a dozen internal services, concatenates all of it into a context window, and ships the whole payload to a model endpoint that usually lives in a different VPC, often a different region, sometimes a different cloud. Then it does it again on the next turn. And the next. Your context has mass, and you are paying freight on every hop.

Your Tool Schema Validates Types, Not Units

· 11 min read
Tian Pan
Software Engineer

A refund agent processes a customer request for $42. The tool call it emits is refund(amount: 4200) — wait, is that right? If the backend stores money in cents, it's exactly right. If the backend stores dollars, the customer just got a $4,200 refund. Both calls are syntactically perfect. Both pass JSON Schema validation in microseconds. The schema says amount is a number, and 4200 is unimpeachably a number.

This is the bug class that unit tests, schema validators, and most agent evals all sail past: unit confusion at the tool-call boundary. The model pattern-matches magnitudes from its training data — money in dollars, time in seconds, weight in whatever the surrounding prose implied — while your tool expects cents, milliseconds, and kilograms. Nothing in the type system objects. The invoice is just off by 100x.

Exactly-Once Was Hard Before Your Agent Could Retry Itself

· 9 min read
Tian Pan
Software Engineer

We spent two decades teaching services to retry safely. The playbook is well worn: a client generates a unique idempotency key, attaches it to the request, and the server records the key alongside the result inside the same transaction that performs the work. A dropped connection, a timeout, a 500 — the client retries with the same key, the server recognizes it, and returns the recorded result instead of charging the card twice. Stripe shipped this pattern years ago and it became table stakes for any API that touches money.

That entire design rests on one assumption nobody wrote down: the caller repeats its request byte-for-byte. The retry carries the same key because the retry is the same code path re-executing with the same variables. Break that assumption and the whole scheme quietly stops working.

When the Clock Is a Tool: Agents, Time Zones, and the Bug That Only Happens at Midnight

· 9 min read
Tian Pan
Software Engineer

Ask a large language model what time it is and you will get a confident answer that is almost certainly wrong. Not because the model is broken, but because there is no clock inside it. A transformer is a stateless text-completion engine: it maps tokens to tokens. Nowhere in that pipeline does a signal arrive that says "it is now 14:32 UTC." The current moment is not something the model perceives — it is something you have to hand it, every single turn, or it will invent one from the stale sediment of its training data.

This is the quiet failure that surfaces at the worst possible moments. Your agent believes it is Monday because the session opened on Monday, and it keeps believing that on Tuesday, on Wednesday, right up until it schedules a "tomorrow morning" reminder for a day that has already passed. It reasons about "the last 24 hours" of logs using a now that froze hours ago. It converts a meeting time across time zones and lands an hour off because it assumed the wrong side of a daylight-saving boundary. None of these look like hallucinations in the classic sense. The output is fluent, plausible, and internally consistent. It is just anchored to a moment that no longer exists.

Conway's Law Comes for Your Agent Fleet

· 9 min read
Tian Pan
Software Engineer

Pull up the architecture diagram for your multi-agent system. Now pull up your org chart. If you squint, they're the same picture. The "research agent" maps to the team that owns search. The "billing agent" has a hard boundary exactly where Finance stops talking to Product. The orchestrator that fans work out to five specialists looks suspiciously like an engineering manager with five direct reports. You didn't decide this on purpose. Conway's Law decided it for you.

Melvin Conway's 1967 observation is that any system you design will mirror the communication structure of the organization that built it. For sixty years this was a story about microservices and monoliths. But agent fleets are the most literal demonstration of the law I've ever seen: the agents are communication structures. An agent boundary is a place where one process hands a message to another and waits. When you draw those boundaries to match your teams instead of your problem, you don't just inherit your org chart's shape — you inherit its dysfunction, and you run it at machine speed.

The Indemnification Gap: When Your Agent Takes an Irreversible Action, Whose Budget Eats It?

· 9 min read
Tian Pan
Software Engineer

Your agent just issued a $40,000 refund to the wrong account, re-routed a freight order that triggered expedited shipping fees, or pushed a config change that took down a customer's production environment for six hours. The action is done. It is irreversible, or close enough that reversing it costs real money. Now the only question that matters is the one nobody asked before you shipped the thing: whose budget eats the loss?

Most teams discover the answer the hard way, in a conference room three days later, with the vendor's account manager on speakerphone reading a liability cap back to them. The cap is the annual subscription fee. The loss is forty times that. The conversation is short.

The Standup Is Lying: Coordinating Work When Agent Fleets Run Overnight

· 10 min read
Tian Pan
Software Engineer

"What did you do yesterday?" is the first question of every standup, and on a team that runs agent fleets overnight it has become impossible to answer honestly. The literal answer is: I wrote three prompts, went home, and woke up to eleven pull requests, four of which I have not read yet. The person reciting their update is not lying on purpose. The ritual is lying for them, because it was built around an assumption that no longer holds — that the unit of work is a human doing one thing at a time, serially, during business hours.

That assumption is load-bearing. It holds up the burndown chart, the sprint commitment, the velocity number, the "blocked / in progress / done" columns, and the whole choreography of who-tells-whom-what-when. Pull the assumption and the artifacts don't gracefully degrade. They keep producing numbers that look authoritative and mean nothing. A team can have a beautiful burndown and a green sprint while half its actual throughput happened between midnight and 6 a.m., attributed to no one, reviewed by no one, and reflected in no ceremony.