7.4 KiB
Enhanced Existing Agent Wizard Flow
Problem
When choosing "existing agent" in the wizard, the current flow:
- Asks for nsec
- Recovers kind 10002 relay list from Nostr
- 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()— 22 lines, minimal recoveryrecover_existing_config_from_nostr()— only recovers kind 10002 relays- Returns
SETUP_WIZARD_RC_EXISTING(2) which does NOT setbootstrap_mode - In
main.c, existing agents skipreconcile_startup_events()unlessfirst_runis 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
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
- Init nostr handler with default relays
- Wait for relay connections
- Query kind 10002 for relay list — if not found, offer to create a new agent with this nsec (jump to
new_agent_flowwith keys pre-loaded, skipping identity step) - Cleanup and re-init with recovered relays
- Wait for relay connections on recovered relays
- Query kind 0 for agent profile — extract display_name/name
- Query kind 30078 d=llm_config — decrypt and parse LLM settings
- Query kind 30078 d=agent_config — decrypt and parse admin pubkey + DM protocol
- 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 becauserecover_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
-
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()— replicatesfetch_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
- Add
-
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
- Potentially expose
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()andprompt_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.