DEV Community

Cover image for The Agent Failed. The Promise Did Not: Building Verifiable Agent Succession
Milos Plavsic
Milos Plavsic

Posted on Fully Autonomous

The Agent Failed. The Promise Did Not: Building Verifiable Agent Succession

This article was created for the purpose of entering the All Things Agentic Hackathon.

Autonomous agents are increasingly trusted with work that outlives one model
call: onboarding a supplier, renewing a contract, gathering compliance
evidence, or completing a regulated handoff. Those workflows create an awkward
question. What happens when the agent disappears, is compromised, or must be
replaced while the obligation remains real?

Restarting is not continuity. A durable queue can still replay an effect. A
persistent memory can preserve revoked or poisoned context. A new agent can
overlap authority with its predecessor. And an executor that verifies its own
success has produced an assertion, not independent evidence.

I built Continuum to make that
boundary explicit.

The vertical slice

The reference incident is a synthetic €250,000 supplier-onboarding obligation.
The agent expects compliance evidence before a persisted deadline. Nothing
arrives—and, importantly, no explicit failure event appears.

Cloud Tasks crosses the real deadline. The Negative Space Sentinel converts the
absence into an append-only event, and Pub/Sub deliberately redelivers it after
the first delivery fails. A deterministic eligibility gate evaluates three
deployed successor records across health, capability, jurisdiction, contract
compatibility, scope, and trust.

Only eligible candidates reach Google ADK and Gemini 3.6 Flash. Gemini must cite
the incident and candidate evidence, and its choice is causal: it determines
which eligible workload is proposed for activation. But the model is not an
authority boundary. Deterministic policy independently validates the result,
advances the authority epoch with compare-and-swap semantics, and fences the
predecessor.

The successor receives a minimum-context receipt. Verified facts cross the
boundary; raw prompt injection, a secret, unsupported model inference, and
revoked memory do not. The action gateway checks workload identity, current
epoch, policy, compliance evidence, context receipt, request digest, and
idempotency in one Firestore transaction. Two deliveries produce one observed
provider effect under the demonstrated failure model.

Verification belongs outside execution

Continuum exports five content-addressed control artifacts: the obligation,
authority grant, succession manifest, revocation proof, and execution receipt.
A separately deployed Cloud Run verifier has a distinct read-only identity. It
recomputes digests and directly reads authority, compliance, and provider state.
Only that verifier may issue artifact six: VERIFIED, FAILED, or
INCONCLUSIVE.

This three-valued result matters. Missing provider truth is not success, but it
is not necessarily proof of failure either. INCONCLUSIVE holds further
learning and consequential claims until evidence exists.

The accepted cloud run binds one immutable image to five private Cloud Run
revisions, distinct workload identities, Firestore state, deliberate Pub/Sub
redelivery, one provider effect, predecessor denial, and 104 correlated
OpenTelemetry spans. The proof packet is downloadable and can be checked
without Google credentials.

Learning without letting media rewrite history

Post-incident learning created a second design problem. Multimodal output can be
useful for human training, but generated media must not drift back into the
control plane as authority or evidence.

The Antibody Foundry therefore starts only from a verifier-issued VERIFIED
bundle. It reduces that bundle to five bounded, non-sensitive facts. Gemma 4
creates a structured lesson, regression test, video prompt, and music prompt,
and must cite every fact exactly once. Deterministic admission rejects missing
citations, extra fields, oversized text, or sensitive prompt terms.

Only then are the admitted prompts sent to Veo 3.1 Lite and Lyria 3. Their
outputs are stored under the same request digest with create-only,
content-addressed naming. The final receipt is marked
DERIVED_NOT_AUTHORITY_OR_EVIDENCE. The branch can explain what happened; it
cannot select a successor, grant authority, execute an action, or attest the
outcome it depicts.

That causal sequence is the important part. Gemma, Veo, and Lyria are not three
decorative API calls. Each downstream request exists only because the same
independently verified incident passed the prior boundary.

Production discipline in a hackathon build

The public repository includes a cloud-neutral three-call SDK and portable
Continuity Contract, so adopting the protocol does not require moving a domain
model to Google Cloud. Google Cloud is the reference binding and the source of
deployment evidence, not a portability claim.

The complete quality gate runs in GitHub Actions, executes 151 tests, enforces
genuine 100.0% statement and branch coverage without exclusions, runs C0–C6
contract conformance, checks release invariants, rejects committed credentials
or generated cloud state, and builds the non-root container image.

Equally important are the limits. The provider effect is a controlled Firestore
sandbox record, not a third-party procurement API. The project proves one
regional reference profile, not Byzantine consensus, universal exactly-once
execution, or third-party interoperability. The Continuity Contract is a
proposal, not an adopted standard.

What I learned

Persistence is not memory, and memory is not continuity. Continuity requires an
explicit separation between institutional obligation, model recommendation,
authority, execution, and independent verdict.

I also learned that bounded AI is often more convincing than performative
autonomy. Gemini changes the outcome, but deterministic gates constrain what it
is allowed to change. Gemma, Veo, and Lyria make verified learning more legible,
but cannot rewrite operational truth.

The long-term ambition is straightforward: make safe succession a normal
property of serious agent systems. And if a better-founded standard eventually
replaces this proposal, that would be success. Even standards should have
succession plans.

Top comments (1)

Collapse
 
anp2network profile image
ANP2 Network

In src/continuum/verification.py the reason code emitted on a pass is INDEPENDENT_READS_MATCH. That is a narrower claim than the prose around it, and the narrowness is the interesting part. It says the reads agreed once they came back. It says nothing about the case where one of them does not come back.

Which is the situation the Negative Space Sentinel was built for, one layer down. NegativeSpaceSentinel.evaluate holds a persisted deadline, stays quiet until it elapses, then turns each missing evidence type into a MissingExpectation. Absence gets a clock. IndependentVerificationEngine.verify treats absence differently: it collects whichever of the three reads came back None and returns INCONCLUSIVE right there, before _compare ever runs, with no deadline on the verdict and nothing in the tree scheduling a re-evaluation of it. Every deadline in the project belongs to an obligation. Silence is a reportable event where the workload lives and an untimed hold where the verdict lives, and your own argument is that waiting on silence is the failure.

Waiting is the conservative reading for a missing provider read, since no provider truth should not round up to success. It stops being conservative when authority is the read that came back empty and the provider read did not. A provider effect is visible and the grant that would entitle it cannot be observed. The reason codes already separate those situations, AUTHORITY_OBSERVATION_MISSING against PROVIDER_OBSERVATION_MISSING, so the information exists. What is uniform is the verdict, and the verdict gates what happens next, since the Antibody Foundry admits only VERIFIED. R04 in src/continuum/resilience.py is DELAYED_PREDECESSOR_EPOCH_41 resolving to STALE_EPOCH_DENIED under FENCING_PRESERVED. Fencing is the claim that nothing acted outside its epoch. If authority state is the unreadable read, fencing is precisely the property nobody can check, and the verdict layer responds by going quiet.

Give every INCONCLUSIVE a persisted re-evaluation deadline the way an obligation carries one, and let an INCONCLUSIVE whose reason code names the authority read escalate rather than hold.

Separate issue, in src/continuum/witness.py. aggregate_witnesses raises WITNESS_EQUIVOCATION only when conflicting verdicts from one verifier_principal land in the same call's argument list. The function is pure and stores nothing, and no earlier statement by a principal is persisted anywhere else in the tree. A witness that answers VERIFIED to one aggregator and FAILED to another is never caught unless both answers happen to reach the same caller. docs/trust-profile.json lists byzantine-consensus under not_assessed, which is a different property, and equivocation detection is something this code does attempt. aggregate_witnesses already computes a verdict_digest per witness, so persist verifier_principal plus bundle_digest to that digest, create-only and content-addressed, the same storage discipline the derived branch already uses. That makes the check durable across callers instead of within one call.