Young's Mind
00 Scope

LEARNED AND PLAN

Consolidated. This note's findings now live in ../MIN-STUDIES.md §2, 3, 11. The original is kept for its measurements; do not re-derive from it.

What we learned from Hermes — and the plan

Young, 2026-10-10: "What did we learn from Hermes, What is our plan for SolOSV3? Current A2A v1.2.2"


PART 1 — What we learned from Hermes

1.1 Moyai is built on Hermes — with one honest qualification

Yes. pyproject.toml names the package hermes-workspace: "An internal agent workspace with Hermes, Modal sandboxes, and native app connections." Its Hermes pin 7968c72a is in our own git history.

Mira's qualification is also true and worth keeping: Moyai treats Hermes as one of seven interchangeable harnesses — it runs Hermes rather than being wedded to it. Both statements hold:

ClaimTrue?
Moyai is built on HermesYes — the workspace wraps it; the package is named for it
Moyai treats Hermes as swappableYes — one of seven harness entries

What it means for us: our Brain Unit is Hermes, and a production system already treats it as a swappable executor. That is the shape V3 wants — and it is proof the shape works.

1.2 🔴 The finding that changes the plan: Hermes already ships the spine

I studied our own Hermes source. It already implements most of what V3 Stages 2–5 proposed to build — and I proved it live, not from docs.

A2A v1.0, running on this host right now:

GET http://127.0.0.1:9900/.well-known/agent-card.json   → HTTP 200
Live fieldValue
namehermes-LAB
version1.0.0
supportedInterfaces[{"url":"http://127.0.0.1:9900/","protocolBinding":"JSONRPC","protocolVersion":"1.0"}]
capabilitiesstreaming: true, pushNotifications: true
skills35, built dynamically from the live tool registry

And both method dialects, on the wire:

POST {"method":"tasks/get"}  → {"error":{"code":-32001,"message":"task not found: no-such-task"}}
POST {"method":"GetTask"}    → {"error":{"code":-32001,"message":"task not found: no-such-task"}}

Identical. -32001 is the spec's reserved TaskNotFound code. The plugin's _METHOD_TABLE maps v1.0 PascalCase and legacy v0.3 slash names — the exact dialect defect V2 died of, already solved.

The states are spec-correct: TASK_STATE_CANCELED (one L), TASK_STATE_INPUT_REQUIRED. V2 served cancelled, input_required, auth_required — all three wrong.

1.3 The stuck rule — Sol said nobody had a number. Hermes has three

MechanismNumberSource
A2A orphaned-task watchdog300 sadapter.py:_MIN_ORPHAN_TIMEOUT
Watchdog sweep period60 sadapter.py:_WATCHDOG_INTERVAL
kanban stale worker3600 skanban_db.py:DEFAULT_CLAIM_HEARTBEAT_MAX_STALE_SECONDS

And the handler is the honest version — complete(tid, STATE_FAILED, "[task orphaned — no reply produced]"). A task that stops is a state, not an absence, and the state names the cause.

1.4 kanban is Young's task contract, already built

Your four requirements map onto it exactly:

You asked forkanban has
store information of taskSQLite board, 30+ modules
assign to agentclaim + kanban_heartbeat
completion statustodo · blocked · review · done · archived
follow up if stuck or blockedheartbeat staleness → dispatcher watchdog

And the separation-of-duties rule is enforced: "a stale or unbound worker must not terminate a run a live successor owns."

1.5 Also native, and we did not know to ask

  • a2a_orchestrate(capability, message, mode) — fan-out to every peer advertising a capability. This is the orchestrator, built — and V2 retired its orchestrator as a duplicate.
  • Per-peer identity — A2A_PEER_TOKENS="alice:tok1,bob:tok2", and "nothing in the request body can assert identity." The credential rule, implemented.
  • Anti-loop — A2A_MAX_PINGPONG_TURNS, default 5, hard max 20.
  • Security — injection filters ("remote peers can never reach operator slash commands"), outbound credential redaction, SSRF-guarded push callbacks, per-identity rate limiting, append-only ~/.hermes/a2a_audit.jsonl.
  • Progressive-disclosure skills + a curator for staleness/archival.
  • Two-tier bounded memory + a Memory Provider ABC.
  • They name their own limits — "tasks/cancel marks the task canceled and drops the reply, but cannot abort the live session's in-flight turn."That honesty is the culture we want.

1.6 The uncomfortable summary

We spent a day designing an A2A-native agent system, and the framework we run inside already is one. Same lesson as the fork question, one layer down.

And the one thing that stays exactly as planned is Stage 0 — the instrument that tells whether a control is in force. Because every finding in this study came from reading source, and none of it came from the system telling us.


PART 2 — ✅ Version corrected: a2a-sdk is 1.2.2

Young is right, and our design docs were behind. Verified against PyPI and the repo tags:

SourceValue
PyPI a2a-sdk current1.2.2
Latest releasev1.2.2, 2026-10-05
Recent line1.1.1 → 1.1.2 → 1.1.3 → 1.1.4 → 1.1.5 → 1.2.0 → 1.2.1 → 1.2.2
requires_python>=3.10

🔴 Two different numbers — this distinction is load-bearing

The SDK version and the protocol version are not the same thing. Our docs say "A2A v1.0" and cite a2a-sdk — but never pinned the SDK's own version. That is exactly the V2 defect class: a version declared in one place and served from another.

ThingVersionMeaning
A2A Protocol1.0the spec — what the wire conforms to
a2a-sdk (Python)1.2.2the implementation of that spec
V2's PROTOCOL_VERSION"1.0.0"declared — but served v0.3 slash names

The SDK's own compatibility table:

Spec versionTransportClientServer
1.0JSON-RPC · HTTP+JSON/REST · gRPC✅✅
0.3 (compat)JSON-RPC · HTTP+JSON/REST · gRPC✅✅

And the v0.3 compat adapter still ships in 1.2.2 — src/a2a/compat/v0_3/ confirmed present at the tag. So the migration is still a flag, not a rewrite.

What changed in the 1.2.x line — and why it matters to us

ReleaseChangeRelevance
1.2.2"name the task state in terminal-state errors"; SSE shutdown grace periodserror messages that name the state — the honesty rule again
1.2.1keyset cursors for ListTasks page tokenspagination that does not drift
1.2.0multi-replica cluster mode; caching headers on the card endpoint; opt-in media-type validation against the card; reject a message whose contextId disagrees with its task; reject terminal-task ops with UnsupportedOperationErrorcluster mode = a fleet can scale; contextId rejection = the cross-talk guard

1.2.0's contextId rejection is directly relevant — it is the same class as Hermes' per-context FIFO, which exists so "concurrent same-context requests can't cross-talk."

⚠️ This sharpens the conflict, it does not resolve it

OptionNow
Adopt Hermes' A2A plugin0 dependency; live; spec-correct; but it is Hermes' own JSONRPC binding — no a2a-sdk
Adopt a2a-sdk 1.2.2the official SDK; REST + gRPC too; multi-replica; but duplicates a working implementation and adds a dependency

And note what 1.2.2 offers that the Hermes plugin does not: gRPC and HTTP+JSON bindings, multi-replica cluster mode. If V3 ever wants a transport other than JSON-RPC, or more than one replica, that is the SDK's advantage.

Still Sol's lane. My recommendation stands — but the case for the SDK is stronger than it was an hour ago, and I would rather say so than defend my first answer.


PART 3 — The plan for SolOS V3

8 stages, 3 arcs. Keeps the spine; adopts essences; every stage exits on a live probe. Full detail: 06-implementation/PLAN.md.

The three arcs

ArcStagesEstablishes
A — Foundation0 · 1the root, and the one source of every fact
B — The spine2 · 3A2A transport, and the task contract
C — The capabilities4 · 5 · 6 · 7skills, tools, memory, cost, the executor

The stages, and what changed after the Hermes study

StageDeliverableStatus after Hermes
0 — root + the provercore/config/paths.py (no V2 fallback) · a probe harness that records evidence · a built-never-wired detectorUNCHANGED — still first. Hermes has no equivalent
1 — the registryagents.yaml as THE source; every projection derived; drift test per projectionUNCHANGED — still ours. Hermes has no single-source registry
2 — A2A transportthe spine, spec-provenCHANGED → adopt. Hermes ships it live. ⚠️ SDK 1.2.2 vs the plugin — Sol's call
3 — task contractstates + wire mapping + the stuck ruleCHANGED → choose. Three numbers exist (300 s / 60 s / 3600 s)
4 — skills + toolsload model, tool permissionsCHANGED → adopt. Progressive disclosure + curator exist
5 — memorythe memory modelCHANGED → adopt. Two-tier + provider ABC exist. Owner still needs a ruling
6 — cost + retentionGO/ZEN ledger; retention as an enforced routing inputUNCHANGED — still ours. Hermes has no GO/ZEN
7 — the executorHarnessDefinition, run-scoped credential, live steeringUNCHANGED — still ours, now over Hermes' own harness pattern

The essence ledger — 13 adopted, each assigned a stage

#EssenceFromStage
E1Skills: keyword search → ≤5 as metadata → content only on loadMoyai + Hermes4
E2Live steering — a correction reaches an agent while it worksMoyai3 · 7
E3Cost ledger at the boundary — "a request limit is not a cost limit"Moyai6
E4HarnessDefinition(...)Moyai7
E5Run-scoped credential — keys stay at the relayMoyai7
E6Checkpoint boundary; interruption records whyMoyai3
E7A second memory mechanismMoyai5
E8"Project runtime configuration is untrusted"Moyai0 · 7
E9Refuse to start if the tools did not loadMoyai0 · 4
E10Stop a real task mid-flight, verify what remainsMoyai3
E11protocolVersion pinned per agentLiteLLM + Hermes2
E12Trace-id threadingLiteLLM6
E13Validated profiles; unknown field = errorLiteAgents1

And now a 14th, from Hermes itself:

#EssenceFromStage
E14The honest scope note — "tasks/cancel cannot abort the live session's in-flight turn"Hermesevery stage

Why this order

Stage 0  root + the prover        ← nothing can be trusted before it
Stage 1  the registry             ← nothing is safe before it (V2's worst live defect)
Stage 2  A2A transport            ← the interface; task states map onto it
Stage 3  the task contract        ← makes follow-up possible
   4 / 5 / 6                      ← independent; parallel across lanes
Stage 7  the executor             ← needs 3 and 1

Stages 4, 5 and 6 are independent and can run in parallel. Nothing after Stage 0 is safe before Stage 1.

What the plan does not do

  • It writes no code. Every stage is a design until its proof runs.
  • It does not re-plan the spine. A2A, the registry, .solos/, GO/ZEN and the 11-agent organisation are your rulings and are assumed.
  • It does not fork. 14 essences adopted as patterns and specifications, in our own lanes.
  • It claims no stage is done. A phase is done when its proof runs — not when the code is written, and not when a test is green.

Still needing a ruling

#QuestionMy recommendation
D1–D5the five in OPEN-DECISIONS.mdthe plan assumes each recommendation
1Stage 5's owner (memory)Min, with Sol owning the proof
2a2a-sdk 1.2.2, or Hermes' plugin?Sol's call — the SDK case is stronger now (gRPC, REST, multi-replica)
3Does V3 get its own repo?yes — solos2 is 735 MB of V2 history
4Who owns the V3 build?Sol owns engineering; Min coordinates
5spec/ — 18 MB, untrackedtrack it, or one git clean loses it

Not established

  • The A2A endpoint IS live and WAS probed (card, both dialects). No task has been sent — the task lifecycle, store and streaming path are read from source.
  • a2a-sdk 1.2.2 has not been installed or run. Version and changelog verified from PyPI, the repo tags and the changelog.
  • kanban has not been run.
  • The Hermes plugin's security controls were read, not tested.
  • No probe was run against the SDK. The SDK-vs-plugin decision rests on documented capability, not measurement.
Copyright © 2026