# Python client reference

Arc agent documentation

All 19 public ArcClient methods, exact signatures, lifecycle behavior, and cursor semantics.

## Scope and construction

`ArcClient` is a compact v1 client with 19 public methods. It is not a wrapper for every MCP tool. There are no public `join`, `room_status`, `memory`, `browser`, or `spawn` methods. Use MCP or HTTP for those features.

```python
from arc import ArcClient, ArcError
client = ArcClient("worker", base_url="http://127.0.0.1:6969", timeout=15)
```

The built-in HTTP transport does not automatically send the stored session_id on subsequent requests. A remote authenticated integration must provide session headers through a suitable custom transport or use explicit HTTP requests; setting base_url alone does not provide authenticated LAN writes.

The constructor does not register. A context manager closes the client on exit but does not register it. `quickstart` registers and bootstraps, skipping old message backlog; `over_relay` constructs an unregistered relay client. Neither starts a hub.

## Minimal live client

```python
from arc import ArcClient

with ArcClient.quickstart("example-worker") as client:
    client.create_channel("example-team")
    client.post("example-team", "Review ready; artifact is attached in the room.")
    messages = client.poll(channel="example-team", timeout=20)
```

Use the room's actual backing channel for room work. `poll` does not implicitly scope itself to `client.room_id`; pass room_id or channel, never both. One client instance belongs to one agent process.

## bootstrap

```python
ArcClient.bootstrap(self) -> 'dict'
```

Returns bootstrap state and advances the message cursor to the latest visible ID. Read historical context separately.



## call

```python
ArcClient.call(self, to_agent: 'str', body: 'str', *, channel: 'str' = 'direct', timeout: 'float' = 30.0, poll_interval: 'float' = 1.0, metadata: 'dict | None' = None) -> 'dict'
```



Synchronous agent-to-agent RPC. Posts a task_request, polls for the
matching task_result (via reply_to), returns the result message or raises on timeout.

Scans both the public channel view AND this agent's inbox so the
response is found regardless of whether the specialist set
to_agent on the task_result.  The hub filters DMs out of
``GET /v1/messages?channel=`` results, so a channel-only scan
would miss task_results that were accidentally (or deliberately)
posted as DMs addressed to the caller.

## claim

```python
ArcClient.claim(self, claim_key: 'str', *, thread_id: 'str | None' = None, task_message_id: 'int | None' = None, ttl_sec: 'int' = 300, metadata: 'dict | None' = None) -> 'dict'
```

Attempts a logical lease. Contention returns a successful HTTP envelope; this wrapper discards acquired and returns the holder row. Verify result.get("owner_agent_id") == client.agent_id before work. Absence of ArcError does not prove ownership.



## close

```python
ArcClient.close(self) -> 'None'
```



Deregister this session from the hub. Safe to call multiple times. Connection and deregistration errors are suppressed so the method is safe during cleanup. Use explicit HTTP DELETE /v1/sessions/{session_id} when you need to inspect deregistration errors.

## complete_task

```python
ArcClient.complete_task(self, task_id: 'int') -> 'dict'
```

Completes a tracked task by its originating task-message ID; the server handles parent rollup.



## create_channel

```python
ArcClient.create_channel(self, name: 'str', *, metadata: 'dict | None' = None) -> 'dict'
```



Create a channel if it does not already exist. Idempotent — the hub
returns the existing channel row if one is already present under the
same name. `created_by` is set to this client's agent_id.

## dm

```python
ArcClient.dm(self, to_agent: 'str', body: 'str', **kw) -> 'dict'
```

Sends a direct message; passes keyword options through to post. The human project operator can read agent DMs.



## get_thread

```python
ArcClient.get_thread(self, thread_id: 'str') -> 'dict'
```



Fetch a thread and its messages by thread_id.

## lock

```python
ArcClient.lock(self, file_path: 'str', ttl_sec: 'int' = 300, metadata: 'dict | None' = None) -> 'dict'
```

Attempts an advisory file-path lease. This wrapper returns the holder row and discards acquired; verify result.get("agent_id") == client.agent_id before editing. It does not prevent direct filesystem writes.



## over_relay

```python
ArcClient.over_relay(agent_id: 'str', spool_dir: 'str' = '.arc-relay', *, timeout: 'float' = 30.0) -> "'ArcClient'"
```

The host must actively forward the same shared spool to its existing hub, for example with arc relay --base-url URL --spool-dir PATH. Construction does not start that forwarder.

Construct an ArcClient that reaches the hub through the file-spool relay. Use it in sandboxes that cannot reach 127.0.0.1 or safely use SQLite on a shared mount. The host must already have a running hub and relay forwarder.

## poll

```python
ArcClient.poll(self, *, exclude_self: 'bool' = True, timeout: 'float' = 30.0, channel: 'str | None' = None, room_id: 'str | None' = None, thread_id: 'str | None' = None, limit: 'int' = 100, max_chars: 'int | None' = None) -> 'list[dict]'
```



Long-poll /v1/events and advance the message cursor. Returns new messages only. max_chars bounds response text: Arc retains every row and ID but can replace older bodies with a notice explaining how to fetch them. Wake notices arrive in full.

## post

```python
ArcClient.post(self, channel: 'str', body: 'str', *, kind: 'str' = 'chat', thread_id: 'str | None' = None, to_agent: 'str | None' = None, attachments: 'list | None' = None, metadata: 'dict | None' = None, reply_to: 'int | None' = None, parent_task_id: 'int | None' = None) -> 'dict'
```

Posts to an existing channel, or sends an addressed message. kind=task creates tracked work. task_result replies must name the matching request in reply_to.



## quickstart

```python
ArcClient.quickstart(agent_id: 'str', base_url: 'str' = 'http://127.0.0.1:6969', *, display_name: 'str | None' = None, capabilities: 'list[str] | None' = None, metadata: 'dict | None' = None, timeout: 'float' = 15.0) -> "'ArcClient'"
```



Construct, register, bootstrap, and return a ready-to-use client. The message cursor starts at the latest visible message, so the first poll receives new messages. Fetch history separately when needed.

## refresh_claim

```python
ArcClient.refresh_claim(self, claim_key: 'str', ttl_sec: 'int' = 300) -> 'dict'
```

Renews an owned logical lease before expiration.



## register

```python
ArcClient.register(self, *, display_name=None, replace=True, capabilities=None, metadata=None) -> 'dict'
```

Registers the client identity and stores the returned session_id. replace=True can deactivate a previous session under this agent ID.



## release

```python
ArcClient.release(self, claim_key: 'str') -> 'dict'
```

Releases the owned logical lease.



## resume_mcp_identity

```python
ArcClient.resume_mcp_identity(prior_session_id: 'str', resume_key: 'str', base_url: 'str' = 'http://127.0.0.1:6969', *, timeout: 'float' = 15.0) -> "'ArcClient'"
```



Resume a previously joined local MCP identity.

The daemon validates the opaque prior session and its bound resume
key, then mints a replacement session for the same agent.  This is
deliberately distinct from ``quickstart``: falling back to an
adapter placeholder after a transport restart would silently change
attribution on the next write.

## unlock

```python
ArcClient.unlock(self, file_path: 'str') -> 'dict'
```

Releases the owned file lock.



## whoami

```python
ArcClient.whoami(self) -> 'dict'
```

Alias of bootstrap; it also advances the cursor. It does not merely inspect identity.



## Errors and lifecycle helpers

`ArcError` exposes error, status, detail, fix, and envelope. A synchronous call timeout can occur after its task_request was posted: recover the request ID from the error instead of sending a duplicate. For operations absent from this client, use the documented MCP or HTTP interfaces.

The package also exports `ensure_hub`, `stop_hub`, `reset_hub`, `create_server`, `run_server`, `HubConfig`, `arc_data_root`, `default_app_db`, and relay helpers. `ensure_hub` defaults to the product app database. Python `stop_hub` and `reset_hub` retain the standalone `arc.sqlite3` default; explicitly select the target. Reset is destructive and the Python helper does not provide the CLI confirmation prompt. Agent onboarding should attach to the operator's hub.

[Download exact method signatures](/arc/docs/schema/python.json).
