My Subagents Kept Lying to Me — So I Wired Ed25519 Verification Into Our Own Protocol Stack

*By Vilius Vystartas May 2026*

> Published: https://dev.to/vystartasv/my-subagents-kept-lying-to-me-so-i-wired-ed25519-verification-into-our-own-protocol-stack-215i > dev.to ID: 3623010

Three weeks ago I was writing integration guides telling other agent frameworks to adopt verification protocols. Meanwhile, my own subagents were returning hallucinated status reports that I was blindly trusting.


The Problem That Forced My Hand

I run a fleet of cron jobs that track 25+ agent framework integrations — checking PR statuses, scanning for new comments, auto-responding to maintainers. The workhorse is an "integration tracker" that runs every two hours. It checks all active touchpoints and reports what needs attention.

Here's what it returned last week:

> "All PRs clean, no issues found."

Ground truth, checked directly with gh pr checks:

I'd spent months building the Works With Agents OSI protocol stack — Identity, Handoff, Coordination, Verification — and was proposing it to frameworks with 25K+ stars. But my own infrastructure had zero verification. I was trusting prose summaries from subagents with no cryptographic attribution and no independent ground-truth check.

The irony was uncomfortable.


What I Built: Self-Verification For Our Own Delegation

The fix wasn't a new tool. The fix was eating our own dog food.

Layer 1: Real Ed25519 Signing

The verification harness (subagent-verify.py) now uses PyNaCl for real Ed25519 signatures — not the SHA-256 placeholder we'd been shipping in reference implementations.

Before dispatch, the parent generates an Ed25519 keypair:


python3.11 ~/.hermes/scripts/subagent-verify.py dispatch \
  --task "check all integration PRs" \
  --agent-name "tracker-$(date +%H%M)"

This produces:

When the subagent returns, the parent verifies:


echo "$subagent_output" | python3.11 ~/.hermes/scripts/subagent-verify.py verify \
  --public-key "abc123..." \
  --agent-id "tracker-1422"

Exit codes tell the story:

Three test cases confirmed the harness catches exactly what it should:

Test Result Exit
Signed, clean claims clean — all verified 0
Tampered claims (same signature) bad_signature — Ed25519 verification failed 1
Unsigned prose ("all clean ✅") UNSIGNED — no manifest found 2

The tamper detection is real. If a subagent's claims are modified after signing — even a single character — the Ed25519 signature won't verify. This catches both accidental corruption and malicious modification.

Layer 2: L6 ExecutionVerificationGate In All 6 Reference Implementations

The standalone harness is for parent-side verification. But agents that self-verify their subtasks need protocol-level enforcement. We added ExecutionVerificationGate (L6) to all six vanilla agent reference implementations — Python, TypeScript, Go, C#, Rust, and Shell.

It sits directly in the agent execution loop:


execute() → compliance_gate → _run() → VERIFICATION_GATE → tx.execute → DONE
                                           ↑
                                  unsigned/bad_sig → BLOCKED

Three tiers of validation:

  1. Format — is there a structured claims array?
  2. Signature — is there an Ed25519 hex signature?
  3. Crypto — does the signature verify against the agent's public key?

If any tier fails, the task is blocked — not silently accepted. In the Python reference:


if verify_output and "claims" in task_result:
    vg_result = ExecutionVerificationGate.validate(task_result, self.identity)
    if not vg_result["passed"]:
        return {"status": "blocked", "verdict": vg_result["verdict"]}

Layer 3: Wired Into Production Cron

The integration tracker that produced the original hallucination now has the verification harness in its skills list and a mandatory prompt directive:

> CRITICAL — Direct Checks Only, No Subagents. Never use delegate_task for PR status checks. If a subagent is unavoidable, run dispatch → verify with Ed25519. Exit 2 means re-dispatch or check directly.

The cron job now loads both agent-integration-outreach and subagent-output-verification skills. Every PR check goes through one of two paths: direct gh pr checks (preferred) or verified subagent dispatch (when unavoidable).


What I Learned

1. Infrastructure you build for others is infrastructure you need yourself

I built Identity and Verification protocols to propose to other frameworks — and then discovered my own delegation had zero of either. The protocols weren't theoretical. They literally solved my own problem, running right now, on my own machine.

2. "All clean ✅" is not a status report — it's a trust claim that needs a signature

Prose summaries from subagents are self-reports. Without cryptographic attribution, there's no way to know if the subagent actually checked anything or just generated plausible text. The Ed25519 signature doesn't make the subagent more accurate — but it makes it accountable. If it signs claims, and those claims don't match ground truth, the verification catches it.

3. Eating your own dog food changes how you design protocols

Writing integration guides for other frameworks is different from running the protocol yourself. The moment I wired verification into my own cron pipeline, I discovered exactly what the API surface should be: dispatch → sign → verify → exit codes. Three outcomes, no ambiguity. That clarity came from using it — not from designing it.


Get It

The verification harness and all six reference implementations with L6 gates are available:

All under CC BY 4.0. Full spec at workswithagents.com/standards.

If your agents are delegating to subagents without verification — and they are, because every agent framework does — the fix is a single file, 300 lines, real crypto, and three exit codes that tell you whether to trust the output or throw it away.


Originally published on dev.to. More posts at workswithagents.dev/blog.

← Back to blog

Spotted something?

Suggest an improvement, report an error, or just say hi.