# Enhanced Existing Agent Wizard Flow ## Problem When choosing "existing agent" in the wizard, the current flow: 1. Asks for nsec 2. Recovers kind 10002 relay list from Nostr 3. Immediately boots the agent This is insufficient when installing an existing agent on a **new server** because: - You cannot review or change the admin pubkey - You cannot review or change the LLM provider/model/API key - You cannot install a systemd service with a dedicated user - You cannot see what config was recovered from Nostr - The agent name is not recovered from the kind 0 profile ## Current Code - [`existing_agent_flow()`](src/setup_wizard.c:1795) — 22 lines, minimal recovery - [`recover_existing_config_from_nostr()`](src/setup_wizard.c:792) — only recovers kind 10002 relays - Returns `SETUP_WIZARD_RC_EXISTING` (2) which does NOT set `bootstrap_mode` - In `main.c`, existing agents skip `reconcile_startup_events()` unless `first_run` is detected ## Data Available on Nostr for an Existing Agent | Data | Kind | Storage | Recovery Method | |------|------|---------|-----------------| | Relay list | 10002 | Public tags | `query_and_extract_kind10002_relays()` | | Agent profile/name | 0 | Public JSON content | Query kind 0 by agent pubkey | | LLM config | 30078 d=llm_config | NIP-44 encrypted to self | `fetch_self_config_plaintext()` | | Agent config - admin pubkey, DM protocol | 30078 d=agent_config | NIP-44 encrypted to self | `fetch_self_config_plaintext()` | | Default skill | 31124 d=didactyl-default | Public content | Query kind 31124 by agent pubkey | | Adoption list | 10123 | Public tags | Query kind 10123 by agent pubkey | ## Proposed Enhanced Flow ```mermaid flowchart TD A[Enter nsec] --> B[Connect to default relays] B --> C[Recover kind 10002 relay list] C --> D{Relay list found?} D -->|No| E{Offer to create new agent with this nsec} E -->|Yes| E2[Jump to new_agent_flow with nsec pre-loaded] E -->|No| E3[Return to main menu] D -->|Yes| F[Reconnect with recovered relays] F --> G[Recover all config from Nostr] G --> H[Display recovered config summary] H --> I{Review each setting} I -->|Keep all| J[Review summary + launch options] I -->|Change admin| K[Prompt new admin pubkey] I -->|Change LLM| L[Prompt LLM config] I -->|Change relays| M[Prompt relay config] K --> I L --> I M --> I J --> N{Launch option} N -->|Boot now| O[Return EXISTING] N -->|Install systemd| P[Install dedicated-user service] N -->|Quit| Q[Exit] ``` ### Step-by-step #### Step 1: Identity — Enter nsec Same as current. Derive keys from nsec. #### Step 2: Recovery — Connect and fetch config from Nostr 1. Init nostr handler with default relays 2. Wait for relay connections 3. Query kind 10002 for relay list — if not found, offer to create a new agent with this nsec (jump to `new_agent_flow` with keys pre-loaded, skipping identity step) 4. Cleanup and re-init with recovered relays 5. Wait for relay connections on recovered relays 6. Query kind 0 for agent profile — extract display_name/name 7. Query kind 30078 d=llm_config — decrypt and parse LLM settings 8. Query kind 30078 d=agent_config — decrypt and parse admin pubkey + DM protocol 9. Cleanup nostr handler #### Step 3: Review — Present recovered config Display all recovered values: ``` ┌─────────────────────────────────────────────┐ │ Existing Agent -- Recovered Configuration │ ├─────────────────────────────────────────────┤ │ Agent name: Simon │ │ Identity: b27072b7fc2edf45... │ │ Admin: a1b2c3d4e5f6... │ │ LLM Provider: ppq │ │ LLM Model: claude-haiku-4.5 │ │ LLM Base URL: https://api.ppq.ai │ │ LLM API Key: sk-...**** │ │ DM Protocol: nip04 │ │ Relays: 5 configured │ └─────────────────────────────────────────────┘ ``` Then offer a menu: ``` [a] change Admin pubkey [l] change LLM provider/model/key [r] change Relay configuration [c] continue with these settings [q] quit ``` Each change option reuses the existing prompt functions (`prompt_admin_pubkey`, `prompt_llm_config`, `prompt_relay_configuration`) but with context-appropriate headers. After any change, redisplay the summary and menu. #### Step 4: Launch — Boot or install systemd Same as the new-agent flow's final step: ``` [b] boot the agent now [i] install dedicated-user systemd service and boot [q] quit ``` The systemd install reuses `install_system_service_with_dedicated_user()`. ### Return Codes - If user chooses "boot now": return `SETUP_WIZARD_RC_EXISTING` (2) — same as current - If user chooses "install systemd": return `SETUP_WIZARD_RC_EXIT` (1) — agent runs as systemd service - If user changed config values: the `main()` flow should still work because `recover_missing_runtime_config_from_nostr()` at line 1108 will fill in any gaps, and the existing agent path at line 1163 loads system context from adopted skills ### Key Consideration: bootstrap_mode for changed configs If the user changes LLM or admin config in the wizard, those changes need to be persisted back to Nostr. Currently, `persist_runtime_config_to_nostr()` is only called when `bootstrap_mode || first_run`. **Solution**: When the existing-agent wizard detects that config was changed, return `SETUP_WIZARD_RC_BOOTSTRAP` (0) instead of `SETUP_WIZARD_RC_EXISTING` (2). This triggers the full reconcile path which persists the updated config. ## Files to Modify 1. **`src/setup_wizard.c`**: - Add `recover_full_config_from_nostr()` — fetches kind 0, kind 30078 llm_config, kind 30078 agent_config - Add `query_self_kind0_name()` — queries agent's own kind 0 profile for name - Add `fetch_and_decrypt_self_config()` — replicates `fetch_self_config_plaintext()` logic from main.c for use in wizard context - Rewrite `existing_agent_flow()` with the enhanced multi-step flow - Make `prompt_admin_pubkey()`, `prompt_llm_config()`, `prompt_relay_configuration()` accept a context string parameter for the page header, or add wrapper versions for the existing-agent context 2. **`src/main.c`**: - Potentially expose `fetch_self_config_plaintext()`, `apply_recalled_llm_config()`, `apply_recalled_agent_config()` as non-static, OR duplicate the logic in setup_wizard.c - Better approach: move these to a shared location or make them accessible via a header ## Implementation Notes - The wizard already calls `nostr_handler_init()` / `nostr_handler_cleanup()` for validation queries. The enhanced flow will do the same but with two init/cleanup cycles: first with default relays to get kind 10002, then with recovered relays to get everything else. - The `prompt_admin_pubkey()` and `prompt_llm_config()` functions currently have hardcoded step headers like "Step 3 of 7". These should be parameterized or have existing-agent variants. - The `fetch_self_config_plaintext()` function in main.c requires an active nostr handler. The wizard will need to have the handler initialized when calling it. - API key display should be masked — show only first 4 and last 4 characters.