Skip to main content

agent_client_protocol/concepts/
peers.rs

1//! Explicit peers: using `_to` and `_from` variants.
2//!
3//! So far, we've used methods like `send_request` and `on_receive_request`
4//! without specifying *who* we're sending to or receiving from. That's because
5//! each role type has a **default peer**.
6//!
7//! # Default Peers
8//!
9//! For simple role types, there's only one peer to talk to:
10//!
11//! | Role Type | Default Peer |
12//! |-----------|--------------|
13//! | [`Client`] | The agent |
14//! | [`Agent`] | The client |
15//!
16//! So when you write:
17//!
18//! ```
19//! # use agent_client_protocol::{Client, Agent, ConnectTo};
20//! # use agent_client_protocol::schema::{InitializeRequest, ProtocolVersion};
21//! # async fn example(transport: impl ConnectTo<Client>) -> Result<(), agent_client_protocol::Error> {
22//! # Client.builder().connect_with(transport, async |cx| {
23//! // As a client
24//! cx.send_request(InitializeRequest::new(ProtocolVersion::V1));
25//! # Ok(())
26//! # }).await?;
27//! # Ok(())
28//! # }
29//! ```
30//!
31//! The request automatically goes to the agent, because that's the only peer
32//! a client can talk to.
33//!
34//! # Explicit Peer Methods
35//!
36//! Every method has an explicit variant that takes a peer argument:
37//!
38//! | Default method | Explicit variant |
39//! |----------------|------------------|
40//! | `send_request` | `send_request_to(peer, request)` |
41//! | `send_notification` | `send_notification_to(peer, request)` |
42//! | `on_receive_request` | `on_receive_request_from(peer, callback)` |
43//! | `on_receive_notification` | `on_receive_notification_from(peer, callback)` |
44//!
45//! For simple role types, the explicit form is equivalent:
46//!
47//! ```
48//! # use agent_client_protocol::{Client, Agent, ConnectTo};
49//! # use agent_client_protocol_test::MyRequest;
50//! # async fn example(transport: impl ConnectTo<Client>) -> Result<(), agent_client_protocol::Error> {
51//! # Client.builder().connect_with(transport, async |cx| {
52//! # let req = MyRequest {};
53//! // These are equivalent for Client:
54//! cx.send_request(req.clone());
55//! cx.send_request_to(Agent, req);
56//! # Ok(())
57//! # }).await?;
58//! # Ok(())
59//! # }
60//! ```
61//!
62//! # Why Explicit Peers Matter
63//!
64//! Explicit peers become essential when working with proxies. A proxy sits
65//! between a client and an agent, so it has *two* peers:
66//!
67//! - [`Client`] - the client (or previous proxy in the chain)
68//! - [`Agent`] - the agent (or next proxy in the chain)
69//!
70//! When writing proxy code, you need to specify which direction:
71//!
72//! ```
73//! # use agent_client_protocol::{Proxy, Client, Agent, Conductor, ConnectTo};
74//! # use agent_client_protocol_test::MyRequest;
75//! # async fn example(transport: impl ConnectTo<Proxy>) -> Result<(), agent_client_protocol::Error> {
76//! Proxy.builder()
77//!     // Receive a request from the client
78//!     .on_receive_request_from(Client, async |req: MyRequest, responder, cx| {
79//!         // Forward it to the agent
80//!         cx.send_request_to(Agent, req)
81//!             .forward_response_to(responder)
82//!     }, agent_client_protocol::on_receive_request!())
83//!     .connect_to(transport)
84//!     .await?;
85//! # Ok(())
86//! # }
87//! ```
88//!
89//! See [Proxies and Conductors](super::proxies) for more on building proxies.
90//!
91//! # Available Peer Types
92//!
93//! | Peer Type | Represents |
94//! |-----------|------------|
95//! | [`Client`] | The client direction |
96//! | [`Agent`] | The agent direction |
97//! | [`Conductor`] | The conductor (for proxies) |
98//!
99//! # Next Steps
100//!
101//! - [Ordering](super::ordering) - Understand dispatch loop semantics
102//! - [Proxies and Conductors](super::proxies) - Build proxies that use explicit peers
103//!
104//! [`Client`]: crate::Client
105//! [`Agent`]: crate::Agent
106//! [`Conductor`]: crate::Conductor