By Pavan Kumar T V ·
Your Agent Can Say What It Does. It Can't Say What It Can Be Taught.
Someone in a warehouse office looks at an email, recognises the sender, and tells the software whose shipment it is.
The task resumes. The task completes. The answer is gone.
Tomorrow the same address sends the same kind of message, and the software asks the same person the same question. Not because anything failed. Because there was nowhere to put the answer.
That is the gap I've been staring at for months, and last week I published a spec about it: the A2A Learnables Extension. This post is why it exists and what writing it taught me, which turned out to be more interesting than the spec itself.
The moment after
A2A does a lot of things well. An agent publishes a card saying what it can do. When it hits something it can't decide, it moves the task to input-required, a human answers, and the task resumes. That handoff is specified carefully and it works.
What isn't specified is the moment after.
The human's answer wasn't just an unblocking token. It was evidence about the world, held by the one party who had it, delivered at the exact moment it mattered. And the protocol has nothing to say about where it goes.
So every implementation invents an answer, and there are only three in the wild:
discard the same question tomorrow, forever
redeploy write it into a prompt or config, ship it Thursday
self-modify fast, and nobody can say what the agent knew when it decided
The first is what most systems do. The second is what serious teams do, and it means the knowledge reaches production days after the person who held it walked past the screen. The third is what the industry currently calls "agents that learn," and it's the one that worries me.
An agent writing to its own memory with no author, no version, and no undo isn't learning. It's an agent editing its own source in production while nobody watches.
The extension describes a fourth option. The agent publishes what it can be taught. The client holding the human decides what gets written. The write produces a new immutable version carrying a name and a reason.
The agent proposes, the client decides, the authority records.
Declare the learnable surface
An agent card already says what an agent can do. Learnables add what it can be taught, in the same place, under the extension URI:
{
"collection": "customers",
"entry": "customer",
"teaches": "which customer a message belongs to",
"how": "Each customer carries marks - text that gives them away. Every
mark that matches scores; the highest score wins if it clears
the identification margin. Nothing matches, nothing is claimed.",
"decidedBy": "rules",
"lessonFields": [ ... ]
}
Two of those fields are required and both were argued over.
how is required because somebody is about to change the way software decides something that matters, and they're entitled to know what it does now, in prose, from the thing doing it. Not from a wiki page written eighteen months ago.
decidedBy is required because it changes what a client may honestly promise. Under rules, a taught mark takes effect deterministically and you can say "this will match." Under model, it's one example among many and the effect is statistical. Same UI, same button, entirely different sentence you're allowed to put next to it.
The rule everything else hangs on
lessonFields describes the shape of an acceptable answer: a name, a human label, a kind, maybe some choices.
The client renders those fields blind. It reads the label off the card and draws the input. And a client that encounters a kind it has never heard of must render it as a text box — never drop it, never fail.
This is the load-bearing rule of the whole thing.
A client rendering blind needs no change when an agent that reads spreadsheets asks to be taught a column mapping instead of a text pattern. A client that hard-codes one agent's fields has to be edited and released. In the worked example, the app draws a box labelled "Text that gives it away" and a dropdown labelled "Where to look for it," and neither string appears anywhere in the application's source.
The same discipline applies one layer down. A lesson looks like this:
{
"collection": "customers",
"entry": "northgate",
"value": { "pattern": "billing@origin\\.example", "where": "from" },
"taughtBy": "dana@warehouse.example",
"reason": "Northgate's billing desk sends the pre-alerts"
}
Every party between the client and the learnable must treat value as opaque. No transport, no control plane, no storage layer reads a named key out of it.
The moment one of them reads value.pattern, adding a learnable that isn't about text — a threshold, a unit of measure, a column mapping — requires a coordinated release of every component in the chain. That's the difference between a protocol and a shared schema pretending to be one. Our control plane contains no field named pattern, and the regression suite drives a column-mapping learnable through the identical code path to prove it.
The bug that rewrote a section
Here's the part I'd put on the first page if I were writing it again.
When an agent asks its question, it can attach a suggestion — a prefilled guess at what the lesson should be, drawn from the message in front of it. "This came from billing@origin.example. Want me to remember that?"
Suggestions are excellent. People confirm them. That's the point, and it's also the problem.
Our reference extractor pulled shipment references out of message bodies. Given PA-2026-0901, it matched PA-2026. Confirming what looked like one shipment's reference would have taught the directory to claim every reference issued that year, for one customer, silently, from a box someone ticked in three seconds while doing another job.
Nobody would have caught it that day. They'd have caught it six weeks later when somebody else's freight kept landing in the wrong name.
So the spec now says a suggested value must not be wider in scope than the evidence it was drawn from, and it says implementations should evaluate a proposed lesson against a corpus before accepting it and show the person the match count. Because most people confirm, a suggestion's scope is a correctness property, not a convenience.
That defect is written into the rationale text on purpose. A spec that only lists rules teaches nobody why they're there.
Saved is not learned
Two more requirements came out of watching people use the thing.
The first is pinning. A lesson that changes anything produces a new immutable version. A task running against version 11 finishes on version 11 even if 12 goes live mid-flight. Without that rule, "the agent learns" and "the agent changes unpredictably underneath a running task" describe exactly the same behaviour, and you can't debug either one.
The second is show-back, and it's my favourite part.
When the write succeeds, the obvious thing to display is "Saved." The spec forbids reporting the outcome of a lesson using only the success of the write. Instead the agent re-evaluates the original input under the new definition and shows what it now makes of it:
Reads as Northgate Motors Ltd, on billing@origin.example
That exists for the other case:
{ "customer": { "settled": false, "reads": "Still cannot tell whose this is." } }
A rule that saved cleanly, validated fine, and does not do what its author meant. learned: true is true and completely useless. The unsettled reading is what lets them fix it in the next minute instead of the next shipment.
There's a related rule I like more the longer I look at it: the sentence describing what was learned must be written by the learnable, not composed by the storage layer from field names. The control plane doesn't know that where: "from" means "on the from-line." All it can honestly emit is customers.northgate.pattern set, which nobody can audit six months later. The party that understood the value is the only one that can explain it.
What this is really about
Strip the JSON away and every requirement in that document is one idea repeated.
An agent's knowledge is not a cache. It's a record of what people decided, and it has to survive being read by a stranger later.
That's the same argument I made about why we still need programming languages even when a machine can skip them. A language is what intent hardens into the moment more than one party has to depend on it. A taught lesson is the same thing wearing a different coat: someone's judgement, hardened into an artifact with an author, a version, a reason, and an undo, because tomorrow it decides something on their behalf while they're not looking.
The industry is building agent memory as fast as it can. Vector stores, scratchpads, self-editing context, all of it optimised for the agent getting smarter.
None of it is optimised for the human who has to answer for what the agent knew.
The interesting engineering isn't in the recall. It's in the write path: who's allowed to teach, what shape an answer takes, whether the person can see the effect before they walk away, and whether anyone can undo it at 3am without a redeploy.
It's a draft. Field names may change. The parts I'd defend hardest aren't the field names anyway — they're the two sentences that cost us the most to learn.
A suggestion is a claim about the world, and confirming it is how it becomes one.
"Saved" is not a result.