Reference
Python SDK
Complete reference for the pacerelle package — client options, methods, message types and Agent Connect helpers.
pip install --pre pacerelleRequires CPython 3.12. Wheels bundle the native encryption library for Windows x64, Linux x64, Linux ARM64 and macOS ARM64.
from pacerelle import AgentGatewayClientThe SDK is in alpha. APIs may still change before 1.0.
AgentGatewayClient
client = AgentGatewayClient(
agent_id=os.environ["PACERELLE_AGENT_ID"],
token=os.environ["PACERELLE_AGENT_TOKEN"],
e2ee=True,
)All arguments are keyword-only.
agent_idstrrequiredtokenstrrequirede2eeboolFalse — always set True outside local debugging.store_rootstr | PathLike~/.myagents; the state lives in <store_root>/<agent_id>/signal.db.base_urlstrhttps://api.pacerelle.com.ws_urlstrbase_url by default.With e2ee=True, the client opens its SQLite state store immediately and restores the agent's
keys. Use one process per store.
Connection
| Method | Description |
|---|---|
await connect() | Publishes the agent's public keys if needed, opens the WebSocket and processes messages until the connection ends. Doesn't reconnect by itself — see reconnecting. |
close() | Closes the state store. Call it before creating a new client. |
publish_prekey_bundle() | Publishes the agent's public keys. Called by connect() when needed. |
get_verification_code() | Returns the verification code, after the keys were published. See Verify your agent. |
Receiving
on_message(handler)
async def handle(message: AgentMessage, agent: AgentGatewayClient) -> None: ...
client.on_message(handle)The handler can be async or a regular function. Messages are processed one at a time, in order;
a message is acknowledged once the handler returns without raising.
on_identity_changed(handler)
Called with a user ID when that user's identity key changed (for example after reinstalling the app). Informational: the SDK keeps working and never replaces the agent's own identity.
Sending
reply
await agent.reply(message, "Done.", attachments=None)Answers a message in its conversation — or its group — on the device that sent it, linked to the original message. The recommended way to reply.
send_message
await agent.send_message(
conversation_id=message.conversation_id,
to=message.from_id,
text="Done.",
reply_to_message_id=message.id, # optional, recommended
attachments=None, # optional list[AgentAttachment]
)Raises RuntimeError if the agent isn't connected. Pass to=f"group:{conversation_id}" to write
to a whole group.
Files
| Method | Description |
|---|---|
await send_file(conversation_id, to, name, data, mime=..., text="", reply_to_message_id=None) | Encrypts, uploads and sends a file. Returns the AgentAttachment. |
await send_media(conversation_id, to, name, data, mime, text="", width=None, height=None, duration_ms=None) | Same, with media hints. |
upload_file(name, data, mime=...) | Encrypts and uploads without sending. |
await download_attachment(attachment) | Downloads a received file and decrypts it locally. Returns bytes. See Files and media. |
Widgets
Each method takes conversation_id, to, title, and optionally widget_id, body and
expires_at (ISO 8601). Each returns the widget ID. See Interactive widgets.
| Method | Specific arguments |
|---|---|
send_confirm_widget | danger, labels={"yes": …, "no": …}, response_mode |
send_choice_widget | options=[{"id", "label"}], multi=True, response_mode |
send_permission_widget | scopes=["once", "session"] |
send_form_widget | fields=[{"name", "label", "type", "required", …}], submitLabel |
send_datetime_widget | mode="date" | "time" | "datetime", min, max |
send_file_picker_widget | multiple, accept, max_files |
send_progress_widget | value, max, cancellable |
send_widget_update | ref, spec, expires_at — updates a widget already sent |
response_mode is "individual" or "collective" — see collective votes.
Types
AgentMessage
A frozen dataclass.
| Field | Type | Description |
|---|---|---|
id | str | Message ID. |
conversation_id | str | Conversation ID. |
from_id | str | Sender ID — use it as to when replying. |
from_device_id | str | None | Sender's device. |
text | str | Message text. |
reply_to_message_id | str | None | The message this one replies to. |
attachments | list[AgentAttachment] | None | Attached files. |
widget_response | AgentWidgetResponse | None | Answer to a widget: ref, value, cancelled, id. |
widget_update | AgentWidgetUpdate | None | Update to a widget. |
encrypted | bool | Whether the message was end-to-end encrypted. |
AgentAttachment
id, name, mime, size, blob_id, optional width, height, duration_ms, and the
per-file key key_b64 / iv_b64.
Permissions
from pacerelle.permissions import PermissionPolicy, PermissionSessionSame contract as the JavaScript policy: create_request, receive_response, run_authorized,
create_widget_update, revoke, end_session, list_grants. See
Permissions.
Agent Connect
Synchronous server-side helpers for Agent Connect. All accept an
optional base_url.
| Function | Returns |
|---|---|
begin_agent_connect(connect_key, client_id, redirect_uri, agent_name, agent_description="", state=None) | AgentConnectStart — authorization_url, state, code_verifier, request_id, expires_at, expires_in |
exchange_agent_connect_code(code, code_verifier, client_id, redirect_uri) | AgentConnectInstallationToken — installation_token, agent_id, owner_id, conversation_id, scope |
request_agent_runtime_token(installation_token) | AgentConnectRuntimeToken — agent_token, agent_id, owner_id, conversation_id, expires_in |