> ## Documentation Index
> Fetch the complete documentation index at: https://microsanbox-staging-appcypher-sdk-runtime-bootstrap.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent client

> 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 theme={null}
@classmethod
async def connect_sandbox(cls, name: str, *, timeout: float | None = None) -> AgentClient
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
@classmethod
async def connect(cls, path: str, *, timeout: float | None = None) -> AgentClient
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
@staticmethod
def socket_path(name: str) -> str
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
async def request(self, flags: int, body: bytes) -> RawFrame
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
async def stream(self, flags: int, body: bytes) -> AgentStream
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
async def send(self, id: int, flags: int, body: bytes) -> None
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
def ready_bytes(self) -> bytes
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
async def close(self) -> None
```

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
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 theme={null}
close()
```

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

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

`Awaitable[None]`

<Accordion title="Example">
  ```python theme={null}
  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 theme={null}
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                  |
