Skip to main content

agent_client_protocol/concepts/
connections.rs

1//! Establishing connections using role types and connection builders.
2//!
3//! To communicate over ACP, you need to establish a connection. This involves
4//! choosing a **role type** that matches your role and using a **connection builder**
5//! to configure and run the connection.
6//!
7//! # Choosing a Role Type
8//!
9//! Your role type determines what messages you can send and who you can send them to.
10//! Choose based on what you're building:
11//!
12//! | You are building... | Use this role type |
13//! |---------------------|-------------------|
14//! | A client that talks to an agent | [`Client`] |
15//! | An agent that responds to clients | [`Agent`] |
16//! | A proxy in a conductor chain | [`Proxy`] |
17//!
18//! # The Connection Builder Pattern
19//!
20//! Every role type has a `builder()` method that returns a connection builder.
21//! The builder lets you configure handlers, then connect to a transport:
22//!
23//! ```
24//! # use agent_client_protocol::{Client, Agent, ConnectTo};
25//! # async fn example(transport: impl ConnectTo<Client>) -> Result<(), agent_client_protocol::Error> {
26//! Client.builder()
27//!     .name("my-client")
28//!     .connect_with(transport, async |cx| {
29//!         // Use `cx` to send requests and handle responses
30//!         Ok(())
31//!     })
32//!     .await?;
33//! # Ok(())
34//! # }
35//! ```
36//!
37//! # The Connection Context
38//!
39//! Inside `connect_with`, you receive a [`ConnectionTo`] (connection context) that
40//! lets you interact with the remote peer:
41//!
42//! ```
43//! # use agent_client_protocol::{Client, Agent, ConnectTo};
44//! # use agent_client_protocol::schema::{InitializeRequest, ProtocolVersion};
45//! # use agent_client_protocol_test::StatusUpdate;
46//! # async fn example(transport: impl ConnectTo<Client>) -> Result<(), agent_client_protocol::Error> {
47//! # Client.builder().connect_with(transport, async |cx| {
48//! // Send a request and wait for the response
49//! let response = cx.send_request(InitializeRequest::new(ProtocolVersion::V1))
50//!     .block_task()
51//!     .await?;
52//!
53//! // Send a notification (fire-and-forget)
54//! cx.send_notification(StatusUpdate { message: "hello".into() })?;
55//! # Ok(())
56//! # }).await?;
57//! # Ok(())
58//! # }
59//! ```
60//!
61//! # Sending Requests
62//!
63//! When you call `send_request()`, you get back a [`SentRequest`] that represents
64//! the pending response. You have two main ways to handle it:
65//!
66//! ## Option 1: Block and wait
67//!
68//! Use `block_task()` when you need the response before continuing:
69//!
70//! ```
71//! # use agent_client_protocol::{Client, Agent, ConnectTo};
72//! # use agent_client_protocol_test::MyRequest;
73//! # async fn example(transport: impl ConnectTo<Client>) -> Result<(), agent_client_protocol::Error> {
74//! # Client.builder().connect_with(transport, async |cx| {
75//! let response = cx.send_request(MyRequest {})
76//!     .block_task()
77//!     .await?;
78//! // Use response here
79//! # Ok(())
80//! # }).await?;
81//! # Ok(())
82//! # }
83//! ```
84//!
85//! ## Option 2: Schedule a callback
86//!
87//! Use `on_receiving_result()` when you want to handle the response asynchronously:
88//!
89//! ```
90//! # use agent_client_protocol::{Client, Agent, ConnectTo};
91//! # use agent_client_protocol_test::MyRequest;
92//! # async fn example(transport: impl ConnectTo<Client>) -> Result<(), agent_client_protocol::Error> {
93//! # Client.builder().connect_with(transport, async |cx| {
94//! cx.send_request(MyRequest {})
95//!     .on_receiving_result(async |result| {
96//!         match result {
97//!             Ok(response) => { /* handle success */ }
98//!             Err(error) => { /* handle error */ }
99//!         }
100//!         Ok(())
101//!     })?;
102//! // Continues immediately, callback runs when response arrives
103//! # Ok(())
104//! # }).await?;
105//! # Ok(())
106//! # }
107//! ```
108//!
109//! See [Ordering](super::ordering) for important details about how these differ.
110//!
111//! # Next Steps
112//!
113//! - [Sessions](super::sessions) - Create multi-turn conversations
114//! - [Callbacks](super::callbacks) - Handle incoming requests from the remote peer
115//!
116//! [`Client`]: crate::Client
117//! [`Agent`]: crate::Agent
118//! [`Proxy`]: crate::Proxy
119//! [`ConnectionTo`]: crate::ConnectionTo
120//! [`SentRequest`]: crate::SentRequest