Add auth secret dropdown picker for non-Oz orchestration#10885
Conversation
Adds an 'API key' dropdown to the orchestration plan card and run-agents confirmation card, shown when execution mode is Cloud and the harness is non-Oz (Claude Code, Codex). Selecting a managed secret propagates it through RunAgentsRequest -> StartAgentExecutionMode::Remote -> launch_remote_child, where it is written to AgentConfigSnapshot.harness_auth_secrets so the cloud child agent gets the right credentials at startup. This unblocks multi-harness local->cloud orchestration after the team-scoped ANTHROPIC_API_KEY / OPENAI_API_KEY blanket env var was removed. Selection state is shared with cloud single-agent mode via CloudAgentSettings.last_selected_auth_secret (keyed per-harness), so picking a secret in either surface affects both. Key plumbing: - RunAgentsRequest and StartAgentExecutionMode::Remote gain a Rust-only harness_auth_secret_name / auth_secret_name field (not round-tripped through the proto). - Shared OrchestrationEditState, OrchestrationPickerHandles, and the OrchestrationControlAction trait gain auth_secret support. - New helpers in orchestration_controls.rs: should_show_auth_secret_picker, resolve_default_auth_secret_for_harness, populate_auth_secret_picker_for_harness, apply_auth_secret_change. - Subscribes to HarnessAvailabilityEvent::AuthSecretsLoaded so the picker re-renders after the lazy fetch completes. - update_request and try_auto_launch_on_stream_complete re-seed the secret from settings so a plan-card pick survives auto-launch when streaming wipes the field. No server or proto changes required \u2014 the existing SpawnAgent path already supports HarnessAuthSecrets. Co-Authored-By: Oz <oz-agent@warp.dev>
|
I'm starting a first review of this pull request. You can view the conversation on Warp. I completed the review and no human review was requested for this pull request. Comment Powered by Oz |
There was a problem hiding this comment.
Overview
This PR adds a managed API-key picker to the orchestration plan and run-agents confirmation surfaces, then threads the selected secret name through remote child-agent launch.
Concerns
- Approved-plan auto-launch can keep an existing auth secret after
override_from_approved_configchanges the harness, routing a saved Claude key as a Codex secret or vice versa. - Auth-secret fetch failures can leave the orchestration picker stuck on
Loading…because the failed fetch path does not notify the new subscribers.
Security
- The stale-harness case is a secret-routing issue: a managed secret selected for one harness can be attached to another harness's auth config during auto-launch.
Verdict
Found: 0 critical, 2 important, 0 suggestions
Request changes
Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).
Powered by Oz
| if self.state.orch.auth_secret_name.is_none() { | ||
| self.state.orch.auth_secret_name = oc::resolve_default_auth_secret_for_harness( | ||
| &self.state.orch.harness_type, | ||
| ctx, | ||
| ); | ||
| } | ||
|
|
There was a problem hiding this comment.
override_from_approved_config changes the harness, an existing auth secret prevents re-resolution and can route a Claude key as Codex (or vice versa). Re-resolve after the override.
| if self.state.orch.auth_secret_name.is_none() { | |
| self.state.orch.auth_secret_name = oc::resolve_default_auth_secret_for_harness( | |
| &self.state.orch.harness_type, | |
| ctx, | |
| ); | |
| } | |
| self.state.orch.auth_secret_name = | |
| oc::resolve_default_auth_secret_for_harness( | |
| &self.state.orch.harness_type, | |
| ctx, | |
| ); |
There was a problem hiding this comment.
taking a look at this + below
| MenuItemFields::new("Loading…").with_disabled(true), | ||
| )); | ||
| } | ||
| AuthSecretFetchState::Failed(_) => { |
There was a problem hiding this comment.
Failed state will not render after a fetch error because fetch_auth_secrets stores Failed without emitting an event, so the picker remains on Loading…; emit/subscribe to a failure event or notify after failure.
There was a problem hiding this comment.
fixed - added HarnessAvailabilityEvent::AuthSecretsFetchFailed
- Plan-card UI: render the API key picker directly under the harness picker in the vertical layout so it no longer splits the model picker from the 'Primary model...' subtext. - Drop the unused harness field from HarnessAvailabilityEvent::AuthSecretsFetchFailed (subscribers ignored it). - Shorten the harness_auth_secret_name doc comment on RunAgentsRequest to match precedent of the other fields. Co-Authored-By: Oz <oz-agent@warp.dev>



Loom for run agents card: https://www.loom.com/share/10263029b97d4bada81f24b2081e3410
Loom for plan card: https://www.loom.com/share/f3e9b7dc44044b8187c723c8d59e4ae4
Fixes https://linear.app/warpdotdev/issue/QUALITY-700/api-key-configuration-for-orchestration-card-in-line-and-plan
Description
Adds an "API key" picker to the orchestration plan card and the
run_agentsconfirmation card. When the orchestration harness is set to a non-Oz harness (Claude Code or Codex) running on Cloud, the user can now pick a managed secret that will be injected into each cloud child agent as it spawns. This unblocks the multi-harness local → cloud orchestration flow that broke when the team-scoped Anthropic / OpenAI blanket env var was removed — Ian's screenshot of a Claude Code child failing to authenticate with no Oz-side fix was the immediate motivation.Note that we haven't added the ability to add in a new secret via this flow yet - I'll follow up on that in another PR, but this should unblock the demo I believe. We can pop up a modal for new secret flow.
Let me know if I missed anything here - I have less context on these codepaths/product flows!
High-level design
The selection lives in the same per-harness setting that cloud single-agent mode already uses, so picking a key from either the plan card, the confirmation card, or the existing single-agent cloud picker is unified — change it in one place and every surface reflects the choice. The picker is gated by the same condition cloud-mode applies: only shown when execution mode is Cloud and the harness has at least one supported managed-secret type. Local harness children continue to inherit credentials from the user's shell environment as they did before.
On dispatch, the selected secret flows through the existing orchestration pipeline as a Rust-only field that does not round-trip through the multi-agent proto. The orchestrate request carries it from the UI into the per-child Start-Agent dispatch, where it gets mapped into the harness-specific config shape the cloud worker already understands. No server or proto changes are needed because the cloud spawn API has supported per-harness auth secrets ever since the single-agent feature shipped — this PR just teaches the orchestration pathway to populate that field instead of leaving it empty. The persistence story is also reused: the secret name is stored client-side in the same settings entry as cloud mode, so it survives across sessions and across both UIs without introducing new state.
Two flow-control subtleties worth flagging for reviewers: the picker's action handler intentionally does not re-render its own dropdown (the user's click already updated the selection, and a self-update would trip the UI framework's circular-update guard), and the confirmation card's streaming/auto-launch paths re-seed the secret from settings after every proto-derived state rebuild so a plan-card pick survives the auto-launch handoff. Both came up during local testing and are documented inline.
Testing
./script/runManual:
Automated: