Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/ai/agent_sdk/ambient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ impl AmbientAgentRunner {
(_, true) => Some(false),
_ => None,
},
agent_identity_uid: args.agent_uid,
skill,
attachments,
interactive: None,
Expand Down
1 change: 1 addition & 0 deletions app/src/ai/agent_sdk/mcp_config_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ fn serializes_mcp_servers_as_object_not_string() {
}),
title: None,
team: None,
agent_identity_uid: None,
skill: None,
attachments: vec![],
interactive: None,
Expand Down
2 changes: 2 additions & 0 deletions app/src/ai/ambient_agents/spawn_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ async fn poll_stops_on_terminal_failure_like_state() {
config: None,
title: None,
team: None,
agent_identity_uid: None,
skill: None,
attachments: vec![],
interactive: None,
Expand Down Expand Up @@ -451,6 +452,7 @@ async fn poll_for_session_join_info_waits_until_link_is_available() {
config: None,
title: None,
team: None,
agent_identity_uid: None,
skill: None,
attachments: vec![],
interactive: None,
Expand Down
1 change: 1 addition & 0 deletions app/src/pane_group/pane/terminal_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,7 @@ fn handle_terminal_view_event(
}),
title: (!title.is_empty()).then_some(title),
team: None,
agent_identity_uid: None,
skill: None,
attachments: vec![],
interactive: Some(true),
Expand Down
6 changes: 6 additions & 0 deletions app/src/server/server_api/ai.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ pub struct SpawnAgentRequest {
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub team: Option<bool>,
/// Agent identity UID to use as the execution principal for the run.
#[serde(
rename = "agent_identity_uid",
skip_serializing_if = "Option::is_none"
)]
pub agent_identity_uid: Option<String>,
/// Use a Claude-compatible skill as the base prompt.
/// Format: "repo:skill_name" or just "skill_name".
/// The skill is resolved at runtime in the agent environment.
Expand Down
28 changes: 27 additions & 1 deletion app/src/server/server_api/ai_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use super::{
build_list_agent_runs_url, build_run_followup_url, AgentMessageHeader, AgentRunEvent,
AgentSource, AmbientAgentTaskState, Artifact, ArtifactDownloadResponse, ArtifactType,
ExecutionLocation, ListRunsResponse, ReadAgentMessageResponse, RunFollowupRequest, RunSortBy,
RunSortOrder, TaskListFilter,
RunSortOrder, SpawnAgentRequest, TaskListFilter, UserQueryMode,
};
use crate::notebooks::NotebookId;

Expand All @@ -33,6 +33,32 @@ fn ambient_agent_headers_for_task_overrides_existing_cloud_agent_header() {
);
}

#[test]
fn spawn_agent_request_serializes_agent_uid_as_agent_identity_uid() {
let request = SpawnAgentRequest {
prompt: "hello".to_string(),
mode: UserQueryMode::Normal,
config: None,
title: None,
team: None,
agent_identity_uid: Some("agent_123".to_string()),
skill: None,
attachments: vec![],
interactive: None,
parent_run_id: None,
runtime_skills: vec![],
referenced_attachments: vec![],
};

let value = serde_json::to_value(&request).unwrap();

assert_eq!(
value.get("agent_identity_uid").and_then(|v| v.as_str()),
Some("agent_123")
);
assert!(value.get("agent_uid").is_none());
}

#[test]
fn test_deserialize_file_artifact_download_response() {
let json = r#"{
Expand Down
1 change: 1 addition & 0 deletions app/src/terminal/view/ambient_agent/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ impl AmbientAgentViewModel {
config,
title: None,
team: None,
agent_identity_uid: None,
skill: None,
attachments,
interactive: None,
Expand Down
8 changes: 8 additions & 0 deletions crates/warp_cli/src/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,14 @@ pub struct RunCloudArgs {
#[command(flatten)]
pub scope: ObjectScope,

/// UID of the agent to execute this run as.
///
/// This will apply the agent's configuration, such
/// as its skills and base model, and attribute
/// credit usage back to the agent.
#[arg(long = "agent", value_name = "UID")]
pub agent_uid: Option<String>,

/// Where this job should be hosted. Setting "warp" runs it on Warp's infrastructure. Any other
/// value is treated is a self-hosted job and the value will be matched with the self-hosted
/// worker's name.
Expand Down
23 changes: 23 additions & 0 deletions crates/warp_cli/src/lib_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,29 @@ fn agent_run_cloud_accepts_model() {
assert_eq!(run_args.model.model.as_deref(), Some("gpt-4o"));
}

#[test]
fn agent_run_cloud_accepts_agent_flag() {
let args = Args::try_parse_from([
"warp",
"agent",
"run-cloud",
"--prompt",
"hello",
"--agent",
"agent_123",
])
.unwrap();

let Some(Command::CommandLine(boxed_cmd)) = args.command else {
panic!("Expected `warp agent run-cloud` command");
};
let CliCommand::Agent(AgentCommand::RunCloud(run_args)) = boxed_cmd.as_ref() else {
panic!("Expected `warp agent run-cloud` command");
};

assert_eq!(run_args.agent_uid.as_deref(), Some("agent_123"));
}

#[test]
fn agent_run_cloud_accepts_mcp() {
let uuid = uuid::Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
Expand Down
Loading