Agentic UI: Add Anthropic API key form to AI settings - #4503
Conversation
📊 Performance Test ResultsComparing a5f9498 vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
bcotrim
left a comment
There was a problem hiding this comment.
Some initial thoughts after a first review and tests:
-
The app shouldn't write to
cli.json. Let's either moveanthropicApiKeyandaiProvidertoshared.json, or add getters and setters as CLI operations. I'd sayshared.jsonis the easiest for now — it's already the layer for Desktop↔CLI state, and it's where the auth token lives. -
Let's make the error layout consistent with the rest of the app. (example from the create site form)
…y-settings # Conflicts: # apps/cli/ai/providers.ts # packages/common/ai/anthropic-key.ts
|
Thanks for the feedback. I changed the code to save the anthropic API key in shared.json and the error style to match existing inputs. @bcotrim , I would appreciate another review. Thanks! change-error-color.mp4 |
| }; | ||
|
|
||
| // AI provider settings live in shared.json (they used to target cli.json). | ||
| if ( typeof oldData.aiProvider === 'string' ) { |
There was a problem hiding this comment.
I don't think we should change this migration. It's the move from the old appdata-v1.json to the split configs, so it only runs for pre-split users — it would miss every user already on `cli.json.
Let's add a new migration under apps/cli/migrations/ instead that copies aiProvider and anthropicApiKey into shared.json and then removes them from cli.json.
There was a problem hiding this comment.
thanks for the suggestion!
…y-settings # Conflicts: # apps/cli/lib/cli-config/core.ts
…y-settings # Conflicts: # apps/cli/commands/ai/index.ts # apps/studio/src/modules/user-settings/lib/ipc-handlers.ts # apps/studio/src/modules/user-settings/lib/tests/settings-tracks.test.ts # apps/studio/src/preload.ts # apps/ui/src/components/settings-view/studio-code-panel.tsx # docs/design-docs/analytics-tracks.md # packages/common/lib/record-tracks-event.ts
…y-settings # Conflicts: # apps/local/src/index.ts # apps/ui/src/ui-classic/components/session-view/composer/index.tsx
|
@bcotrim , @wojtekn , I added tracks and added the migration for aiProvider and anthropicApiKey in the right place. 75312ff#diff-cf956473de32305a64e2d8b454483a4178cadcf7a68e6c70d1cee0795ba631e1 Could you review it again? Thx! |
bcotrim
left a comment
There was a problem hiding this comment.
After running some more tests I noticed another behavior:
Switching the Anthropic API key on/off only affects new sessions — existing ones keep the provider they were already using. That makes sense to me, but there's no way to tell which provider a chat is on.
It's not only a missing indicator either: the model dropdown filters by the global setting rather than the session's, so an existing WordPress.com session shows only Anthropic models and hides GPT 5.6 Sol, which it can still use.
We can start with something simple, like a label next to the model dropdown, and revisit later. What do you think?
bcotrim
left a comment
There was a problem hiding this comment.
After running some more tests I noticed another behavior:
Switching the Anthropic API key on/off only affects new sessions — existing ones keep the provider they were already using. That makes sense to me, but there's no way to tell which provider a chat is on.
It's not only a missing indicator either: the model dropdown filters by the global setting rather than the session's, so an existing WordPress.com session shows only Anthropic models and hides GPT 5.6 Sol, which it can still use.
We can start with something simple, like a label next to the model dropdown, and revisit later. What do you think?
bcotrim
left a comment
There was a problem hiding this comment.
After running some more tests I noticed another behavior:
Switching the Anthropic API key on/off only affects new sessions — existing ones keep the provider they were already using. That makes sense to me, but there's no way to tell which provider a chat is on.
It's not only a missing indicator either: the model dropdown filters by the global setting rather than the session's, so an existing WordPress.com session shows only Anthropic models and hides GPT 5.6 Sol, which it can still use.
We can start with something simple, like a label next to the model dropdown, and revisit later. What do you think?
|
Thanks for pointing that out @bcotrim . Initially I wanted to keep that out of scope of this PR, but I agree that we need some visual indicator. I think we could add the dropdown for users to pick the provider if the API key is saved so they can choose per conversation, I'll create a separate PR for that. provider-dropdown.mp4 |
|
I'll add the provider in the same dropdown as a follow-up. Great suggestion! |



Related issues
validateAnthropicApiKey), now merged.How AI was used in this PR
Proposed Changes
Studio's agentic UI always routes chat through the WordPress.com AI service. This PR lets users bring their own Anthropic API key instead:
studio ui) and the desktop app's agentic UI. A toggle picks the provider and a field below it holds the key. The key is write-only: the renderer only ever receives a truncated preview (sk-ant-api03-6Ic...lgAA), never the key itself.~/.studio/shared.json(the Desktop↔CLI shared config, next to the WordPress.com auth token), so the CLI, browser UI, and desktop stay in sync. Reads fall back to the legacycli.jsonlocation, and a new CLI migration (apps/cli/migrations/08-move-ai-settings-to-shared.ts) movesaiProvider/anthropicApiKeyover and strips them fromcli.jsonon first run.studio_setting_ai_provider_change, is emitted from the desktop settings handlers when the provider or key presence actually changes (provider,has_anthropic_api_key,surface— the key itself is never sent). Documented indocs/design-docs/analytics-tracks.md.packages/common/ai/settings-store.ts) tolerates unknownaiProvidervalues by falling back to WordPress.com instead of failing, and preserves unrelated config fields untouched.Scope notes for reviewers:
studio uiwrites these settings throughapps/local, which has no Tracks emitter, so those changes go uncounted for now (STU-2247).agenticRequiresAuth) is a product decision and intentionally untouched.Testing Instructions
Browser UI
npm start, open the Agentic UI1234). Shortly after you stop typing, "Anthropic rejected this API key. Check the key and try again." appears with a red border on the field, nothing is written to~/.studio/shared.json, and the toggle stays disabled.~/.studio/shared.jsonhas"aiProvider": "anthropic-api-key"plus the key. Reload the page — the field shows the truncated key as its placeholder.shared.jsonresets to"aiProvider": "wpcom"and the picker offers all models again. Clear the key field: the key is removed fromshared.json.PUT /api/ai-settingsstores the key;PUT /api/ai-settings/providerwithanthropic-api-keyanswers 400 when the key is rejected.Tracks Desktop
npm start(full restart required — new main-process IPC handlers).~/.studio/shared.jsonis used, so a key saved in the desktop app is also active forstudio uiand the CLI.STUDIO_DEBUG_TRACKS=1, changing the provider or key logs astudio_setting_ai_provider_changeevent carrying onlyprovider,has_anthropic_api_key, andsurface.Migration from an earlier build
"aiProvider": "anthropic-api-key"and an"anthropicApiKey"to~/.studio/cli.jsonand remove both from~/.studio/shared.json.node apps/cli/dist/cli/main.mjs site list): both fields move toshared.jsonand disappear fromcli.json. Values already present inshared.jsonare kept.add-antrhopic-api-key.mp4
Pre-merge Checklist