Skip to content

Add auth secret dropdown picker for non-Oz orchestration#10885

Merged
advait-m merged 6 commits into
masterfrom
advait/orchestration-auth-secret-picker
May 14, 2026
Merged

Add auth secret dropdown picker for non-Oz orchestration#10885
advait-m merged 6 commits into
masterfrom
advait/orchestration-auth-secret-picker

Conversation

@advait-m
Copy link
Copy Markdown
Member

@advait-m advait-m commented May 14, 2026

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_agents confirmation 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

  • I have manually tested my changes locally with ./script/run

Manual:

  • Created an API key for myself for both CC and Codex, tested with that - see Looms

Automated:

  • Added unit tests covering: Claude/Codex auth-secret propagation through the orchestrate → start-agent conversion, whitespace-only names being normalized to None, Local mode ignoring the field.
  • Updated the existing orchestration / start-agent / convert-from / block-tests test suites for the new struct field; all 131 orchestration/run_agents/start_agent tests pass.

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>
@cla-bot cla-bot Bot added the cla-signed label May 14, 2026
@advait-m advait-m marked this pull request as ready for review May 14, 2026 02:13
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 14, 2026

@advait-m

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 /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_config changes 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

Comment on lines +560 to +566
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,
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] [SECURITY] If 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.

Suggested change
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,
);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

taking a look at this + below

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed - removed gating

MenuItemFields::new("Loading…").with_disabled(true),
));
}
AuthSecretFetchState::Failed(_) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] This 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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed - added HarnessAvailabilityEvent::AuthSecretsFetchFailed

@advait-m advait-m changed the title Add auth secret picker for non-Oz orchestration Add auth secret dropdown picker for non-Oz orchestration May 14, 2026
Copy link
Copy Markdown
Contributor

@liliwilson liliwilson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this makes sense to me! Thanks for getting it out so quickly

One UI comment:
Image
I think for the plan mode, API key should probably be just below the harness selector (or at least shouldn't be in between the model selector and the "Primary model..." subtext)

Comment thread app/src/ai/harness_availability.rs Outdated
Comment thread crates/ai/src/agent/action/mod.rs Outdated
@advait-m
Copy link
Copy Markdown
Member Author

Nice, this makes sense to me! Thanks for getting it out so quickly

One UI comment: Image I think for the plan mode, API key should probably be just below the harness selector (or at least shouldn't be in between the model selector and the "Primary model..." subtext)

good catch, fixed

image

- 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>
@advait-m advait-m enabled auto-merge (squash) May 14, 2026 06:43
@advait-m advait-m merged commit 98aaece into master May 14, 2026
25 checks passed
@advait-m advait-m deleted the advait/orchestration-auth-secret-picker branch May 14, 2026 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants