Skip to main content

subagents/
subagents.rs

1use antigravity_sdk_rust::agent::{Agent, AgentConfig};
2use antigravity_sdk_rust::hooks::Hook;
3use antigravity_sdk_rust::policy;
4use antigravity_sdk_rust::types::{
5    BuiltinTools, CapabilitiesConfig, GeminiConfig, HookResult, ToolCall, ToolResult,
6};
7use std::sync::Arc;
8use std::sync::atomic::{AtomicBool, Ordering};
9use tracing_subscriber::EnvFilter;
10
11struct SubagentHook {
12    subagent_active: Arc<AtomicBool>,
13}
14
15impl Hook for SubagentHook {
16    async fn pre_tool_call(&self, tool_call: &ToolCall) -> Result<HookResult, anyhow::Error> {
17        if tool_call.name == "START_SUBAGENT" {
18            self.subagent_active.store(true, Ordering::SeqCst);
19            println!("\n  --- 🤖 [Hook] Spawning Subagent ---");
20            println!("  Arguments: {}\n", tool_call.args);
21        } else {
22            let indent = if self.subagent_active.load(Ordering::SeqCst) {
23                "    "
24            } else {
25                "  "
26            };
27            println!(
28                "{}- [Start]: {} (ID: {})",
29                indent, tool_call.name, tool_call.id
30            );
31        }
32        Ok(HookResult {
33            allow: true,
34            message: String::new(),
35        })
36    }
37
38    async fn post_tool_call(&self, result: &ToolResult) -> Result<(), anyhow::Error> {
39        if result.name == "START_SUBAGENT" {
40            self.subagent_active.store(false, Ordering::SeqCst);
41            println!("\n  --- 🤖 [Hook] Subagent Finished ---");
42            println!("  Result: {:?}\n", result.result);
43        } else {
44            let indent = if self.subagent_active.load(Ordering::SeqCst) {
45                "    "
46            } else {
47                "  "
48            };
49            println!(
50                "{}- [Done]: {} (ID: {}) ✅",
51                indent,
52                result.name,
53                result.id.as_deref().unwrap_or("")
54            );
55        }
56        Ok(())
57    }
58}
59
60#[tokio::main]
61async fn main() -> Result<(), anyhow::Error> {
62    // Initialize tracing subscriber
63    tracing_subscriber::fmt()
64        .with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
65        .init();
66
67    // Load environment variables from .env file if present
68    dotenvy::dotenv().ok();
69
70    let mut config = AgentConfig::default();
71
72    if let Ok(harness_path) = std::env::var("ANTIGRAVITY_HARNESS_PATH") {
73        config.binary_path = Some(harness_path);
74    }
75
76    let mut gemini_config = GeminiConfig::default();
77    if let Ok(api_key) = std::env::var("GEMINI_API_KEY") {
78        gemini_config.api_key = Some(api_key);
79    }
80    gemini_config.models.default.name = "gemini-3.5-flash".to_string();
81    config.gemini_config = gemini_config;
82
83    // Enable subagents capability and file viewing
84    let capabilities = CapabilitiesConfig {
85        enabled_tools: Some(vec![
86            BuiltinTools::StartSubagent,
87            BuiltinTools::ListDir,
88            BuiltinTools::ViewFile,
89            BuiltinTools::Finish,
90        ]),
91        ..Default::default()
92    };
93    config.capabilities = capabilities;
94
95    // Add Hook for visibility
96    let subagent_active = Arc::new(AtomicBool::new(false));
97    config
98        .hooks
99        .push(Arc::new(SubagentHook { subagent_active }));
100
101    // Allow tools
102    config.policies = Some(vec![policy::allow_all()]);
103
104    let mut agent = Agent::new(config);
105    println!("Starting agent...");
106    agent.start().await?;
107
108    let prompt = "Use a subagent to research the files in the current directory. \
109                  Delegate the task of listing the directory to the subagent, and then \
110                  tell me what files you found.";
111
112    println!("  User: {}", prompt);
113    let response = agent.chat(prompt).await?;
114    println!("\n  Agent:\n{}", response.text);
115
116    agent.stop().await?;
117    Ok(())
118}