#16626

Issue independent agent bootstrap fetches concurrently

Draftkevinyang372wants to merge intofrom

Description

Part of the Oz cloud-agent startup latency work (workstream C3). worker_container_ready -> shared_session_started is a near-constant ~2.9s for every run of every harness. It is a chain of server round trips in AgentDriverRunner::setup_and_run_driver that were awaited one after another even though most of them only need the task id and the workload token. This PR issues the independent ones together.

Dependency map of the chain (cloud --task-id --execution-id launch)

Serial before this PR, in order:

  1. set_ambient_agent_task_id (local)
  2. worker_container_ready timeline POST (1 RTT, telemetry only)
  3. issue_workload_token + ExecutionBootstrap GraphQL (1 RTT with retry) — needs task id, execution id, workload token
  4. refresh_team_metadata (1 RTT, up to 30s retry budget) — needs auth only
  5. Warp Drive wait — waits for the initial load that began at login; no request of its own
  6. build_driver_options_and_task, which starts with bootstrap_git_credentials_for_task (issue_workload_token + TaskGitCredentials GraphQL, 1 RTT) — needs task id, workload token, and use_factory_repositories, which is computed locally from the task id, the FactoryDeferredRepositories capability, and WARP_FACTORY_ID
  7. then skill repo clones (need git credentials), build_execution_task_and_options, attachment downloads (need the bootstrap's attachment list), cloud provider load
  8. AgentDriver::create spawns the PTY; run() PATCHes InProgress (already overlapping the shell bootstrap); run_internal waits for bootstrap, then the session-sharing handshake.

What now runs concurrently

Steps 2, 3, 4, and 6a are issued with one try_join!:

  • the ExecutionBootstrap fetch,
  • the git credentials bootstrap (hoisted out of build_driver_options_and_task; it ran there only because that was the first place with use_factory_repositories, which is now captured once up front as RepositoryContract::for_task and passed to both the fetch and the credentials call, preserving the "capability captured at launch" guarantee the existing subprocess test checks),
  • the team metadata refresh,
  • the worker_container_ready POST.

None of the four reads anything another one produces: the bootstrap and git credentials each issue their own workload token (a local read on the self-hosted worker), the team refresh only needs auth, and the timeline POST is fire-and-record. try_join! keeps today's failure semantics in the single-failure case: a fast bootstrap failure still surfaces as ConfigBuildFailed without waiting for the team refresh's retry budget, and a team refresh timeout still surfaces as TeamMetadataRefreshFailed (the existing paused-time test for that path still passes). Dropping the team refresh future on another future's error stops its retries, which dropping_cloud_startup_metadata_refresh_stops_retries already covers.

Expected effect: three round trips removed from the critical path (container-ready POST, team refresh, git credentials), i.e. roughly half of the ~6 serialized round trips in this phase, for every harness.

What stays serial, and why

  • Warp Drive wait stays after the join and the team-scope resolution. It waits on a load that started at login, so there is no round trip to overlap; joining it would also make the legacy launch path touch UpdateManager before the team refresh resolves, which the paused-time test does not register.
  • Team scope resolution (legacy path) reads UserWorkspaces, so it needs the team refresh.
  • Skill repo clones need the git credentials; attachment downloads need the bootstrap's attachment list; both stay inside build_driver_options_and_task after the join.
  • InProgress PATCH mutates server state and already overlaps the shell bootstrap (the PTY spawn starts in AgentDriver::create, before run() issues the PATCH). Unchanged.
  • PTY spawn was not moved earlier. The shell's environment must be complete at spawn (secrets, cloud-provider variables, task variables, the deferred-repository policy file), and that is only known after the bootstrap fetch, build_execution_task_and_options, prepare_execution_task_data, and load_providers. The only remaining pre-spawn work after that point is the attachment/handoff fetch, Bedrock credential minting (which feeds the environment), and resume loading. Overlapping the spawn with those would require splitting AgentDriver::create so the terminal is created before options are final and then re-spawned or re-exported into, which is what the standby path does with replace_shell_with_resolved_env at the cost of a second shell spawn. Not worth it for one round trip here; noted as a follow-up if the handoff fetch shows up in the A1 breakdown.

Setup events

Two new, run-scoped events make the join measurable: setup_execution_bootstrap_fetch and setup_git_credentials_bootstrap. Neither call was instrumented before. No existing names were changed; setup_team_metadata_refresh and setup_warp_drive_sync keep their meaning. The server does not allowlist setup-metric names, so nothing needs to land first.

Linked Issue

  • The linked issue is labeled ready-to-spec or ready-to-implement.
  • Where appropriate, screenshots or a short video of the implementation are included below (especially for user-visible or UI changes).

Testing

  • cargo check -p warp --tests — clean, no warnings
  • cargo nextest run -p warp -E 'test(/agent_sdk::tests/) | test(/agent_sdk::setup_observability/) | test(/agent_sdk::driver::prewarmed/)' — 56 passed, 0 failed, including legacy_execution_launch_skips_bootstrap_and_reports_team_metadata_refresh_failure (team refresh timeout still reported after 30s with the join) and paired_execution_keeps_captured_capability_after_runtime_flag_changes (the capability captured before the bootstrap still governs the git credentials request and the options build)
  • cargo clippy -p warp --all-targets --tests -- -D warnings — clean
  • cargo fmt -p warp with the repo's import config

Test changes: the subprocess bootstrap test now builds RepositoryContract::for_task itself and calls bootstrap_git_credentials_for_task explicitly, mirroring the new call structure; the legacy launch test's client-event expectation widened from 1..=2 to 1..=3 for the new git-credentials setup metric, which posts from the background and may or may not land before exit.

Not done: an end-to-end timing comparison against a local or staging Oz stack. Recommend comparing worker_container_ready -> shared_session_started on staging before/after, using the two new setup events to confirm the fetches overlap.

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

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

CHANGELOG-OZ: Cloud agent runs fetch their configuration, git credentials, and team metadata concurrently at startup instead of one after another.

Activity

1

This pull request is a draft

Merging is unavailable until it is marked ready for review.