1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Example demonstrating bidirectional communication with ClaudeClient
//!
//! This example shows how to use ClaudeClient (analogous to Python's ClaudeClient)
//! for bidirectional, streaming communication with Claude Code.
//!
//! Key features demonstrated:
//! - Connecting to Claude
//! - Sending multiple queries in the same session
//! - Streaming responses with receive_response()
//! - Claude remembering context across queries
//! - Clean disconnection
//!
//! Run with:
//! ```bash
//! cargo run --example 06_bidirectional_client
//! ```
use claude_agent_sdk::{ClaudeAgentOptions, ClaudeClient, ContentBlock, Message};
use futures::StreamExt;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Bidirectional ClaudeClient Example ===\n");
// Create client with options
let options = ClaudeAgentOptions {
max_turns: Some(5),
..Default::default()
};
let mut client = ClaudeClient::new(options);
// Connect to Claude (analogous to Python's `async with ClaudeClient()`)
println!("Connecting to Claude...");
client.connect().await?;
println!("Connected!\n");
// First query
println!("Query 1: What is your name?");
client.query("What is your name?").await?;
// Receive response as a stream (continues until ResultMessage)
let mut stream = client.receive_response();
while let Some(message) = stream.next().await {
match message? {
Message::Assistant(msg) => {
for block in msg.message.content {
if let ContentBlock::Text(text) = block {
println!("Claude: {}", text.text);
}
}
},
Message::Result(result) => {
println!(
"\n[Result] Duration: {}ms, Cost: ${:.4}\n",
result.duration_ms,
result.total_cost_usd.unwrap_or(0.0)
);
},
_ => {},
}
}
drop(stream); // Release borrow before next query
// Second query - Claude remembers context!
println!("Query 2: Can you remember what I just asked you?");
client
.query("Can you remember what I just asked you?")
.await?;
let mut stream = client.receive_response();
while let Some(message) = stream.next().await {
match message? {
Message::Assistant(msg) => {
for block in msg.message.content {
if let ContentBlock::Text(text) = block {
println!("Claude: {}", text.text);
}
}
},
Message::Result(result) => {
println!(
"\n[Result] Duration: {}ms, Cost: ${:.4}\n",
result.duration_ms,
result.total_cost_usd.unwrap_or(0.0)
);
},
_ => {},
}
}
drop(stream); // Release borrow before next query
// Third query
println!("Query 3: Tell me a short joke");
client.query("Tell me a short joke").await?;
let mut stream = client.receive_response();
while let Some(message) = stream.next().await {
match message? {
Message::Assistant(msg) => {
for block in msg.message.content {
if let ContentBlock::Text(text) = block {
println!("Claude: {}", text.text);
}
}
},
Message::Result(result) => {
println!(
"\n[Result] Duration: {}ms, Cost: ${:.4}\n",
result.duration_ms,
result.total_cost_usd.unwrap_or(0.0)
);
},
_ => {},
}
}
drop(stream); // Release borrow before disconnect
// Clean disconnect (analogous to Python's `async with` exit)
println!("Disconnecting...");
client.disconnect().await?;
println!("Disconnected!");
Ok(())
}