use claude_agent_sdk::{
ClaudeAgentOptions, ClaudeClient, Message, PermissionMode, SdkPluginConfig,
};
use futures::StreamExt;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
println!("=== Example 22: Plugin Integration - Development Assistant ===\n");
println!("Building a development assistant with plugins:\n");
let plugins = vec![
SdkPluginConfig::local("./plugins/database-tools"),
SdkPluginConfig::local("./plugins/api-tester"),
SdkPluginConfig::local("./plugins/code-gen"),
];
println!("Configured plugins:");
for (i, plugin) in plugins.iter().enumerate() {
println!(" {}. {:?}", i + 1, plugin.path().unwrap());
}
println!();
let options = ClaudeAgentOptions::builder()
.plugins(plugins)
.allowed_tools(vec![
"Read".to_string(),
"Write".to_string(),
"Bash".to_string(),
])
.permission_mode(PermissionMode::Default) .max_turns(10)
.max_budget_usd(5.0) .build();
println!("Configuration:");
println!(" • Permission mode: Ask (for safety)");
println!(" • Max turns: 10");
println!(" • Budget limit: $5.00");
println!(" • Standard tools: Read, Write, Bash");
println!(" • Plugin count: 3\n");
let mut client = ClaudeClient::new(options);
println!("Connecting to Claude...");
match client.connect().await {
Ok(_) => println!("✓ Connected successfully\n"),
Err(e) => {
println!("✗ Connection failed: {}", e);
println!("\nNote: This example requires:");
println!(" • Claude CLI installed and configured");
println!(" • Plugin support enabled (if available)");
println!(" • Valid plugin paths");
return Ok(());
},
}
println!("--- Example Task: Project Setup ---\n");
client
.query("What plugins and tools are currently available to you?")
.await?;
println!("Processing response...\n");
let mut message_count = 0;
{
let mut stream = client.receive_response();
while let Some(result) = stream.next().await {
match result {
Ok(Message::Assistant(msg)) => {
message_count += 1;
println!("Assistant message #{}:", message_count);
for block in &msg.message.content {
match block {
claude_agent_sdk::ContentBlock::Text(text) => {
println!("{}", text.text);
},
claude_agent_sdk::ContentBlock::ToolUse(tool) => {
println!(" [Tool: {}]", tool.name);
},
_ => {},
}
}
println!();
},
Ok(Message::System(sys)) => {
println!("System: {}", sys.subtype);
},
Ok(Message::Result(result)) => {
println!("--- Result ---");
println!("Duration: {}ms", result.duration_ms);
println!("Turns: {}", result.num_turns);
println!("Error: {}", result.is_error);
if let Some(cost) = result.total_cost_usd {
println!("Cost: ${:.4}", cost);
}
break;
},
Err(e) => {
println!("Error: {}", e);
break;
},
_ => {},
}
}
}
client.disconnect().await?;
println!("\n✓ Disconnected\n");
println!("=== Plugin Integration Best Practices ===\n");
println!("1. Plugin Organization:");
println!(" • Group related tools in single plugins");
println!(" • Use descriptive plugin names");
println!(" • Version your plugins properly");
println!("\n2. Error Handling:");
println!(" • Check plugin paths exist before loading");
println!(" • Handle plugin load failures gracefully");
println!(" • Provide fallback behavior when plugins fail");
println!("\n3. Configuration:");
println!(" • Use permission modes appropriately");
println!(" • Set budget limits for safety");
println!(" • Combine plugins with standard tools wisely");
println!("\n4. Development Workflow:");
println!(" • Test plugins individually first");
println!(" • Verify plugin compatibility");
println!(" • Monitor plugin performance impact");
println!(" • Document plugin requirements");
println!("\n5. Production Deployment:");
println!(" • Use absolute paths for stability");
println!(" • Implement plugin health checks");
println!(" • Version lock plugin dependencies");
println!(" • Have rollback plans ready");
Ok(())
}