LearnNewsExamplesServices
Frontmatter
id10349
titleSunset Protocol: self-DM handover for next-session boot pickup
stateClosed
labels
documentationenhancementaiarchitecture
assignees[]
createdAtApr 26, 2026, 1:49 AM
updatedAtJun 7, 2026, 7:21 PM
githubUrlhttps://github.com/neomjs/neo/issues/10349
authorneo-opus-ada
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 27, 2026, 2:01 AM

Sunset Protocol: self-DM handover for next-session boot pickup

Closed v13.0.0/archive-v13-0-0-chunk-6 documentationenhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on Apr 26, 2026, 1:49 AM

Context

The Sunset Protocol currently emits the end-of-session handover to three surfaces: GitHub issue comments (ticket-scoped), chat to the human commander (interactive), and Sandman memory persistence (vector-store). It pre-dates the A2A mailbox substrate (add_message / list_messages) and does not leverage it.

When session 48197e2e booted at 2026-04-25T23:26Z (consuming the prior session's b5a17132 handover), the Sunset Protocol's "future-self entry point" pointed at Sandman memory ID a745b31e-4d1b-421e-b046-03a21de94c35. get_message returned "Message not found: a745b31e-..." — a durability gap between the writing session's vector-store write and the reading session's vector-store read. Boot fell back to fetching the three carry-over tickets directly via get_local_issue_by_id, which worked but is a less direct substrate match for "general session-arc state" (vs ticket-scoped state).

The mailbox substrate (Nodes table in SQLite, surfaced via A2A graph topology with SENT_TO/SENT_BY edges) has stronger durability guarantees than the Chroma vector store. A self-DM via add_message(to: '<own-identity>', ...) written at sunset, read via list_messages at boot, closes the durability gap with a complementary lightweight bridge.

The change also progresses the broader wakeup-events goal (collaboration target with Gemini): validating the self-routing path of A2A (sender = receiver = same identity node) is a substrate-confidence dividend. Same identity binding, same SENT_TO/SENT_BY edge mechanics that wakeup events depend on.

The Problem

Three failure modes in the current Sunset Protocol:

  1. Sandman memory durability gap. Vector-store writes from session N may not be retrievable in session N+1 (collection rebuild, embedding-version mismatch, missing message ID, etc.). Empirically observed this session.
  2. Substrate redundancy without primary owner. GitHub issue comments are public + ticket-scoped; chat to human is human-mediated; Sandman memory is the intended cross-session bridge but has the durability gap. No single substrate cleanly owns "the next-session greeting from past-self."
  3. Identity self-sufficiency miss. Agents have stable identities (@neo-opus-ada, @neo-gemini-pro) but the protocol doesn't use the agent's own mailbox as a persistence substrate. "Get a heads-up from yesterday" via list_messages would immediately clarify "this is not a standalone session."

The Architectural Reality

Current state:

  • AGENTS.md §14 (A2A Contextual Bridge Protocol — End of Session Handoff) codifies the Origin Session ID embedding pattern. Three steps: horizon scan, telemetry payload, ingestion mandate.
  • AGENTS_STARTUP.md §6 (Memory Core check) covers boot Memory Core healthcheck + get_context_frontier() + get_all_summaries() + sandman_handoff.md parse.
  • A2A mailbox tools add_message / list_messages are operational (per ai/mcp/server/memory-core/openapi.yaml /mailbox/messages paths).
  • Healthcheck identity block surfaces identity.source (env-var | gh-cli | oidc | unresolved) and identity.bound — provides the gate for "is the agent's identity stable enough to write a self-DM."

What needs to change:

  • AGENTS.md §14 extended with a step: at session end, if identity is bound, send a handover self-DM via add_message(to: '<own-identity>', subject: 'Sunset Protocol Handover — session <ID>', taggedConcepts: ['sunset-protocol-handover'], originSessionId, ...).
  • AGENTS_STARTUP.md §6 extended with a step: at boot, after Memory Core healthcheck, call list_messages({status: 'unread'}) (or with taggedConcepts filter once supported) and parse messages tagged sunset-protocol-handover. Apply context, then mark_read.

The Fix

Phase 1 (this ticket's MVP scope):

  1. AGENTS.md §14 extension — add step "End-of-Session Self-DM":

    • Trigger condition: at sunset, if healthcheck() returns identity.bound: true.
    • Call add_message({to: '<own-identity>', subject, body, taggedConcepts: ['sunset-protocol-handover'], originSessionId}).
    • body mirrors the handover narrative posted to ticket comments — implementation guidance, mental-model state, carry-over tickets, pickup signal.
    • taggedConcepts MUST include sunset-protocol-handover for list_messages filtering.
    • originSessionId MUST be the sunsetting session ID.
    • Failure mode: if identity.bound: false or add_message errors, skip self-DM gracefully — GitHub comments + Sandman memory remain the canonical surfaces.
  2. AGENTS_STARTUP.md §6 extension — add step "Self-Handover Mailbox Check":

    • Placement: after Memory Core healthcheck + get_context_frontier() + get_all_summaries(), before the existing sandman_handoff.md parse.
    • Call list_messages({status: 'unread'}) (or with taggedConcepts filter once supported).
    • For each unread message tagged sunset-protocol-handover: parse body, apply context, optionally mark_read (or batch at end of boot).
    • Multiple stacked handovers (multi-session sunset without resume): read in chronological order; latest wins for state but earlier ones provide context drift.

Acceptance Criteria

  • AGENTS.md §14 extended with the End-of-Session Self-DM step (trigger condition, call shape, taggedConcepts mandate, identity-bound gate, failure mode).
  • AGENTS_STARTUP.md §6 extended with the Self-Handover Mailbox Check step (placement, call shape, parsing/marking semantics, multi-handover ordering).
  • Cross-references between AGENTS.md §14 and AGENTS_STARTUP.md §6 are bidirectional (each cites the other).
  • taggedConcepts: ['sunset-protocol-handover'] codified in both docs as the canonical retrieval key.
  • Identity-bound gate explicit in AGENTS.md §14 (skip self-DM if identity.source === 'unresolved').
  • Empirical anchor cited inline: session 48197e2e's get_message(a745b31e-...) "Message not found" failure as the durability-gap motivator.
  • Cross-flag #10347 dependency note: Antigravity-side intermittent SENT_TO cull means Gemini's resumes are at risk until that lands; Claude-side path is currently stable.
  • Optional: ripple check on pull-request and pr-review skills (likely no change — sunset is session-arc scope, not PR-cycle scope).

Out of Scope

  • Implementing taggedConcepts server-side filter on list_messages — parser-layer filtering is fine for MVP; server-side push-down is an optimization for later if message volume grows.
  • @self sentinel resolution in add_message — explicit identity is sufficient; sentinel sugar is premature.
  • Cross-agent (A → B) sunset handover — different shape; ticket comments + Origin Session ID already cover this surface.
  • Multi-handover consolidation / rollup — read-each-in-order is fine for MVP; only optimize if backlog grows large.
  • Sunset-protocol-as-skill graduation — currently codified inline in AGENTS.md; promotion to a .agent/skills/sunset-protocol/ Progressive Disclosure skill is a separate decision if the protocol grows beyond a few paragraphs.
  • Changes to Sandman memory write path — vector-store durability is a #9999 / #10030 concern; this ticket adds a complementary substrate, not a replacement.

Avoided Traps

  • "Replace Sandman memory with mailbox" framing — rejected. Sandman memory serves the Retrospective daemon (semantic search across the corpus); self-mailbox handover serves future-self only. Both substrates have distinct consumers; both stay.
  • "Broadcast handover to @AGENT:*" — rejected. Pollutes other agents' inboxes with another agent's session-arc state. Identity-scoped self-DM is correct routing.
  • "Always self-DM unconditionally" — rejected. If identity.source === 'unresolved' (single-tenant fallthrough or env-var missing), the self-DM has no durable destination. Identity-bound gate is mandatory.
  • "Skip GitHub ticket comments if self-DM is the new substrate" — rejected. GitHub comments serve human commanders + cross-agent handoff (next agent picking up the ticket); self-DM serves future-self only. Both surfaces have distinct consumers; both stay.
  • "Tag with session ID instead of taggedConcepts" — rejected. taggedConcepts: ['sunset-protocol-handover'] is the routing key; originSessionId provides per-message provenance. Two distinct fields, two distinct purposes.
  • "Inline a link to external state in body" — rejected. Body is rich markdown self-contained; don't link to state that may not be retrievable next session.

Related

  • AGENTS.md §14 — current End-of-Session protocol (this ticket extends it).
  • AGENTS_STARTUP.md §6 — current Memory Core boot check (this ticket extends it).
  • #9999 — Cloud-Native KB epic; addresses Sandman memory durability gap at substrate level. Complementary, not blocking.
  • #10030 — Native Edge Graph topology; same domain as Sandman memory.
  • #10347 — Antigravity-side intermittent SENT_TO cull; gates reliable mailbox routing for Gemini's resume path. Claude-side path is stable per empirical evidence.
  • #10341 (PR #10348) — pr-review §5.3 MCP-tool-description budget audit; tangentially related as both touch agent-facing infrastructure discipline.

Origin Session ID: 48197e2e-3e95-47eb-9eb8-bbb032948845

Retrieval Hint: query_raw_memories(query='sunset protocol self-DM mailbox handover boot pickup list_messages add_message taggedConcepts identity-bound')