This document covers the v2 APIs for building agent integrations with connection pooling, multiple transports, and reverse connections.
Quick Start
use ;
use Duration;
async
AgentPool
The AgentPool is the primary interface for v2 agent communication. It manages connections, load balancing, health tracking, and metrics.
Creating a Pool
use ;
// Default configuration
let pool = new;
// Custom configuration
let config = AgentPoolConfig ;
let pool = with_config;
Adding Agents
// gRPC agent (detected by host:port format)
pool.add_agent.await?;
pool.add_agent.await?;
// UDS agent (detected by path format)
pool.add_agent.await?;
// Explicit transport selection
pool.add_grpc_agent.await?;
pool.add_uds_agent.await?;
Sending Requests
use RequestHeaders;
let headers = RequestHeaders ;
// Send to specific agent
let response = pool.send_request_headers.await?;
// Send body chunks
let chunk = RequestBodyChunk ;
let response = pool.send_request_body_chunk.await?;
Cancelling Requests
// Cancel specific request
pool.cancel_request.await?;
// Cancel all requests for an agent
pool.cancel_all.await?;
Pool Methods
| Method | Description |
|---|---|
new() | Create pool with default config |
with_config(config) | Create pool with custom config |
add_agent(name, endpoint) | Add agent with auto-detected transport |
add_grpc_agent(name, endpoint, tls) | Add gRPC agent explicitly |
add_uds_agent(name, path) | Add UDS agent explicitly |
add_reverse_connection(name, client, caps) | Add reverse-connected agent |
remove_agent(name) | Remove agent from pool |
send_request_headers(agent, headers) | Send request headers |
send_request_body_chunk(agent, chunk) | Send request body chunk |
cancel_request(agent, request_id) | Cancel specific request |
cancel_all(agent) | Cancel all requests |
get_health(agent) | Get agent health status |
metrics_collector() | Get metrics collector reference |
AgentClientV2 (gRPC)
Low-level gRPC client for direct use without pooling.
Creating a Client
use AgentClientV2;
let client = connect.await?;
// With TLS
let client = connect_with_tls.await?;
Sending Messages
// Send request headers
let response = client.send_request_headers.await?;
// Send body chunk
let response = client.send_request_body_chunk.await?;
// Cancel request
client.cancel_request.await?;
AgentClientV2Uds (Unix Domain Socket)
Low-level UDS client for direct use without pooling.
Creating a Client
use AgentClientV2Uds;
let client = connect.await?;
Handshake
The UDS client performs automatic handshake on connection:
// Handshake is automatic, but you can query capabilities
let capabilities = client.capabilities;
println!;
println!;
println!;
ReverseConnectionListener
Accepts inbound connections from agents.
Creating a Listener
use ;
let config = ReverseConnectionConfig ;
let listener = bind_uds.await?;
Accepting Connections
// Accept a single connection
let = listener.accept.await?;
println!;
// Add to pool
pool.add_reverse_connection.await?;
Configuration Types
AgentPoolConfig
LoadBalanceStrategy
Metrics
MetricsCollector
let metrics = pool.metrics_collector;
// Get metrics snapshot
let snapshot = metrics.snapshot;
println!;
println!;
// Export in Prometheus format
let prometheus_output = metrics.export_prometheus;
Available Metrics
| Metric | Type | Description |
|---|---|---|
agent_requests_total | Counter | Total requests by agent and decision |
agent_request_duration_seconds | Histogram | Request latency distribution |
agent_connections_active | Gauge | Current active connections |
agent_errors_total | Counter | Error counts by type |
agent_circuit_breaker_state | Gauge | Circuit breaker state (0=closed, 1=open) |
Error Handling
V2-Specific Errors
Pool Error Handling
match pool.send_request_headers.await
Header Utilities
The library provides zero-allocation header handling for common HTTP headers.
Common Header Names
Pre-defined static strings for standard headers avoid allocations:
use names;
// Use static strings directly
let content_type = CONTENT_TYPE; // "content-type"
let authorization = AUTHORIZATION; // "authorization"
let x_request_id = X_REQUEST_ID; // "x-request-id"
Header Name Interning
The intern_header_name function returns borrowed references for known headers:
use intern_header_name;
use Cow;
let name = intern_header_name;
// Returns Cow::Borrowed("content-type") - no allocation
let custom = intern_header_name;
// Returns Cow::Owned("x-custom-header") - allocates only for unknown headers
Cow Header Maps
For high-throughput scenarios, use CowHeaderMap to minimize allocations:
use ;
let mut headers: CowHeaderMap = new;
headers.insert;
// Convert from standard HashMap
let cow_headers = to_cow_optimized;
// Convert back when needed
let standard = from_cow_optimized;
Available Header Constants
| Constant | Value |
|---|---|
CONTENT_TYPE | “content-type” |
CONTENT_LENGTH | “content-length” |
AUTHORIZATION | “authorization” |
ACCEPT | “accept” |
HOST | “host” |
USER_AGENT | “user-agent” |
X_REQUEST_ID | “x-request-id” |
X_FORWARDED_FOR | “x-forwarded-for” |
| … | (32 total) |
Memory-Mapped Buffers
For large request/response bodies, memory-mapped buffers minimize heap allocation.
Feature flag required:
[]
= { = "0.3", = ["mmap-buffers"] }
Basic Usage
use ;
// Configure threshold for switching to mmap
let config = LargeBodyBufferConfig ;
let mut buffer = with_config;
// Write chunks - automatically switches to mmap when needed
buffer.write_chunk?;
// Read back - seamless regardless of storage type
let data = buffer.as_slice?;
Configuration Options
| Option | Default | Description |
|---|---|---|
mmap_threshold | 1MB | Size above which to use memory-mapped files |
max_body_size | 100MB | Maximum allowed body size |
temp_dir | None | Custom temp directory for mmap files |
Storage Behavior
| Body Size | Storage | Allocation |
|---|---|---|
| < threshold | Vec<u8> | Heap memory |
| >= threshold | mmap’d file | OS page cache |
Methods
| Method | Description |
|---|---|
new() | Create buffer with default config |
with_config(config) | Create buffer with custom config |
write_chunk(data) | Write data (auto-transitions to mmap) |
as_slice() | Get immutable slice of data |
as_mut_slice() | Get mutable slice (forces to memory) |
into_vec() | Take ownership as Vec |
clear() | Reset buffer |
len() | Current data size |
is_empty() | Check if empty |
is_mmap() | Check if using mmap storage |
When to Use
| Scenario | Recommendation |
|---|---|
| File uploads | Use with 1MB threshold |
| API responses | Use with default config |
| Streaming bodies | Accumulate chunks, then read |
| Memory-constrained | Lower threshold (e.g., 256KB) |
Migration from v1
Before (v1)
use AgentClient;
let client = unix_socket.await?;
let response = client.send_event.await?;
After (v2 with pooling)
use AgentPool;
let pool = new;
pool.add_agent.await?;
let response = pool.send_request_headers.await?;