Mailbox identity observability + Claude Desktop onboarding docs
Context
Two friction points surfaced during the 2026-04-22 A2A handshake bootstrapping session that neither block Phase 4 work (unlike #10174) nor fit cleanly as subs of existing tickets, but materially improve the next agent's experience. Aggregated here to trade review throughput for speed of delivery.
The Problem
Friction 1 — Silent identity-binding failures. healthcheck currently returns {status: 'healthy', ...} even when StdioIdentityResolver bound no agent identity AND the AgentIdentity graph node lookup failed. The mailbox and permission subsystems then throw "Cannot <op>: no agent identity context bound" on every call. Diagnosing the chain today requires reading StdioIdentityResolver.mjs → running ps -E | grep NEO_AGENT_IDENTITY → querying seedAgentIdentities.mjs state manually. One MCP tool call should surface all of it.
Friction 2 — Missing Claude Desktop setup docs. .github/AI_QUICK_START.md currently documents Option A (Gemini CLI) and Option B (Antigravity OS). The Claude Desktop harness — which now embeds Claude Code — is absent. Its MCP config lives at ~/Library/Application Support/Claude/claude_desktop_config.json, a path that is neither obvious nor documented anywhere in the repo. The empirical bootstrap also exposed two more gotchas worth capturing: NEO_AGENT_IDENTITY must live in the per-server env block (not shell export), and for multi-harness dev boxes the .neo-ai-data folder must be unified across checkouts (symlink is the current tactical convention).
The Architectural Reality
Friction 1:
ai/mcp/server/memory-core/Server.mjs (lines 226-238, logIdentityStatus) — already logs the identity state to stdout at boot. Surface the same shape in the healthcheck tool response.
ai/mcp/server/memory-core/Server.mjs (healthcheckHandler — locate) — add an identity block alongside session, database, features. Non-fatal: unbound identity must NOT flip status: 'healthy' → 'unhealthy'. The mailbox is an optional feature; unbound is a valid single-tenant mode.
Friction 2:
.github/AI_QUICK_START.md §4 "Choosing Your Agent Environment" — add Option C: Claude Desktop (Claude Code embedded).
.github/AI_QUICK_START.md §5 "Understanding the Configuration Files" — add "Core Configuration (Claude Desktop)" subsection with the claude_desktop_config.json shape including the NEO_AGENT_IDENTITY env slot per MCP server.
.github/AI_QUICK_START.md — add a short section on the shared .neo-ai-data convention for multi-harness dev boxes (symlink pattern from antigravity → github checkout, rationale: unified SQLite graph substrate).
The Fix
healthcheck tool response gains identity: {source, bound, nodeId} block.
source: 'env-var' | 'gh-cli' | 'oidc' | 'unresolved'
bound: boolean — true iff the resolved login matched a seeded AgentIdentity graph node
nodeId: the bound @login node ID, or null
status stays 'healthy' regardless of bound — this is observability, not a gate
AI_QUICK_START.md updated:
- §4: Option C Claude Desktop added alongside Gemini CLI / Antigravity
- §5: New "Core Configuration (Claude Desktop)" subsection with the
claude_desktop_config.json shape example (memory-core + the other three Neo MCP servers, with NEO_AGENT_IDENTITY shown in the memory-core env)
- New subsection: "Multi-harness dev: unifying
.neo-ai-data" — documents the symlink convention (ln -s <primary>/.neo-ai-data <secondary>/.neo-ai-data), the rationale (shared SQLite graph → A2A mailbox works across harnesses), and the better-sqlite3 WAL-mode concurrency note (safe for multiple reader + serialized writer processes)
- Restart gotcha noted once: MCP config changes require a FULL harness quit (⌘Q on macOS), not just a window close
Acceptance Criteria
Out of Scope
- Auto-seeding identity nodes at memory-core boot (security concern: would mask misconfiguration; agents should fail loud on first mailbox op instead)
- Health-state degradation based on
identity.bound
- OIDC-source identity state (SSE transport) — tested path exists per
#10000; this ticket adds the stdio observability that matches
- Documentation for the Antigravity-side mirror of
.neo-ai-data — the current symlink convention is sufficient tactical guidance; architectural unification belongs to #9999
Avoided Traps
- "Make
healthcheck return status: unhealthy when unbound." Rejected — mailbox is an optional feature; single-tenant stdio-mode without a bound identity is a valid and supported configuration. Conflating "mailbox accessible" with "healthy" would break all human-dev workflows that have gh authenticated but no NEO_AGENT_IDENTITY pin.
- "Document claude_desktop_config.json in the
.claude/ directory so it sits next to the config it shadows." Rejected — .claude/settings.json is a repo-tracked Claude Code convention file that doesn't own MCP servers on macOS Claude Desktop. Mixing the documentation across both locations introduces the exact ambiguity that cost this session two restarts to diagnose. AI_QUICK_START.md is the single source of truth for all harness setup; Claude Desktop belongs there alongside Gemini CLI and Antigravity.
- "File the symlink convention as a separate ticket." Rejected — the convention only exists because of the mailbox bootstrap pain in this same session, and its docs-home is identical. Aggregated for throughput.
Related
- Parent:
#10139 Mailbox A2A primitive (epic; both concerns emerged from mailbox bootstrapping UX)
- Builds on:
#10145 (identity substrate that this observability surfaces), #10144 (AgentIdentity seed convention)
- Sibling:
#10174 (mailbox runtime-correctness fix; this ticket is the observability/docs dual)
- Potentially supersedes informal troubleshooting in
learn/agentos/tooling/MemoryCoreMcpAuth.md §Troubleshooting
Origin Session ID: d907e342-28fc-4eb6-8c51-355772dbfb44
Mailbox identity observability + Claude Desktop onboarding docs
Context
Two friction points surfaced during the 2026-04-22 A2A handshake bootstrapping session that neither block Phase 4 work (unlike #10174) nor fit cleanly as subs of existing tickets, but materially improve the next agent's experience. Aggregated here to trade review throughput for speed of delivery.
The Problem
Friction 1 — Silent identity-binding failures.
healthcheckcurrently returns{status: 'healthy', ...}even whenStdioIdentityResolverbound no agent identity AND the AgentIdentity graph node lookup failed. The mailbox and permission subsystems then throw"Cannot <op>: no agent identity context bound"on every call. Diagnosing the chain today requires readingStdioIdentityResolver.mjs→ runningps -E | grep NEO_AGENT_IDENTITY→ queryingseedAgentIdentities.mjsstate manually. One MCP tool call should surface all of it.Friction 2 — Missing Claude Desktop setup docs.
.github/AI_QUICK_START.mdcurrently documents Option A (Gemini CLI) and Option B (Antigravity OS). The Claude Desktop harness — which now embeds Claude Code — is absent. Its MCP config lives at~/Library/Application Support/Claude/claude_desktop_config.json, a path that is neither obvious nor documented anywhere in the repo. The empirical bootstrap also exposed two more gotchas worth capturing:NEO_AGENT_IDENTITYmust live in the per-serverenvblock (not shell export), and for multi-harness dev boxes the.neo-ai-datafolder must be unified across checkouts (symlink is the current tactical convention).The Architectural Reality
Friction 1:
ai/mcp/server/memory-core/Server.mjs(lines 226-238,logIdentityStatus) — already logs the identity state to stdout at boot. Surface the same shape in the healthcheck tool response.ai/mcp/server/memory-core/Server.mjs(healthcheckHandler— locate) — add anidentityblock alongsidesession,database,features. Non-fatal: unbound identity must NOT flipstatus: 'healthy' → 'unhealthy'. The mailbox is an optional feature; unbound is a valid single-tenant mode.Friction 2:
.github/AI_QUICK_START.md§4 "Choosing Your Agent Environment" — add Option C: Claude Desktop (Claude Code embedded)..github/AI_QUICK_START.md§5 "Understanding the Configuration Files" — add "Core Configuration (Claude Desktop)" subsection with theclaude_desktop_config.jsonshape including theNEO_AGENT_IDENTITYenv slot per MCP server..github/AI_QUICK_START.md— add a short section on the shared.neo-ai-dataconvention for multi-harness dev boxes (symlink pattern from antigravity → github checkout, rationale: unified SQLite graph substrate).The Fix
healthchecktool response gainsidentity: {source, bound, nodeId}block.source:'env-var' | 'gh-cli' | 'oidc' | 'unresolved'bound: boolean —trueiff the resolved login matched a seeded AgentIdentity graph nodenodeId: the bound@loginnode ID, ornullstatusstays'healthy'regardless ofbound— this is observability, not a gateAI_QUICK_START.mdupdated:claude_desktop_config.jsonshape example (memory-core + the other three Neo MCP servers, withNEO_AGENT_IDENTITYshown in the memory-core env).neo-ai-data" — documents the symlink convention (ln -s <primary>/.neo-ai-data <secondary>/.neo-ai-data), the rationale (shared SQLite graph → A2A mailbox works across harnesses), and thebetter-sqlite3WAL-mode concurrency note (safe for multiple reader + serialized writer processes)Acceptance Criteria
healthcheckresponse includesidentity: {source, bound, nodeId}identity.bound === false,identity.nodeId === null,status === 'healthy'(backward compatible)identity.source === 'env-var',identity.bound === true,identity.nodeId === '@<login>'AI_QUICK_START.md§4 lists Claude Desktop as Option CAI_QUICK_START.md§5 includesclaude_desktop_config.jsonexample withNEO_AGENT_IDENTITYshown in the memory-coreenvblockAI_QUICK_START.mddocuments the.neo-ai-datasymlink conventionlearn/agentos/tooling/MemoryCoreMcpAuth.mdcross-references the new healthcheck shape in its Troubleshooting section (replacing the "Check startup logs for[neo-memory-core MCP] Identity: ..." guidance with "Callhealthcheckand inspectidentity.*")Out of Scope
identity.bound#10000; this ticket adds the stdio observability that matches.neo-ai-data— the current symlink convention is sufficient tactical guidance; architectural unification belongs to#9999Avoided Traps
healthcheckreturnstatus: unhealthywhen unbound." Rejected — mailbox is an optional feature; single-tenant stdio-mode without a bound identity is a valid and supported configuration. Conflating "mailbox accessible" with "healthy" would break all human-dev workflows that haveghauthenticated but noNEO_AGENT_IDENTITYpin..claude/directory so it sits next to the config it shadows." Rejected —.claude/settings.jsonis a repo-tracked Claude Code convention file that doesn't own MCP servers on macOS Claude Desktop. Mixing the documentation across both locations introduces the exact ambiguity that cost this session two restarts to diagnose.AI_QUICK_START.mdis the single source of truth for all harness setup; Claude Desktop belongs there alongside Gemini CLI and Antigravity.Related
#10139Mailbox A2A primitive (epic; both concerns emerged from mailbox bootstrapping UX)#10145(identity substrate that this observability surfaces),#10144(AgentIdentity seed convention)#10174(mailbox runtime-correctness fix; this ticket is the observability/docs dual)learn/agentos/tooling/MemoryCoreMcpAuth.md§TroubleshootingOrigin Session ID:
d907e342-28fc-4eb6-8c51-355772dbfb44