Request-Response
The request-response service enables a direct, unicast exchange of data between two nodes. Unlike pub-sub, which broadcasts to many subscribers, request-response expects a direct response for every request sent.
This pattern is especially useful when a node wants to request another node’s ability to handle a specific task e.g., checking battery levels, resource availability, or configuration setting.
The Request-Response service
from hyveos_sdk import Connectionimport asyncio
async with Connection() as connection: req_resp = connection.get_request_response_service()
# continue with usage of req_resp # TODOuse hyveos_sdk::Connection;
#[tokio::main]async fn main() { let connection = Connection::new().await.unwrap(); let mut req_resp = connection.req_resp();
// continue with usage of req_resp // todo!()}import { Client } from 'hyveos-sdk'import { Connection } from 'hyveos-web'
async function main() { const transport = new Connection('http://localhost:8080') const client = new Client(transport) const reqResp = client.reqresp
// continue with usage of reqResp // TODO}Example 1. Obtain the Request-Response service handler. Note the async environment.
Sending Requests
To query a specific node for data or ask it to perform an action, send a request. Typically, it will hold the target peer’s ID and an optional topic
to which that peer is registered. Topics can and should mainly be used to logically group requests.
The receiving peer must be subscribed to the topic specified in the request in order to receive the request.
from hyveos_sdk import Connectionimport asyncio
async with Connection() as connection: req_resp = connection.get_request_response_service()
peer_id = "0123456789ABCDEF" topic = "robot_status" message_data = "give_status"
response = await req_resp.send_request(peer_id, message_data, topic)
response_data = loads(response.data.data) print(f"Received response: {response_data}")
asyncio.run(main())use hyveos_sdk::Connection;use futures::StreamExt as _;
#[tokio::main]async fn main() { let connection = Connection::new().await.unwrap(); let mut req_resp = connection.req_resp();
let peer_id = String::from("0123456789ABCDEF"); let topic = Some("robot_status"); let message_data = String::from("give_status");
let response = req_resp.send_request(peer_id, message_data, topic).await.unwrap();
let data = Result::from(response).unwrap(); println!("Received response: {}", String::from_utf8(data).unwrap());}import { Client } from 'hyveos-sdk'import { Connection } from 'hyveos-web'
async function main() { const transport = new Connection('http://localhost:8080') const client = new Client(transport) const reqResp = client.reqresp
const peerId = "0123456789ABCDEF" const topic = "robot_status" const messageData = "give_status"
const response = await reqResp.request(peerId, messageData, topic)
const decodedResponse = new TextDecoder().decode(response) console.log('Received response:', decodedResponse)}Example 2. Simple request of status information through request/response without error handling.
You might want to include try/catch in actual production code.
Receiving & Responding to Requests
The remote node will have to react to the sent request.
Workflow
- Receive the message through an incoming stream at the remote node
- Process the message
- Respond, with a handler (currently in Rust and Typescript, but not Python yet)
Receive a Request
Messages will be received through a stream of inbound receive messages.
from hyveos_sdk import Connectionimport asyncio
async def main(): async with Connection() as connection: req_resp = connection.get_request_response_service()
topic = "robot_status"
async with req_resp.receive(topic) as requests: # Handle stream of incoming requests -> RecvRequest # TODO pass
asyncio.run(main())use hyveos_sdk::Connection;use futures::TryStreamExt as _;
#[tokio::main]async fn main() { let connection = Connection::new().await.unwrap(); let mut req_resp = connection.req_resp();
let topic = Some("robot_status"); let mut request_stream = req_resp.recv(topic).await.unwrap();
// Handle stream of incoming requests -> InboundRequest // todo!()}import { Client } from 'hyveos-sdk'import { Connection } from 'hyveos-web'
async function main() { const transport = new Connection('http://localhost:8080') const client = new Client(transport) const reqResp = client.reqresp
const topic = "robot_status"
const requestStream = reqResp.recv(topic)
// Handle stream of incoming requests -> IncomingRequestHandle // TODO}Example 3. Receiving the request of giving the status information. Example 4 below will explain the processing of inbound requests.
Process Inbound Request
In the Pyhton SDK, you explicitly receive a seq number upon receive().
seq is then given in respond() for matching the request to the eventual response.
The Rust and Typescript SDKs have a InboundRequestHandle object for takes care of this.
Each inbound message in Rust comes in a (request, handle) pair.
request is of type InboundRequest, handle is of type InboundRequestHandle.
Retrieve the the fields of request when handling the inbound request.
# continuing Example 3 async for request in requests: print(f"Request from {request.peer.peer_id}") seq = request.seq received = request.msg print(f"Data: {received}")
# respond with seq # TODO // continuing Example 3 while let Some(Ok(request, handle)) = request_stream.try_next().await.unwrap() { println!("Request from {} on topic {:?}", request.peer_id, request.topic);
let received = String::from_utf8(request.data).unwrap_or_default(); println!("Data: {}", received);
// For responding, use the handler // todo!() // continuing Example 3 for await (const request of requestStream) { console.log(`Request from ${request.peerId} on topic ${request.topic}`)
const received = new TextDecoder().decode(request.data) console.log(`Data: ${received}`)
// For responding, use the handler // TODOExample 4. Retrieving fields from the request. In Rust and Typescript, this means
leveraging InboundRequest.
Responding to a request
# Continuing from Example 4 if received is "give_status": await req_resp.respond(seq, "All systems operational.") else: await req_resp.respond(seq, None, "Unknown request") # Error // Continuing from Example 4 if received == "give_status" { handle.respond("All systems operational.".as_bytes()).await.unwrap(); } else { handle.respond_with_error("Unknown request").await.unwrap(); } }} // Continuing from Example 4 if (received === "give_status") { await reqResp.respond(new TextEncoder().encode('All systems operational.')) } else { await request.error('Unknown request') } }}Example 5. Use the InboundRequestHandle for responding. In Rust and Typescript, you can respond with an error as well.
Note that in Python in case of an error, you can leave the data argument to None and give an error message in the
last argument—here: "Unknown request".
Pyhton responding incorporates explicitly giving the seq number in the argument of respond().
JSON and CBOR Request/Response Services
While raw bytes give you flexibility, you’ll often want structured data. hyveOS offers typed request/response services for JSON and CBOR.
The same code examples apply analogously.
All methods send_request(), recv() and respond() are in called the same way for
these services. The JSON and CBOR services are just convenient data format wrapper services.
© 2025 P2P Industries. This documentation is licensed under the MIT License.
Cookie Policy
Privacy Policy