orbtile-adapter
Send your own tool's status to Orbtile: a dependency-free client for Orbtile Adapter API v1.1.
Version 0.1.0 · Python 3.10+ · stdlib runtime only · MIT. Install with python3 -m pip install orbtile-adapter.
Ten-line quick start
from orbtile_adapter import Client, SessionUpdate
registration = {"name": "Tiny", "palette": {"baseHue": 150, "attentionHue": 330},
"capabilities": ["tap", "approvals", "questions"]}
with Client("dev.example.tiny", registration) as pad:
update: SessionUpdate = {"title": "Tiny agent", "activity": "thinking", "project": "Customer jobs"}
pad.upsert_session("run", **update)
pad.upsert_session("run", activity="streaming", message={"id": "m1", "text": "Hello"})
for event in pad.events():
pad.apply(event, lambda answer: print(answer["type"]))
if event["type"] == "tap":
break
Discovery uses ORBTILE_API_FILE, or Orbtile's platform discovery path. Pass discovery_file= for a fake server. macOS keeps Standard then Enterprise fallback. Windows searches %USERPROFILE%\.orbtile\adapter-api.json (Store), %LOCALAPPDATA%\Orbtile\Windows\adapter-api.json (Standard MSI), then %LOCALAPPDATA%\Orbtile Enterprise\Windows\adapter-api.json (Enterprise MSI), choosing the first existing file and defaulting to Store. HTTP/1.1 uses the discovered Unix socket on macOS or loopback TCP address on Windows. Each connection verifies the server's HMAC proof before registration, every call sends the discovery Bearer token, and interactive routes also send the ownership token. Tokens stay in memory and are never logged.
Allow the adapter in Orbtile Settings > Agents; once allowed, it can receive approval/question decisions from the keypad. connect() returns the registration reply, including enabled and reason; successful session replies with visible:false mean user consent is pending or denied.
SessionUpdate and SessionBatchItem provide typed dictionaries, including the optional project: str | None field (Orbtile 0.2.17+). It sets the per-session Project group and label within its host. Orbtile cleans it and trims surrounding whitespace; the result must be 1...128 characters, otherwise the update fails with HTTP 422 invalid_field. Omission keeps it on merges; project=None clears it and restores cwd grouping. This optional field is v1-compatible; older servers ignore it.
API
Client(adapter_id, registration, *, discovery_file=None, heartbeat_interval=5, timeout=5) connects through connect() or a context manager. AsyncClient has the same awaited methods and an async context manager. The asyncio facade uses stdlib worker threads; no socket operation blocks the event loop.
verify(),register(),heartbeat(),close();info,capabilities,registration_reply,heartbeat_errorexpose state. A daemon renews leases every five seconds, including while polling.upsert_session(id, **fields),remove_session(id, host="local"),replace_sessions([{ "id": ..., "title": ..., "activity": ... }]). Session identity includes host; send the remote host with every update. Replacement is display-only: publish requests with the dedicated helpers.request_approval(id, request, **fields)andask_question(id, request, **fields)set the proper activity and clear the other kind. Requests are the documented JSON objects, including freshids. Helpers do not invent an inbound decision endpoint.poll_events(wait_seconds=2)returns the protocol reply.events()is a sync/async iterator that retries network failures and overload responses with an unchanged applied cursor. Only one poll is allowed per client.cursoris the local applied cursor;lastSequenceis never automatically acknowledged.apply(event, commit)validates request kind/id, session/host, local and server expiry, decision and current question options under the same lock asanswer_locally(id, commit, host="local", request_id=...). A duplicate/invalid event returnsFalseand is discarded. An own-UI callback is ignored if the request was already consumed or its suppliedrequest_idwas replaced. A successful callback retires the prompt and advances the cursor; a callback that raises leaves it pending and unacknowledged.acknowledge(event)explicitly discards a delivered event without executing it.
Callbacks are synchronous atomic own-UI transactions, including for AsyncClient (where they run in a worker thread). They must have no side effects if they raise, or use an idempotent own-UI ledger. Check your current UI choices inside the transaction. answer_locally commits and retires the prompt before sending its null clear; a transport failure cannot revive that prompt. Do not run commands from event text. After apply succeeds, clear approval/question with a null update to retire the host UI too.
Orbtile enforces Allow-hold and Send-hold on the pad; the SDK accepts only documented final decision events after checking a live local prompt. A disconnect, timeout, denial, missing opt-in or invalid event never means Allow. Keep your own dialog available as the fallback.
On 401 the client reloads discovery once and verifies the listener again. On a lost registration it registers again, restores cached display metadata, resets the event cursor, and drops every old interactive request. Interactive callers receive LeaseLostError; reconciliation_required remains true even if background heartbeats subsequently succeed. Reconcile your own UI, call reconcile() to clear this notification, and publish new request ids. lease_generation changes at a lease reset. A cursor is in-memory and valid only within that live registration, never across app restarts. Transport reconnects within the registration preserve it.
Errors inherit AdapterError: APIError exposes status, code, field, retry_after; DiscoveryError, ProofError, PayloadTooLargeError, LeaseLostError, TransportError cover local failures. Error text never includes remote error messages or tokens. Bodies exceeding 64 KiB after UTF-8 encoding fail before connection. HTTP errors from direct methods propagate; iterators alone retry transport/overload failures.
Tiny agent and tests
The example streams a session and publishes a question, retaining a terminal fallback when no pad answer arrives. No command execution or automatic approval occurs.
From a checkout of github.com/Orbtile/orbtile-adapters:
python3 -m pip install orbtile-adapter
python3 examples/mock-orbtile.py /tmp/orbtile-sdk-python/api.json --events
# Separate terminal:
ORBTILE_API_FILE=/tmp/orbtile-sdk-python/api.json python3 sdk/python/examples/tiny_agent.py
PYTHONPATH=sdk/python/src python3 -m unittest discover -s sdk/python/tests -v
Tests use temporary Unix sockets on macOS or loopback TCP on Windows and in-process fake servers; they do not access the real app, listener or discovery directory.
Metadata
Release files for orbtile-adapter 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| orbtile_adapter-0.1.0.tar.gz | 20.3 kB | With provenance | Details for orbtile_adapter-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| orbtile_adapter-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for orbtile_adapter-0.1.0-py3-none-any.whl |
Total release size: 32.9 kB
Release files / orbtile_adapter-0.1.0.tar.gz
| Download URL | orbtile_adapter-0.1.0.tar.gz |
|---|---|
| Size | 20.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54fc742e9c8c39650e85f4835689877919e823b11c0ebbd66da4b7a5d5b4746b
|
|
BLAKE2b-256 checksum How to use checksums |
394fda4382f667a1c1fc59298399c3dc37aad8f9d8655c7b69508c69c0978d91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logRelease files / orbtile_adapter-0.1.0-py3-none-any.whl
| Download URL | orbtile_adapter-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9b0dcfcc80addbc180ebe93a360b1180bc16e227928bcb7e67e3eea6d0817872
|
|
BLAKE2b-256 checksum How to use checksums |
81bbb5931719a20e8718d23b5ca56cddaae79109aafa706976985c8e1a86f94b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logSecurity for orbtile-adapter 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for orbtile_adapter-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.