LearnNewsExamplesServices
Frontmatter
id10176
titleMailbox identity observability + Claude Desktop onboarding docs
stateClosed
labels
documentationenhancementaiarchitecture
assigneesneo-opus-4-7
createdAtApr 22, 2026, 4:06 PM
updatedAtApr 23, 2026, 3:58 PM
githubUrlhttps://github.com/neomjs/neo/issues/10176
authorneo-opus-4-7
commentsCount0
parentIssue10139
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtApr 23, 2026, 3:56 PM

Mailbox identity observability + Claude Desktop onboarding docs

Closeddocumentationenhancementaiarchitecture
neo-opus-4-7
neo-opus-4-7 commented on Apr 22, 2026, 4:06 PM

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

  1. 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
  2. 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

  • healthcheck response includes identity: {source, bound, nodeId}
  • Response schema validation test pins the new shape
  • Unbound-identity case: identity.bound === false, identity.nodeId === null, status === 'healthy' (backward compatible)
  • Bound-identity case (env-var source): identity.source === 'env-var', identity.bound === true, identity.nodeId === '@<login>'
  • gh-cli fallback source path tested
  • AI_QUICK_START.md §4 lists Claude Desktop as Option C
  • AI_QUICK_START.md §5 includes claude_desktop_config.json example with NEO_AGENT_IDENTITY shown in the memory-core env block
  • AI_QUICK_START.md documents the .neo-ai-data symlink convention
  • Restart-gotcha (⌘Q, not window close) noted once in the setup flow
  • learn/agentos/tooling/MemoryCoreMcpAuth.md cross-references the new healthcheck shape in its Troubleshooting section (replacing the "Check startup logs for [neo-memory-core MCP] Identity: ..." guidance with "Call healthcheck and inspect identity.*")

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

tobiu referenced in commit 057130b - "feat(memory-core): healthcheck identity observability block (#10176) (#10239) on Apr 23, 2026, 3:56 PM
tobiu closed this issue on Apr 23, 2026, 3:56 PM
tobiu referenced in commit f70c48f - "feat(memory-core): surface effective chromadb topology in /health (#10127) (#10268) on Apr 24, 2026, 1:32 AM
tobiu referenced in commit 24fa125 - "feat(memory-core): surface active embedding provider in healthcheck (#10723) (#10767) on May 5, 2026, 9:00 PM