---
title: Agent client
description: Rust SDK - Low-level agentd client reference
---

`AgentClient` is the low-level transport for talking to `agentd` through a running sandbox's relay socket. Most applications should use [`Sandbox`](/sdk/rust/sandbox), [`exec`](/sdk/rust/execution), and [`fs`](/sdk/rust/filesystem) instead. Reach for `AgentClient` when you are building a protocol-level integration or an SDK layer. [`AgentBridge`](#agentbridge) wraps the same connection in concrete, FFI-shaped types for the Node, Python, and Go bindings.

The client has two tiers that share one socket and one background reader task:

- **Typed** methods encode and decode microsandbox protocol messages for you.
- **Raw** methods move framed CBOR bytes without decoding the message body.

The raw body is the full CBOR-encoded protocol `Message` body (`v`, `t`, and `p`), not just the inner payload. The typed and raw methods reach the connection through `Deref` to the underlying client; everything below is callable directly on the value `connect_sandbox` returns.

<div className="msb-glance">

  <p className="msb-gl"><span className="msb-dot static"></span>Module functions<span className="msb-ct">2</span></p>
  <a className="msb-row" href="#agentconnect_sandbox"><span className="msb-rn">agent::connect_sandbox()</span><span className="msb-rg">resolve a name and connect</span></a>
  <a className="msb-row" href="#agentconnect_sandbox_with_timeout"><span className="msb-rn">agent::connect_sandbox_with_timeout()</span><span className="msb-rg">connect with a handshake timeout</span></a>

  <p className="msb-gl"><span className="msb-dot static"></span>Static · AgentClient<span className="msb-ct">7</span></p>
  <a className="msb-row" href="#agentclientconnect"><span className="msb-rn">AgentClient::connect()</span><span className="msb-rg">dial a socket path</span></a>
  <a className="msb-row" href="#agentclientconnect_with_timeout"><span className="msb-rn">AgentClient::connect_with_timeout()</span><span className="msb-rg">dial with a timeout</span></a>
  <a className="msb-row" href="#agentclientconnect_with_deadline"><span className="msb-rn">AgentClient::connect_with_deadline()</span><span className="msb-rg">dial with a deadline</span></a>
  <a className="msb-row" href="#agentclientconnect_sandbox"><span className="msb-rn">AgentClient::connect_sandbox()</span><span className="msb-rg">resolve a name and connect</span></a>
  <a className="msb-row" href="#agentclientconnect_sandbox_with_timeout"><span className="msb-rn">AgentClient::connect_sandbox_with_timeout()</span><span className="msb-rg">resolve a name, with timeout</span></a>
  <a className="msb-row" href="#agentclientsocket_path"><span className="msb-rn">AgentClient::socket_path()</span><span className="msb-rg">resolve a path without connecting</span></a>
  <a className="msb-row" href="#agentclientensure_version_compat_for"><span className="msb-rn">AgentClient::ensure_version_compat_for()</span><span className="msb-rg">gate a type at a generation</span></a>

  <p className="msb-gl"><span className="msb-dot instance"></span>Instance · AgentClient<span className="msb-ct">15</span></p>
  <a className="msb-row" href="#client-request"><span className="msb-rn">client.request()</span><span className="msb-rg">one-shot typed RPC</span></a>
  <a className="msb-row" href="#client-stream"><span className="msb-rn">client.stream()</span><span className="msb-rg">open a typed stream</span></a>
  <a className="msb-row" href="#client-send"><span className="msb-rn">client.send()</span><span className="msb-rg">typed follow-up message</span></a>
  <a className="msb-row" href="#client-request_raw"><span className="msb-rn">client.request_raw()</span><span className="msb-rg">one-shot raw RPC</span></a>
  <a className="msb-row" href="#client-stream_raw"><span className="msb-rn">client.stream_raw()</span><span className="msb-rg">open a raw stream</span></a>
  <a className="msb-row" href="#client-send_raw"><span className="msb-rn">client.send_raw()</span><span className="msb-rg">raw follow-up frame</span></a>
  <a className="msb-row" href="#client-ready"><span className="msb-rn">client.ready()</span><span className="msb-rg">decoded handshake payload</span></a>
  <a className="msb-row" href="#client-ready_bytes"><span className="msb-rn">client.ready_bytes()</span><span className="msb-rg">raw handshake CBOR</span></a>
  <a className="msb-row" href="#client-protocol"><span className="msb-rn">client.protocol()</span><span className="msb-rg">codec generation</span></a>
  <a className="msb-row" href="#client-is_legacy_protocol"><span className="msb-rn">client.is_legacy_protocol()</span><span className="msb-rg">pre-0.5 relay?</span></a>
  <a className="msb-row" href="#client-negotiated_version"><span className="msb-rn">client.negotiated_version()</span><span className="msb-rg">negotiated capability generation</span></a>
  <a className="msb-row" href="#client-agent_version"><span className="msb-rn">client.agent_version()</span><span className="msb-rg">runtime package version</span></a>
  <a className="msb-row" href="#client-supports"><span className="msb-rn">client.supports()</span><span className="msb-rg">message type available?</span></a>
  <a className="msb-row" href="#client-ensure_version_compat"><span className="msb-rn">client.ensure_version_compat()</span><span className="msb-rg">gate a type, error if too old</span></a>
  <a className="msb-row" href="#client-close"><span className="msb-rn">client.close()</span><span className="msb-rg">close the connection</span></a>

  <p className="msb-gl"><span className="msb-dot static"></span>Static · AgentBridge<span className="msb-ct">4</span></p>
  <a className="msb-row" href="#agentbridgeconnect_sandbox"><span className="msb-rn">AgentBridge::connect_sandbox()</span><span className="msb-rg">connect by sandbox name</span></a>
  <a className="msb-row" href="#agentbridgeconnect_sandbox_with_timeout"><span className="msb-rn">AgentBridge::connect_sandbox_with_timeout()</span><span className="msb-rg">connect by name, with timeout</span></a>
  <a className="msb-row" href="#agentbridgeconnect_path"><span className="msb-rn">AgentBridge::connect_path()</span><span className="msb-rg">connect to a socket path</span></a>
  <a className="msb-row" href="#agentbridgeconnect_path_with_timeout"><span className="msb-rn">AgentBridge::connect_path_with_timeout()</span><span className="msb-rg">connect to a path, with timeout</span></a>

  <p className="msb-gl"><span className="msb-dot instance"></span>Instance · AgentBridge<span className="msb-ct">7</span></p>
  <a className="msb-row" href="#bridge-request"><span className="msb-rn">bridge.request()</span><span className="msb-rg">one-shot raw request</span></a>
  <a className="msb-row" href="#bridge-send"><span className="msb-rn">bridge.send()</span><span className="msb-rg">follow-up frame</span></a>
  <a className="msb-row" href="#bridge-stream_open"><span className="msb-rn">bridge.stream_open()</span><span className="msb-rg">open a stream</span></a>
  <a className="msb-row" href="#bridge-stream_next"><span className="msb-rn">bridge.stream_next()</span><span className="msb-rg">pull the next frame</span></a>
  <a className="msb-row" href="#bridge-stream_close"><span className="msb-rn">bridge.stream_close()</span><span className="msb-rg">close a stream</span></a>
  <a className="msb-row" href="#bridge-ready_bytes"><span className="msb-rn">bridge.ready_bytes()</span><span className="msb-rg">raw handshake CBOR</span></a>
  <a className="msb-row" href="#bridge-close"><span className="msb-rn">bridge.close()</span><span className="msb-rg">close the connection</span></a>

  <p className="msb-gl"><span className="msb-dot type"></span>Types</p>
  <div className="msb-chiprow">
    <a className="msb-typepill" href="#agentclient">AgentClient</a>
    <a className="msb-typepill" href="#agentbridge">AgentBridge</a>
    <a className="msb-typepill" href="#bridgeframe">BridgeFrame</a>
    <a className="msb-typepill" href="#streamhandle">StreamHandle</a>
    <a className="msb-typepill" href="#agentprotocol">AgentProtocol</a>
    <a className="msb-typepill" href="#rawframe">RawFrame</a>
    <a className="msb-typepill" href="#agentclienterror">AgentClientError</a>
    <a className="msb-typepill" href="#agentclientresult">AgentClientResult</a>
  </div>

</div>

<p className="msb-label" id="typical-flow">Typical flow</p>

```rust
use microsandbox::{
    agent,
    protocol::{
        fs::{FsOp, FsRequest, FsResponse},
        message::MessageType,
    },
};

let client = agent::connect_sandbox("dev").await?;   // 1. resolve name + connect

let response = client                                // 2. one-shot typed RPC
    .request(
        MessageType::FsRequest,
        &FsRequest {
            op: FsOp::Stat {
                path: "/etc/os-release".to_string(),
                follow_symlink: true,
            },
        },
    )
    .await?;

let fs_response: FsResponse = response.payload()?;   // 3. decode the payload
client.close().await;                                // 4. close
```

## Module functions

---

#### <span className="msb-recv">agent::</span><span className="msb-hn">connect_sandbox()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_sandbox(name: &str) -> AgentClientResult<AgentClient>
```

Resolve a sandbox name to its agent relay socket path and connect, using the default ten-second handshake timeout. The socket lives under the SDK's configured runtime directory at a short, name-derived path. Sandbox names are limited to 128 UTF-8 bytes.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentclient">AgentClient</a></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::agent;

let client = agent::connect_sandbox("dev").await?;
```

</Accordion>

---

#### <span className="msb-recv">agent::</span><span className="msb-hn">connect_sandbox_with_timeout()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_sandbox_with_timeout(name: &str, timeout: Duration) -> AgentClientResult<AgentClient>
```

Like [`connect_sandbox`](#agentconnect_sandbox), but with an explicit handshake timeout instead of the ten-second default.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>timeout</code><span className="msb-type">Duration</span></div>
    <div className="msb-param-desc">Maximum time to wait for the relay handshake.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentclient">AgentClient</a></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use std::time::Duration;
use microsandbox::agent;

let client = agent::connect_sandbox_with_timeout("dev", Duration::from_secs(2)).await?;
```

</Accordion>

## AgentClient: static methods

---

#### <span className="msb-recv">AgentClient::</span><span className="msb-hn">connect()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect(sock_path: impl AsRef<Path>) -> AgentClientResult<AgentClient>
```

Connect to an arbitrary agent relay socket by path, using the default ten-second handshake timeout. The connection performs the relay handshake, validates the cached `core.ready` frame, and starts one background reader task.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>sock_path</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div>
    <div className="msb-param-desc">Path to the agent relay socket.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentclient">AgentClient</a></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::agent::AgentClient;

let path = AgentClient::socket_path("dev")?;
let client = AgentClient::connect(&path).await?;
```

</Accordion>

---

#### <span className="msb-recv">AgentClient::</span><span className="msb-hn">connect_with_timeout()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_with_timeout(sock_path: impl AsRef<Path>, timeout: Duration) -> AgentClientResult<AgentClient>
```

Connect to an arbitrary agent relay socket by path with an explicit handshake timeout.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>sock_path</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div>
    <div className="msb-param-desc">Path to the agent relay socket.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>timeout</code><span className="msb-type">Duration</span></div>
    <div className="msb-param-desc">Maximum time to wait for the relay handshake.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentclient">AgentClient</a></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

---

#### <span className="msb-recv">AgentClient::</span><span className="msb-hn">connect_with_deadline()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_with_deadline(sock_path: impl AsRef<Path>, deadline: Instant) -> AgentClientResult<AgentClient>
```

Connect to an arbitrary agent relay socket by path with an explicit handshake deadline. The deadline bounds both handshake reads, so an accepted connection that stalls before writing the handshake bytes cannot block this call indefinitely.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>sock_path</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div>
    <div className="msb-param-desc">Path to the agent relay socket.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>deadline</code><span className="msb-type">Instant</span></div>
    <div className="msb-param-desc">Tokio instant by which the handshake must complete.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentclient">AgentClient</a></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

---

#### <span className="msb-recv">AgentClient::</span><span className="msb-hn">connect_sandbox()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_sandbox(name: &str) -> AgentClientResult<AgentClient>
```

Resolve a sandbox name to its agent socket path and connect. Equivalent to the module-level [`agent::connect_sandbox`](#agentconnect_sandbox).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentclient">AgentClient</a></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

---

#### <span className="msb-recv">AgentClient::</span><span className="msb-hn">connect_sandbox_with_timeout()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_sandbox_with_timeout(name: &str, timeout: Duration) -> AgentClientResult<AgentClient>
```

Resolve a sandbox name to its agent socket path and connect with an explicit handshake timeout. Equivalent to the module-level [`agent::connect_sandbox_with_timeout`](#agentconnect_sandbox_with_timeout).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>timeout</code><span className="msb-type">Duration</span></div>
    <div className="msb-param-desc">Maximum time to wait for the relay handshake.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentclient">AgentClient</a></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

---

#### <span className="msb-recv">AgentClient::</span><span className="msb-hn">socket_path()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span></div>

```rust
fn socket_path(name: &str) -> MicrosandboxResult<PathBuf>
```

Resolve a sandbox's relay socket path **without connecting**. Returns the same path [`connect_sandbox`](#agentconnect_sandbox) would dial: the hashed path under the runtime directory when it fits the platform's Unix-socket length limit, and the legacy name-derived path otherwise. Useful for talking to `agentd` over a raw byte transport (for example a transparent relay that splices bytes to and from the socket) instead of this frame client. The sandbox need not be running.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">PathBuf</span></div>
    <div className="msb-param-desc">Relay socket path.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::agent::AgentClient;

let path = AgentClient::socket_path("dev")?;
println!("{}", path.display());
```

</Accordion>

---

#### <span className="msb-recv">AgentClient::</span><span className="msb-hn">ensure_version_compat_for()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span></div>

```rust
fn ensure_version_compat_for(t: MessageType, negotiated: u8) -> AgentClientResult<()>
```

Check a message type against an explicit negotiated generation. The single place the rule lives, exposed for callers that hold the negotiated generation but not a live client. Returns [`AgentClientError::UnsupportedOperation`](#agentclienterror) if the type was introduced after the given generation.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>t</code><span className="msb-type">MessageType</span></div>
    <div className="msb-param-desc">Protocol message type to gate.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>negotiated</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Protocol generation to check against.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::{agent::AgentClient, protocol::message::MessageType};

AgentClient::ensure_version_compat_for(MessageType::FsRequest, 2)?;
```

</Accordion>

## AgentClient: instance methods

---

#### <span className="msb-recv">client.</span><span className="msb-hn">request()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn request<T: Serialize>(&self, t: MessageType, payload: &T) -> AgentClientResult<Message>
```

Send one typed protocol message and wait for one response frame with the same correlation id. Flags are derived from the message type. Use this for one-shot RPCs such as filesystem stat or list requests. Fails fast with [`AgentClientError::UnsupportedOperation`](#agentclienterror) if the connected sandbox is too old for the message type.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>t</code><span className="msb-type">MessageType</span></div>
    <div className="msb-param-desc">Protocol message type.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>payload</code><span className="msb-type">&amp;T: Serialize</span></div>
    <div className="msb-param-desc">Message payload, serialized with CBOR.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">Message</span></div>
    <div className="msb-param-desc">Decoded response message.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::protocol::{
    fs::{FsOp, FsRequest, FsResponse},
    message::MessageType,
};

let response = client
    .request(
        MessageType::FsRequest,
        &FsRequest {
            op: FsOp::Stat {
                path: "/etc/os-release".to_string(),
                follow_symlink: true,
            },
        },
    )
    .await?;
let fs_response: FsResponse = response.payload()?;
```

</Accordion>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">stream()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn stream<T: Serialize>(&self, t: MessageType, payload: &T) -> AgentClientResult<(u32, Receiver<Message>)>
```

Open a typed streaming session. The returned id is the protocol correlation id. Use it with [`send()`](#client-send) for follow-up messages such as stdin, resize, signal, or file data chunks. The receiver yields messages until a terminal frame is delivered or the connection closes.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>t</code><span className="msb-type">MessageType</span></div>
    <div className="msb-param-desc">Protocol message type for the opening frame.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>payload</code><span className="msb-type">&amp;T: Serialize</span></div>
    <div className="msb-param-desc">Opening message payload, serialized with CBOR.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">(u32, Receiver&lt;Message&gt;)</span></div>
    <div className="msb-param-desc">Correlation id and a typed message receiver.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::protocol::{exec::ExecRequest, message::MessageType};

let (id, mut rx) = client
    .stream(MessageType::ExecRequest, &ExecRequest {
        cmd: "echo".into(),
        args: vec!["hi".into()],
        env: Vec::new(),
        cwd: None,
        user: None,
        tty: false,
        rows: 24,
        cols: 80,
        rlimits: Vec::new(),
    })
    .await?;

while let Some(msg) = rx.recv().await {
    println!("{:?}", msg.t);
}
```

</Accordion>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">send()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn send<T: Serialize>(&self, id: u32, t: MessageType, payload: &T) -> AgentClientResult<()>
```

Send a typed follow-up message on an existing correlation id (the id returned by [`stream()`](#client-stream)).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>id</code><span className="msb-type">u32</span></div>
    <div className="msb-param-desc">Correlation id from the open stream.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>t</code><span className="msb-type">MessageType</span></div>
    <div className="msb-param-desc">Protocol message type.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>payload</code><span className="msb-type">&amp;T: Serialize</span></div>
    <div className="msb-param-desc">Message payload, serialized with CBOR.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::protocol::{exec::ExecStdin, message::MessageType};

client.send(id, MessageType::ExecStdin, &ExecStdin { data: b"input\n".to_vec() }).await?;
```

</Accordion>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">request_raw()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn request_raw(&self, flags: u8, body: Vec<u8>) -> AgentClientResult<RawFrame>
```

Allocate a correlation id, send one raw frame with `(flags, body)`, and wait for one raw response frame with the matching id. CBOR encoding and decoding are left to the caller.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>flags</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Frame flag byte.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">Vec&lt;u8&gt;</span></div>
    <div className="msb-param-desc">CBOR-encoded protocol message body.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#rawframe">RawFrame</a></div>
    <div className="msb-param-desc">Raw response frame.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let frame = client.request_raw(flags, body).await?;
println!("id={} flags={}", frame.id, frame.flags);
```

</Accordion>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">stream_raw()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn stream_raw(&self, flags: u8, body: Vec<u8>) -> AgentClientResult<(u32, Receiver<RawFrame>)>
```

Open a raw streaming session. The receiver yields raw frames for the returned correlation id until a frame with the terminal flag arrives or the receiver is dropped. Use [`send_raw()`](#client-send_raw) with the returned id to send follow-up frames.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>flags</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Frame flag byte for the opening frame.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">Vec&lt;u8&gt;</span></div>
    <div className="msb-param-desc">CBOR-encoded protocol message body.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">(u32, Receiver&lt;RawFrame&gt;)</span></div>
    <div className="msb-param-desc">Correlation id and a raw frame receiver.</div>
  </div>
</div>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">send_raw()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn send_raw(&self, id: u32, flags: u8, body: &[u8]) -> AgentClientResult<()>
```

Send a raw follow-up frame on an existing correlation id (the id returned by [`stream_raw()`](#client-stream_raw)).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>id</code><span className="msb-type">u32</span></div>
    <div className="msb-param-desc">Correlation id from the open raw stream.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>flags</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Frame flag byte.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">&amp;[u8]</span></div>
    <div className="msb-param-desc">CBOR-encoded protocol message body.</div>
  </div>
</div>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">ready()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn ready(&self) -> AgentClientResult<Ready>
```

Return the decoded `core.ready` payload captured during the handshake (boot timings and the runtime's self-reported version).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">Ready</span></div>
    <div className="msb-param-desc">Decoded handshake payload.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let ready = client.ready()?;
println!("boot {} ns", ready.boot_time_ns);
```

</Accordion>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">ready_bytes()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn ready_bytes(&self) -> &[u8]
```

Return the cached handshake `core.ready` frame body as CBOR bytes. Useful for bindings that want to deserialize the ready payload with their own CBOR tooling. For typed access, use [`ready()`](#client-ready).

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">&amp;[u8]</span></div>
    <div className="msb-param-desc">CBOR-encoded ready frame body.</div>
  </div>
</div>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">protocol()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn protocol(&self) -> AgentProtocol
```

The agent protocol generation (wire codec) negotiated for this connection.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentprotocol">AgentProtocol</a></div>
    <div className="msb-param-desc">Codec generation: <code>Current</code> or <code>LegacyV1</code>.</div>
  </div>
</div>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">is_legacy_protocol()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn is_legacy_protocol(&self) -> bool
```

Whether this connection is using the legacy pre-0.5 protocol.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">bool</span></div>
    <div className="msb-param-desc"><code>true</code> if the relay speaks the pre-0.5 protocol.</div>
  </div>
</div>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">negotiated_version()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn negotiated_version(&self) -> u8
```

The negotiated protocol generation for this connection: the lower of what this client speaks and what the sandbox advertised at handshake. This is the capability gate that drives [`supports()`](#client-supports) and the typed send path, and it is distinct from [`protocol()`](#client-protocol), which selects the wire codec.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Negotiated capability generation.</div>
  </div>
</div>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">agent_version()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn agent_version(&self) -> &str
```

The runtime's self-reported package version, taken from its `core.ready` frame. Empty when the runtime predates this field (an older agent), in which case fall back to the generation for diagnostics.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Runtime package version, or empty if unknown.</div>
  </div>
</div>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">supports()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn supports(&self, t: MessageType) -> bool
```

Whether the connected sandbox is new enough to handle the given message type. The single source of truth for feature gating: callers that cannot gate by sending (for example the SSH/SFTP layer) consult this instead of inspecting the protocol generation directly.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>t</code><span className="msb-type">MessageType</span></div>
    <div className="msb-param-desc">Protocol message type to check.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">bool</span></div>
    <div className="msb-param-desc"><code>true</code> if the runtime can handle the type.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::protocol::message::MessageType;

if client.supports(MessageType::FsRequest) {
    // safe to issue filesystem RPCs
}
```

</Accordion>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">ensure_version_compat()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn ensure_version_compat(&self, t: MessageType) -> AgentClientResult<()>
```

Reject a message type the connected sandbox is too old to handle, against this connection's negotiated generation. Fails before any bytes are sent, so only that one operation fails and the session continues. The typed [`request()`](#client-request), [`stream()`](#client-stream), and [`send()`](#client-send) methods call this internally.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>t</code><span className="msb-type">MessageType</span></div>
    <div className="msb-param-desc">Protocol message type to gate.</div>
  </div>
</div>

<Accordion title="Example">

```rust
use microsandbox::protocol::message::MessageType;

client.ensure_version_compat(MessageType::TcpConnect)?;
```

</Accordion>

---

#### <span className="msb-recv">client.</span><span className="msb-hn">close()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn close(self)
```

Close the client by consuming it. Drops the writer and aborts the reader task; any in-flight requests resolve with [`AgentClientError::Closed`](#agentclienterror). Dropping the client has the same effect.

<Accordion title="Example">

```rust
client.close().await;
```

</Accordion>

## AgentBridge

Bytes-in/bytes-out wrapper around [`AgentClient`](#agentclient), with concrete, monomorphic types suitable for crossing FFI boundaries. The Node, Python, and Go bindings build on it. No generics, no consuming-`self` methods, no callbacks across FFI: each method takes `&self` and is idempotent where the underlying operation allows. CBOR (de)serialization happens entirely in the caller's language; the bridge only moves bytes. One instance owns one Unix-socket connection; multiple concurrent streams are supported, each identified by an opaque [`StreamHandle`](#streamhandle).

---

#### <span className="msb-recv">AgentBridge::</span><span className="msb-hn">connect_sandbox()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_sandbox(name: &str) -> AgentClientResult<AgentBridge>
```

Connect to a sandbox by name, resolving the socket path from SDK config. Sandbox names are limited to 128 UTF-8 bytes.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentbridge">AgentBridge</a></div>
    <div className="msb-param-desc">Connected bridge.</div>
  </div>
</div>

---

#### <span className="msb-recv">AgentBridge::</span><span className="msb-hn">connect_sandbox_with_timeout()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_sandbox_with_timeout(name: &str, timeout: Duration) -> AgentClientResult<AgentBridge>
```

Connect to a sandbox by name with an explicit handshake timeout.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>name</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>timeout</code><span className="msb-type">Duration</span></div>
    <div className="msb-param-desc">Maximum time to wait for the relay handshake.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentbridge">AgentBridge</a></div>
    <div className="msb-param-desc">Connected bridge.</div>
  </div>
</div>

---

#### <span className="msb-recv">AgentBridge::</span><span className="msb-hn">connect_path()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_path(path: &str) -> AgentClientResult<AgentBridge>
```

Connect to an arbitrary agentd relay socket by path.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Path to the agent relay socket.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentbridge">AgentBridge</a></div>
    <div className="msb-param-desc">Connected bridge.</div>
  </div>
</div>

---

#### <span className="msb-recv">AgentBridge::</span><span className="msb-hn">connect_path_with_timeout()</span>
<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>

```rust
async fn connect_path_with_timeout(path: &str, timeout: Duration) -> AgentClientResult<AgentBridge>
```

Connect to an arbitrary agentd relay socket by path with an explicit handshake timeout.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>path</code><span className="msb-type">&amp;str</span></div>
    <div className="msb-param-desc">Path to the agent relay socket.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>timeout</code><span className="msb-type">Duration</span></div>
    <div className="msb-param-desc">Maximum time to wait for the relay handshake.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#agentbridge">AgentBridge</a></div>
    <div className="msb-param-desc">Connected bridge.</div>
  </div>
</div>

---

#### <span className="msb-recv">bridge.</span><span className="msb-hn">request()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn request(&self, flags: u8, body: Vec<u8>) -> AgentClientResult<BridgeFrame>
```

One-shot request: send `(flags, body)` and wait for one response frame.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>flags</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Frame flag byte.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">Vec&lt;u8&gt;</span></div>
    <div className="msb-param-desc">CBOR-encoded protocol message body.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><a className="msb-type" href="#bridgeframe">BridgeFrame</a></div>
    <div className="msb-param-desc">Response frame.</div>
  </div>
</div>

---

#### <span className="msb-recv">bridge.</span><span className="msb-hn">send()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn send(&self, id: u32, flags: u8, body: Vec<u8>) -> AgentClientResult<()>
```

Send a follow-up frame on an existing correlation id.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>id</code><span className="msb-type">u32</span></div>
    <div className="msb-param-desc">Correlation id from an open stream.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>flags</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Frame flag byte.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">Vec&lt;u8&gt;</span></div>
    <div className="msb-param-desc">CBOR-encoded protocol message body.</div>
  </div>
</div>

---

#### <span className="msb-recv">bridge.</span><span className="msb-hn">stream_open()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn stream_open(&self, flags: u8, body: Vec<u8>) -> AgentClientResult<(u32, StreamHandle)>
```

Open a streaming session. Returns the protocol correlation id (for follow-up sends via [`send()`](#bridge-send)) and an opaque stream handle (for [`stream_next()`](#bridge-stream_next) and [`stream_close()`](#bridge-stream_close)).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>flags</code><span className="msb-type">u8</span></div>
    <div className="msb-param-desc">Frame flag byte for the opening frame.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">Vec&lt;u8&gt;</span></div>
    <div className="msb-param-desc">CBOR-encoded protocol message body.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">(u32, <a className="msb-type" href="#streamhandle">StreamHandle</a>)</span></div>
    <div className="msb-param-desc">Correlation id and an opaque stream handle.</div>
  </div>
</div>

---

#### <span className="msb-recv">bridge.</span><span className="msb-hn">stream_next()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn stream_next(&self, handle: StreamHandle) -> AgentClientResult<Option<BridgeFrame>>
```

Pull the next frame from a stream. Returns `None` when the stream has ended (the terminal frame was already delivered, or the stream was closed or dropped).

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>handle</code><a className="msb-type" href="#streamhandle">StreamHandle</a></div>
    <div className="msb-param-desc">Handle returned by <a href="#bridge-stream_open"><code>stream_open()</code></a>.</div>
  </div>
</div>

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">Option&lt;<a className="msb-type" href="#bridgeframe">BridgeFrame</a>&gt;</span></div>
    <div className="msb-param-desc">Next frame, or <code>None</code> at end of stream.</div>
  </div>
</div>

<Accordion title="Example">

```rust
let (id, handle) = bridge.stream_open(flags, body).await?;
while let Some(frame) = bridge.stream_next(handle).await? {
    // decode frame.body with your own CBOR tooling
}
```

</Accordion>

---

#### <span className="msb-recv">bridge.</span><span className="msb-hn">stream_close()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn stream_close(&self, handle: StreamHandle)
```

Close a stream and drop its handle. Idempotent.

<p className="msb-label">Parameters</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><code>handle</code><a className="msb-type" href="#streamhandle">StreamHandle</a></div>
    <div className="msb-param-desc">Handle returned by <a href="#bridge-stream_open"><code>stream_open()</code></a>.</div>
  </div>
</div>

---

#### <span className="msb-recv">bridge.</span><span className="msb-hn">ready_bytes()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>

```rust
fn ready_bytes(&self) -> AgentClientResult<Vec<u8>>
```

The cached handshake `core.ready` frame body bytes (CBOR). Errors with [`AgentClientError::Closed`](#agentclienterror) if the bridge has been closed.

<p className="msb-label">Returns</p>

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">Vec&lt;u8&gt;</span></div>
    <div className="msb-param-desc">CBOR-encoded ready frame body.</div>
  </div>
</div>

---

#### <span className="msb-recv">bridge.</span><span className="msb-hn">close()</span>
<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>

```rust
async fn close(&self)
```

Close the connection. Idempotent. After close, every operation except another close returns [`AgentClientError::Closed`](#agentclienterror).

<Accordion title="Example">

```rust
bridge.close().await;
```

</Accordion>

## Types

---

### AgentClient
<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#agentconnect_sandbox">agent::connect_sandbox()</a>, <a href="#agentclientconnect">AgentClient::connect()</a> · wrapped by <a href="#agentbridge">AgentBridge</a></p>

Client for communicating with `agentd` through a running sandbox's relay. A newtype over the underlying `microsandbox_agent_client::AgentClient`; the typed and raw transport methods reach the inner client through `Deref`. See the [static](#agentclient-static-methods) and [instance](#agentclient-instance-methods) method sections above.

---

### BridgeFrame
<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#bridge-request">bridge.request()</a>, <a href="#bridge-stream_next">bridge.stream_next()</a></p>

FFI-friendly view of a [`RawFrame`](#rawframe): id, flags, body bytes.

| Field | Type | Description |
| --- | --- | --- |
| `id` | `u32` | Correlation ID from the frame header. |
| `flags` | `u8` | Frame flags from the frame header. |
| `body` | `Vec<u8>` | Raw CBOR-encoded body bytes. |

---

### StreamHandle
<div className="msb-tags"><span className="msb-tag is-type">type alias</span></div>

<p className="msb-backref">Returned by <a href="#bridge-stream_open">bridge.stream_open()</a> · used by <a href="#bridge-stream_next">bridge.stream_next()</a>, <a href="#bridge-stream_close">bridge.stream_close()</a></p>

```rust
pub type StreamHandle = u64;
```

Opaque handle identifying an open stream on an [`AgentBridge`](#agentbridge). Foreign-language wrappers reference streams by this `u64` instead of owning a tokio receiver.

---

### AgentProtocol
<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Returned by <a href="#client-protocol">client.protocol()</a></p>

Agent protocol generation (wire codec) spoken by a connected sandbox relay.

| Variant | Description |
| --- | --- |
| `Current` | Current protocol generation. |
| `LegacyV1` | Pre-0.5 microsandbox relay handshake and agent protocol. |

---

### RawFrame
<div className="msb-tags"><span className="msb-tag is-type">struct</span></div>

<p className="msb-backref">Returned by <a href="#client-request_raw">client.request_raw()</a>, <a href="#client-stream_raw">client.stream_raw()</a></p>

A framed protocol message at the byte level. `id` is the protocol correlation id, `flags` is the frame flag byte, and `body` is the CBOR-encoded protocol message body. Re-exported from `microsandbox::protocol::codec`.

| Field | Type | Description |
| --- | --- | --- |
| `id` | `u32` | Protocol correlation id. |
| `flags` | `u8` | Frame flag byte. |
| `body` | `Vec<u8>` | CBOR-encoded protocol message body. |

---

### AgentClientError
<div className="msb-tags"><span className="msb-tag is-type">enum</span></div>

<p className="msb-backref">Error variant of <a href="#agentclientresult">AgentClientResult</a></p>

Errors raised by [`AgentClient`](#agentclient) and [`AgentBridge`](#agentbridge).

| Variant | Description |
| --- | --- |
| `Connect { path, source }` | Failed to open the Unix socket connection to the relay. |
| `Handshake(String)` | Handshake with the relay failed (timeout, EOF, or malformed frame). |
| `SandboxNotFound(String)` | Sandbox name could not be resolved to an agent socket path. |
| `InvalidSandboxName(String)` | Sandbox name failed SDK validation before socket resolution. |
| `Io(std::io::Error)` | An I/O error occurred on the socket after connect. |
| `Protocol(ProtocolError)` | A wire-protocol error (framing, CBOR, oversize frame). |
| `Cbor(String)` | CBOR encoding or decoding failed. |
| `InvalidPacket(String)` | The supplied packet did not contain exactly one complete transport frame. |
| `UnsupportedOperation { msg_type, needs, peer }` | The connected sandbox's runtime is older than the requested feature needs; restart the sandbox to update its runtime. |
| `ReaderClosed(u32)` | The reader task closed before the in-flight request received its response. |
| `Closed` | The client has been closed. |
| `IdRangeExhausted` | The relay-assigned correlation ID range has no available IDs. |
| `NotImplemented(&'static str)` | The operation is not implemented yet. |

---

### AgentClientResult
<div className="msb-tags"><span className="msb-tag is-type">type alias</span></div>

<p className="msb-backref">Returned by most <a href="#agentclient">AgentClient</a> and <a href="#agentbridge">AgentBridge</a> methods</p>

```rust
pub type AgentClientResult<T> = Result<T, AgentClientError>;
```

Result alias for agent client operations. The error is [`AgentClientError`](#agentclienterror).
