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

`AgentClient` is the low-level raw transport for talking to `agentd` through a running sandbox's relay socket. Most applications should use [`Sandbox`](/sdk/python/sandbox), [`exec`](/sdk/python/execution), and [`fs`](/sdk/python/filesystem) instead. Use this API when you are building protocol-level tools or higher-level SDK helpers.

All request bodies and response bodies are raw CBOR bytes. The SDK handles framing and correlation ids, but it does not encode or decode the CBOR message body for you.

The raw body is the full CBOR-encoded protocol `Message` body: `v`, `t`, and `p`. It is not just the inner payload.

```python
from microsandbox import AgentClient

client = await AgentClient.connect_sandbox("dev")
ready = client.ready_bytes()
await client.close()
```

---

## 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.connect_sandbox()

```python
@classmethod
async def connect_sandbox(cls, name: str) -> AgentClient
```

Connect to a running sandbox by name. Sandbox names are limited to 128 UTF-8 bytes.

---

#### AgentClient.connect()

```python
@classmethod
async def connect(cls, path: str) -> AgentClient
```

Connect to an agent relay socket by path.

---

#### request()

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

Send one raw frame and wait for one response frame.

---

#### stream()

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

Open a raw streaming session. The returned stream carries the protocol correlation id and is also an async iterator of raw frames.

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

---

#### send()

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

Send a follow-up frame on an existing correlation id. Use this with the `id` on the [`AgentStream`](#agentstream) returned by [`stream()`](#stream).

---

#### ready_bytes()

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

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

---

#### close()

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

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

---

## RawFrame

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

`id` is the protocol correlation id, `flags` is the frame flag byte, and `body` is the CBOR-encoded protocol message body.

---

## AgentStream

```python
class AgentStream:
    id: int
    async def next(self) -> RawFrame | None: ...
    async def close(self) -> None: ...
```

`id` is the protocol correlation id. Pass it to [`AgentClient.send()`](#send) for follow-up frames in the same session. `close()` releases the stream handle early. `next()` returns `None` at EOF.
