PR review surfaced a data-loss path: pingKey returned False on ANY exception,
so a VPN flap or DNS hiccup made Rules 1/2 (reuse existing valid key) fall
through to Rule 3 (mint new shadow), silently rotating the user's API key
and rewriting plugin-sync targets (~/.claude/settings.json, .zshrc).
Now pingKey returns False ONLY on a definitive auth failure (HTTP 401/403).
Network errors, timeouts, and 5xx responses return True so the existing key
is preferred over re-minting. Mirror change in both Python and Node.
Additional fixes from the same review pass:
- --agent-caller is now PATCHed to the backend when supplied on a Rule 1
or Rule 2 reuse path (previously silently dropped). Best-effort —
failures don't break reuse.
- bootstrap_via_backend / bootstrapViaBackend renames the `body` local on
the error path to `err_body` (no longer shadows the request payload).
Same rename in the claim flow.
- Bootstrap envelope is now validated for non-empty api_key +
default_user_id before mutation — defends against partial backend
responses silently persisting null/undefined into typed string fields.
- Stale docstrings in agent_detect.{py,ts} and bootstrap_via_backend no
longer claim env-var sniffing fills `agent_caller`; the field is
self-declared via --agent-caller only.
Tests (new file mirrored across runtimes):
- test_init_internals.py / init-internals.test.ts
- pingKey: 200/401/403/5xx/connect-error/timeout matrix
- plugin_sync.updateShellRc: trailing-newline preservation, no-create,
surrounding-content preservation, idempotency, missing-file no-op
- plugin_sync.updateClaudeSettings: no env-block creation, no
MEM0_API_KEY insertion into existing env, idempotency, malformed JSON
no-op
- Python only: bootstrap 403 "permission" → daily-limit translation
Python: 161 tests pass. Node: 112 tests pass. ruff + biome clean.
CLI now consumes the unified mem0_notice surface that the platform side
emits for unclaimed Agent Mode keys. The notice is a directive to the
LLM agent reading the output, with a verbatim sentence to relay to the
human owner. Two presentation paths:
- Human/text output: yellow stderr banner after the primary output,
once per command. Skipped in agent mode (the JSON envelope carries
it instead, so no duplication).
- JSON/agent output (--json/--agent): folded into the envelope as
"mem0_notice" so an agent parsing the output sees it without
inspecting HTTP headers.
CLI changes (Python + Node, kept in lockstep):
- state.{ts,py}: captureNotice / takeNotice helpers — last-write-wins
stash so multi-request commands fire the notice exactly once.
- backend/platform.{ts,py}: _request extracts notice from response
bodies (top-level dict or list[0]) with header fallback, strips
from downstream payload, captures for end-of-command surfacing.
- output.{ts,py}: JSON envelope formatters fold in any pending notice.
- index.ts / app.py: entrypoint surfaces notice on exit when not in
agent mode.
- commands/agent-mode.{ts,py}: init success path prints the platform's
notice verbatim (fallback to dim claim-command line if a stale
backend doesn't return it).
Init-flag handling fix: the Python argv preprocessor was stripping
--agent from sys.argv unconditionally as the global JSON-output alias.
That swallowed `mem0 init --agent` (where --agent is a subcommand flag
for unattended bootstrap). Now preserved when "init" is in argv.
Parity tests: cli/python/tests/test_agent_mode.py and
cli/node/tests/agent-mode.test.ts — 7 tests each, kept in sync.
cli-spec.json updated: init now lists --agent and --source.
Docs:
- README.md: Agent Mode promo at top of Quickstart.
- docs/llms.txt: fast-path block for AI agents reading the docs.
- skills/mem0/SKILL.md, skills/mem0-cli/SKILL.md,
skills/mem0-integrate/SKILL.md, mem0-plugin/skills/mem0/SKILL.md:
autonomous-setup section + fallback hints.
- mem0-plugin/README.md, openclaw/README.md: "Quick path for agents"
blocks above the human Quick Start.