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

Low-level raw CBOR transport for communicating with `agentd` through a sandbox relay.

## Constants

| Name | Value | Description |
|------|-------|-------------|
| `FLAG_TERMINAL` | `0b0000_0001` | Last frame for a correlation id |
| `FLAG_SESSION_START` | `0b0000_0010` | First frame of a streaming session |
| `FLAG_SHUTDOWN` | `0b0000_0100` | Shutdown frame |

## AgentClient

#### <span className="msb-recv">AgentClient.</span><span className="msb-hn">connect_sandbox()</span>

<Tooltip tip="Connecting an agent client by socket path is local-only; on microsandbox cloud the SDK uses the agent WebSocket route internally."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

```python
@classmethod
async def connect_sandbox(cls, name: str, *, timeout: float | None = None) -> AgentClient
```

<Accordion title="Example">

```python
client = await AgentClient.connect_sandbox("dev", timeout=5.0)
```

</Accordion>

Connect to a running sandbox by name. 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">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">float | None</span></div>
    <div className="msb-param-desc">Connection timeout in seconds. <code>None</code> uses the default.</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">AgentClient</span></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

#### <span className="msb-recv">AgentClient.</span><span className="msb-hn">connect()</span>

<Tooltip tip="Connecting an agent client by socket path is local-only; on microsandbox cloud the SDK uses the agent WebSocket route internally."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

```python
@classmethod
async def connect(cls, path: str, *, timeout: float | None = None) -> AgentClient
```

<Accordion title="Example">

```python
path = AgentClient.socket_path("dev")
client = await AgentClient.connect(path)
```

</Accordion>

Connect to an agent relay socket by path. Use this when you already know the socket path, for example one returned by [`socket_path()`](#agentclient-socket_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">str</span></div>
    <div className="msb-param-desc">Path to the agentd relay socket.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>timeout</code><span className="msb-type">float | None</span></div>
    <div className="msb-param-desc">Connection timeout in seconds. <code>None</code> uses the default.</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">AgentClient</span></div>
    <div className="msb-param-desc">Connected client.</div>
  </div>
</div>

#### <span className="msb-recv">AgentClient.</span><span className="msb-hn">socket_path()</span>

<Tooltip tip="Connecting an agent client by socket path is local-only; on microsandbox cloud the SDK uses the agent WebSocket route internally."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

```python
@staticmethod
def socket_path(name: str) -> str
```

<Accordion title="Example">

```python
path = AgentClient.socket_path("dev")
```

</Accordion>

Resolve a sandbox's `agentd` relay socket path **without connecting**. Returns the same path [`connect_sandbox()`](#agentclient-connect_sandbox) would dial, so you can talk 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. 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">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">str</span></div>
    <div className="msb-param-desc">Filesystem path to the relay socket.</div>
  </div>
</div>

<p className="msb-member-group">Instance methods</p>

#### <span className="msb-recv">client.</span><span className="msb-hn">request()</span>

```python
async def request(self, flags: int, body: bytes) -> RawFrame
```

<Accordion title="Example">

```python
frame = await client.request(0, body)
print(frame["id"], frame["flags"])
```

</Accordion>

Send one raw frame 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">int</span></div>
    <div className="msb-param-desc">Frame flag byte, e.g. a combination of <code>FLAG_*</code> constants.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">bytes</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">The response frame.</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">stream()</span>

```python
async def stream(self, flags: int, body: bytes) -> AgentStream
```

<Accordion title="Example">

```python
from microsandbox import FLAG_SESSION_START, FLAG_TERMINAL

stream = await client.stream(FLAG_SESSION_START, body)
async for frame in stream:
    if frame["flags"] & FLAG_TERMINAL:
        break
```

</Accordion>

Open a raw streaming session. The returned [`AgentStream`](#agentstream) carries the protocol correlation id and is also an async iterator of raw 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">int</span></div>
    <div className="msb-param-desc">Frame flag byte; pass <code>FLAG_SESSION_START</code> to open a session.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>body</code><span className="msb-type">bytes</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="#agentstream">AgentStream</a></div>
    <div className="msb-param-desc">Open streaming session.</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">send()</span>

```python
async def send(self, id: int, flags: int, body: bytes) -> None
```

<Accordion title="Example">

```python
stream = await client.stream(FLAG_SESSION_START, body)
await client.send(stream.id, 0, follow_up_body)
```

</Accordion>

Send a follow-up frame on an existing correlation id. Use the `id` from the [`AgentStream`](#agentstream) 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">int</span></div>
    <div className="msb-param-desc">Correlation id of an open session, from <code>stream.id</code>.</div>
  </div>
  <div className="msb-param">
    <div className="msb-param-key"><code>flags</code><span className="msb-type">int</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">bytes</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_bytes()</span>

```python
def ready_bytes(self) -> bytes
```

<Accordion title="Example">

```python
ready = client.ready_bytes()
```

</Accordion>

Return the cached handshake `core.ready` frame body as CBOR bytes.

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

<div className="msb-params">
  <div className="msb-param">
    <div className="msb-param-key"><span className="msb-type">bytes</span></div>
    <div className="msb-param-desc">CBOR-encoded <code>core.ready</code> frame body.</div>
  </div>
</div>

#### <span className="msb-recv">client.</span><span className="msb-hn">close()</span>

```python
async def close(self) -> None
```

<Accordion title="Example">

```python
await client.close()
```

</Accordion>

Close the client. Calling it more than once is safe.

## AgentStream


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

An async iterator of raw agent frames.

#### <span className="msb-recv">stream.</span><span className="msb-hn">id</span>

`int`

Protocol correlation id; pass to [`send()`](#client-send) for follow-up frames

#### <span className="msb-recv">stream.</span><span className="msb-hn">next()</span>

```python
next()
```

Read the next frame; returns `None` at EOF

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

`Awaitable[`[`RawFrame`](#rawframe)` \| None]`

#### <span className="msb-recv">stream.</span><span className="msb-hn">close()</span>

```python
close()
```

Release the stream handle early; safe to call more than once

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

`Awaitable[None]`

<Accordion title="Example">

```python
from microsandbox import FLAG_SESSION_START, FLAG_TERMINAL

async with await client.stream(FLAG_SESSION_START, body) as stream:
    async for frame in stream:
        if frame["flags"] & FLAG_TERMINAL:
            break
```

</Accordion>

## Types

### RawFrame

<p className="msb-backref">Returned by <a href="#client-request">request()</a> · yielded by <a href="#agentstream">AgentStream</a></p>

A raw protocol frame with a CBOR-encoded body.

```python
class RawFrame(TypedDict):
    id: int
    flags: int
    body: bytes
```

| Field | Type | Description |
|-------|------|-------------|
| id | `int` | Protocol correlation id |
| flags | `int` | Frame flag byte (combination of `FLAG_*` constants) |
| body | `bytes` | CBOR-encoded protocol message body |
