diff --git a/cli/node/src/commands/agent-mode.ts b/cli/node/src/commands/agent-mode.ts index c7090d05b..727f88181 100644 --- a/cli/node/src/commands/agent-mode.ts +++ b/cli/node/src/commands/agent-mode.ts @@ -26,7 +26,10 @@ export interface BootstrapEnvelope { export async function bootstrapViaBackend( config: Mem0Config, - { source }: { source?: string | null } = {}, + { + source, + agentCaller, + }: { source?: string | null; agentCaller?: string | null } = {}, ): Promise { const baseUrl = (config.platform.baseUrl || "https://api.mem0.ai").replace( /\/+$/, @@ -34,6 +37,7 @@ export async function bootstrapViaBackend( ); const body: Record = {}; if (source) body.source = source; + if (agentCaller) body.agent_caller = agentCaller; let resp: Response; try { @@ -89,6 +93,7 @@ export async function bootstrapViaBackend( config.platform.baseUrl = baseUrl; config.platform.agentMode = true; config.platform.createdVia = "agent_mode"; + config.platform.agentCaller = agentCaller ?? ""; config.platform.claimedAt = ""; config.platform.defaultUserId = envelope.default_user_id; // Adopt the slug-derived user_id as the default scope for memory ops. diff --git a/cli/node/src/commands/init.ts b/cli/node/src/commands/init.ts index d96d55960..da5ec95b8 100644 --- a/cli/node/src/commands/init.ts +++ b/cli/node/src/commands/init.ts @@ -367,7 +367,10 @@ export async function runInit( return; } // Rule 3: mint a fresh shadow (no valid key to reuse). - await bootstrapViaBackend(config, { source: opts.source ?? null }); + await bootstrapViaBackend(config, { + source: opts.source ?? null, + agentCaller: detectAgentCaller(), + }); fireInit("agent"); return; } diff --git a/cli/node/src/config.ts b/cli/node/src/config.ts index 5077d6a61..13b8ba227 100644 --- a/cli/node/src/config.ts +++ b/cli/node/src/config.ts @@ -24,6 +24,7 @@ export interface PlatformConfig { // Agent Mode (unclaimed-shadow signup) agentMode: boolean; // true while the key is an unclaimed agent-mode key createdVia: string; // "agent_mode" | "email" | "api_key" | "existing_key" + agentCaller: string; // canonical agent name when createdVia === "agent_mode" (e.g. "claude-code") claimedAt: string; // ISO timestamp once the agent has been claimed defaultUserId: string; // `user_` returned by bootstrap; auto-default scope } @@ -61,6 +62,7 @@ export function createDefaultConfig(): Mem0Config { userEmail: "", agentMode: false, createdVia: "", + agentCaller: "", claimedAt: "", defaultUserId: "", }, @@ -90,6 +92,7 @@ export function loadConfig(): Mem0Config { config.platform.userEmail = plat.user_email ?? ""; config.platform.agentMode = Boolean(plat.agent_mode ?? false); config.platform.createdVia = plat.created_via ?? ""; + config.platform.agentCaller = plat.agent_caller ?? ""; config.platform.claimedAt = plat.claimed_at ?? ""; config.platform.defaultUserId = plat.default_user_id ?? ""; @@ -133,6 +136,7 @@ export function saveConfig(config: Mem0Config): void { user_email: config.platform.userEmail, agent_mode: config.platform.agentMode, created_via: config.platform.createdVia, + agent_caller: config.platform.agentCaller, claimed_at: config.platform.claimedAt, default_user_id: config.platform.defaultUserId, }, diff --git a/cli/python/src/mem0_cli/commands/agent_mode_cmd.py b/cli/python/src/mem0_cli/commands/agent_mode_cmd.py index e28ba7faf..a6f41ff5a 100644 --- a/cli/python/src/mem0_cli/commands/agent_mode_cmd.py +++ b/cli/python/src/mem0_cli/commands/agent_mode_cmd.py @@ -32,16 +32,25 @@ def bootstrap_via_backend( config: Mem0Config, *, source: str | None = None, + agent_caller: str | None = None, ) -> None: """POST /api/v1/auth/agent_mode/ and mutate config in place. - Returns nothing — the caller saves the config and prints follow-up messages. + Args: + config: Mem0Config mutated in place with the new platform values. + source: ``--source`` flag passthrough (analytics tag, free-form). + agent_caller: Canonical agent name detected from env vars + (claude-code, cursor, ...). Persisted on the backend APIKey and + saved into ``platform.agent_caller`` for local introspection. + Raises typer.Exit(1) on failure. """ base_url = (config.platform.base_url or "https://api.mem0.ai").rstrip("/") body: dict[str, Any] = {} if source: body["source"] = source + if agent_caller: + body["agent_caller"] = agent_caller try: with httpx.Client(timeout=30.0) as client: @@ -84,6 +93,7 @@ def bootstrap_via_backend( config.platform.base_url = base_url config.platform.agent_mode = True config.platform.created_via = "agent_mode" + config.platform.agent_caller = agent_caller or "" config.platform.claimed_at = "" config.platform.default_user_id = envelope["default_user_id"] # Adopt the slug-derived user_id as the default scope for memory ops. diff --git a/cli/python/src/mem0_cli/commands/init_cmd.py b/cli/python/src/mem0_cli/commands/init_cmd.py index f13f8d3fe..1de422439 100644 --- a/cli/python/src/mem0_cli/commands/init_cmd.py +++ b/cli/python/src/mem0_cli/commands/init_cmd.py @@ -295,7 +295,7 @@ def run_init( _fire_init("existing_key") return # Rule 3: mint a fresh shadow (no valid key to reuse). - bootstrap_via_backend(config, source=source) + bootstrap_via_backend(config, source=source, agent_caller=detect_agent_caller()) _fire_init("agent") return diff --git a/cli/python/src/mem0_cli/config.py b/cli/python/src/mem0_cli/config.py index a8f1285df..9abe4bde3 100644 --- a/cli/python/src/mem0_cli/config.py +++ b/cli/python/src/mem0_cli/config.py @@ -31,6 +31,7 @@ class PlatformConfig: # Agent Mode (unclaimed-shadow signup) agent_mode: bool = False # True while the key is an unclaimed agent-mode key created_via: str = "" # "agent_mode" | "email" | "api_key" | "existing_key" + agent_caller: str = "" # canonical agent name when created_via == "agent_mode" (e.g. "claude-code") claimed_at: str = "" # ISO timestamp once the agent has been claimed by a human default_user_id: str = "" # `user_` returned by bootstrap; used as auto-default @@ -90,6 +91,7 @@ def load_config() -> Mem0Config: config.platform.user_email = plat.get("user_email", "") config.platform.agent_mode = bool(plat.get("agent_mode", False)) config.platform.created_via = plat.get("created_via", "") + config.platform.agent_caller = plat.get("agent_caller", "") config.platform.claimed_at = plat.get("claimed_at", "") config.platform.default_user_id = plat.get("default_user_id", "") @@ -147,6 +149,7 @@ def save_config(config: Mem0Config) -> None: "user_email": config.platform.user_email, "agent_mode": config.platform.agent_mode, "created_via": config.platform.created_via, + "agent_caller": config.platform.agent_caller, "claimed_at": config.platform.claimed_at, "default_user_id": config.platform.default_user_id, },