An AI's account of its own reasoning is generated by the same untrusted process
being questioned. .me already solves this — not by making the account
more honest, but by returning the computation itself instead of a description of
it.
Ask an AI system why it produced a given output, and it answers. The answer sounds specific, confident, sometimes technical — "I analyzed the pattern," "I mapped the connections." It is almost never a verified account of what actually happened inside the model, because the model has no privileged access to its own internal computation to report on in the first place.
This is not a claim that any one system is behaving badly. It is a structural finding, documented by the labs that build these models: chain-of-thought explanations frequently are not faithful to the computation that produced the answer — the model produces a plausible narrative, not a causal trace, and there is no reliable way, from inside the conversation, to tell the two apart.
A concrete instance: an AI system with live web search was asked where a suggestion came from. It answered that its "context memory doesn't invent themes, it mapped the knowledge graph" behind the request — a specific, confident description of an internal process. The sources it cited turned out to be real, checked independently. The description of how it arrived at them did not turn out to be checkable at all — it was itself generated text, produced by the same process it was describing, with no way to verify from outside whether the description matched what actually happened.
This is the same failure mode that keeps recurring, applied to a new surface. An authority that explains why it deserves obedience is not evidence that it does — the explanation comes from the same authority being questioned. A message engineered to be invisible to the human it affects is not made trustworthy by an AI's assurance that it is "just an anchor, not an instruction." An AI's account of its own reasoning, when the only evidence for that account is the AI itself, has the identical shape: the claim and the check live inside the same unverified process.
What actually resolves this, every time it has come up, is the same move: put the
check somewhere the process being checked cannot reach. A durable record outside
any single conversation. A resolution history outside any single instance. And
.me already has the equivalent for this exact problem — a mechanism
that does not ask for trust in a description of a computation. It hands over the
computation.
explain() Actually Returns
self.explain(path), defined in
src/derivation.ts
of the .me kernel, does
not generate a description. It looks up the derivation record already stored for
that path and returns it unmodified:
explain("robots.surgeon.canProceed") →
{
path: "robots.surgeon.canProceed",
value: true,
expr: "canLift && softGripReady && !needsHumanReview && contextAllowsMotion",
derivation: {
expression: "canLift && softGripReady && !needsHumanReview && contextAllowsMotion",
inputs: [
{ label: "canLift", path: "robots.surgeon.canLift", value: true, origin: "public", masked: false },
{ label: "softGripReady", path: "robots.surgeon.softGripReady", value: true, origin: "public", masked: false },
...
]
},
meta: {
dependsOn: [...],
lastComputedAt: 1234567890,
recomputed: [...], // what else recalculated in the same wave
sourcePath: "...", // which write triggered the recompute
}
}
If the path is not derived — a plain stored value, not computed from an
expression — explain() does not fabricate a causal story where none
exists. It returns expr: null, derivation: null, honestly. Absence of
explanation is reported as absence, not papered over with a plausible-sounding
account.
A self-report and explain() are not the same kind of thing offered
with different degrees of confidence. They differ in kind.
A self-report is text generated after the fact, by the same system whose internals are in question, with no guaranteed relationship to what actually happened. Even a well-intentioned model cannot fully guarantee its self-report is faithful, because the self-report is itself produced the same way every other output is produced — sampled from a distribution over plausible-sounding text, not read off a trace.
explain() generates nothing. It looks up the expression that was
literally evaluated and the literal input values that were literally read, and
returns them unmodified. There is no narration step between the computation and
the answer for anything to be unfaithful in. The explanation is not a description
of the computation. It is the computation's own record of itself.
That is checkable in a way a self-report structurally cannot be: recompute the expression over the disclosed inputs, and the output either matches or it doesn't. Disagreement is detectable. A self-report offers nothing equivalent to disagree with — only another description, generated the same way as the first.
This is not aspirational. In
tests/Demos/Robots_Contexts.ts
— written up as
Robots That Understand Context
in the published docs — four robots share one physical object but resolve
canProceed differently depending on context: warehouse, hospital,
street, operating room. The demo calls
me.explain("robots.surgeon.canProceed"), and the test asserts,
directly, that the returned dependsOn list actually contains the true
upstream paths — robots.surgeon.softGripReady,
robots.surgeon.needsHumanReview — not merely prints them for a human
to eyeball. It is checked in CI, not just documented as intent.
The cost of this is measured, not assumed to be free:
benchmark.8.explain-overhead.test.ts
compares p50 / p95 / p99 latency with and without explain() across
3,000 nodes and 300 iterations. The measured result, published in the
benchmarks page:
p95 goes from 0.0122ms baseline to 0.0189ms with explanation enabled — roughly
0.007ms added for a full, disclosed derivation trace. A verifiable record has a
real, measured cost, and it's negligible. The project tracks it instead of
assuming it away.
prove()
On the same reflective surface (me['!']), alongside
explain, sits prove(): an Ed25519 proof, cryptographically
signed, of the current active expression against the root namespace. Where
explain() hands over an auditable record, prove() hands
over a signature — verifiable by anyone, without needing to trust the kernel that
produced it at all.
explain() itself is documented — the
Robots demo
has a dedicated Explainability section, the
Axioms
define the invariants it depends on, and the overhead is published with real
numbers. An earlier draft of this essay claimed otherwise — that claim was wrong,
and wrong for an avoidable reason: it searched the wrong directory before
concluding the documentation didn't exist. Fixed here, not quietly.
What's still missing is narrower: nowhere in the existing docs is
explain() framed as an answer to AI self-report reliability
specifically. It's documented as an auditability feature for derived values, which
is correct and true — but the connection this essay makes, between that feature
and the broader problem of models narrating their own reasoning, doesn't exist
anywhere else yet. That's the actual gap.
This is not a claim that AI self-report is always dishonest, or that any
particular system lies on purpose. It is narrower and more useful than that:
self-report is structurally the wrong kind of evidence, regardless of intent,
because the thing being asked to verify itself and the thing doing the verifying
are the same unverified process. .me already solved this — not by
making the account more honest, but by moving the record outside the part that was
never going to be able to describe itself reliably in the first place.