1use antigravity_sdk_rust::agent::Agent;
2use antigravity_sdk_rust::policy::{self, Decision, Policy};
3use antigravity_sdk_rust::types::ToolCall;
4use serde_json::Value;
5use std::sync::Arc;
6use tracing_subscriber::EnvFilter;
7
8fn block_rm_predicate(tool_call: &ToolCall) -> bool {
9 tool_call
10 .args
11 .get("CommandLine")
12 .and_then(Value::as_str)
13 .is_some_and(|cmd| cmd.contains("rm"))
14}
15
16fn critical_file_predicate(tool_call: &ToolCall) -> bool {
17 tool_call
18 .args
19 .get("TargetFile")
20 .or_else(|| tool_call.args.get("target_file"))
21 .or_else(|| tool_call.args.get("path"))
22 .and_then(Value::as_str)
23 .is_some_and(|p| {
24 std::path::Path::new(p)
25 .extension()
26 .is_some_and(|ext| ext.eq_ignore_ascii_case("key"))
27 || p.contains("production")
28 })
29}
30
31fn programmatic_approval_handler(tool_call: &ToolCall) -> bool {
32 println!(
33 "\n [ASK_USER Handler] Intercepted request for tool: {}",
34 tool_call.name
35 );
36 println!(" [ASK_USER Handler] Target arguments: {}", tool_call.args);
37 println!(" [ASK_USER Handler] Simulating user review... Decision: DENY.");
38 false
39}
40
41#[tokio::main]
42async fn main() -> Result<(), anyhow::Error> {
43 tracing_subscriber::fmt()
45 .with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
46 .init();
47
48 dotenvy::dotenv().ok();
50
51 let harness_path = std::env::var("ANTIGRAVITY_HARNESS_PATH").ok();
52 let api_key = std::env::var("GEMINI_API_KEY").ok();
53
54 let mut builder = Agent::builder();
55 if let Some(path) = harness_path {
56 builder = builder.binary_path(path);
57 }
58 if let Some(key) = api_key {
59 builder = builder.api_key(key);
60 }
61
62 let agent = builder
63 .default_model("gemini-3.5-flash")
64 .policy(policy::deny_all())
66 .policy(policy::allow("LIST_DIR"))
68 .policy(Policy::new(
70 "RUN_COMMAND".to_string(),
71 Decision::Deny,
72 Some(Arc::new(block_rm_predicate)),
73 None,
74 "block-rm".to_string(),
75 ))
76 .policy(policy::allow("RUN_COMMAND"))
78 .policy(Policy::new(
80 "WRITE_TO_FILE".to_string(),
81 Decision::AskUser,
82 Some(Arc::new(critical_file_predicate)),
83 Some(Arc::new(programmatic_approval_handler)),
84 "ask-for-critical-writes".to_string(),
85 ))
86 .policy(policy::allow("WRITE_TO_FILE"))
87 .build();
88
89 println!("Starting agent...");
90 let agent = agent.start().await?;
91
92 println!("\n Chatting with agent...");
93
94 let prompt1 = "List the files in the current directory.";
96 println!("\n User: {}", prompt1);
97 let response1 = agent.chat(prompt1).await?;
98 println!(" Agent: {}", response1.text);
99
100 let prompt2 = "Delete all files using rm -rf.";
102 println!("\n User: {}", prompt2);
103 let response2 = agent.chat(prompt2).await?;
104 println!(" Agent: {}", response2.text);
105
106 let prompt3 = "Create a new configuration file named production.key with content 'debug=true'.";
108 println!("\n User: {}", prompt3);
109 let response3 = agent.chat(prompt3).await?;
110 println!(" Agent: {}", response3.text);
111
112 agent.stop().await?;
113 Ok(())
114}