Skip to main content

subagents/
subagents.rs

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