Skip to main content

orbtile-adapter

Send your own tool's status to Orbtile: a dependency-free client for Orbtile Adapter API v1.2.

Version 0.2.0 · Python 3.10+ · stdlib runtime only · MIT. Install with python3 -m pip install orbtile-adapter.

icon and palette.states are optional Adapter API v1.2 registration fields, passed through as given; None clears a custom icon or the state colours. Older Orbtile hosts ignore them with warnings, so check info['apiMinor'] >= 2 before relying on them. Changing either asks the user to Allow again. See the protocol rules.

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_error expose 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) and ask_question(id, request, **fields) set the proper activity and clear the other kind. Requests are the documented JSON objects, including fresh ids. 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. cursor is the local applied cursor; lastSequence is 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 as answer_locally(id, commit, host="local", request_id=...). A duplicate/invalid event returns False and is discarded. An own-UI callback is ignored if the request was already consumed or its supplied request_id was 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.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for orbtile-adapter 0.2.0
File Size Uploaded Provenance Actions
orbtile_adapter-0.2.0.tar.gz 21.3 kB With provenance Details for orbtile_adapter-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for orbtile-adapter 0.2.0
File Interpreter ABI Platform Actions
orbtile_adapter-0.2.0-py3-none-any.whl Python 3 none any Details for orbtile_adapter-0.2.0-py3-none-any.whl

Total release size: 34.1 kB

Release files / orbtile_adapter-0.2.0.tar.gz

Download URL orbtile_adapter-0.2.0.tar.gz
Size 21.3 kB
Tags Source
SHA-256 checksum
How to use checksums
2cee8f446d1533b0e372b8d6838aed38f9bbc92fde66d456bd8fa520a5a6bdd0
BLAKE2b-256 checksum
How to use checksums
5a5fa8b4bb7761cbb6aa2d9c1ff02e366b5ef6d9785b6d940e3c300ae6a0a936
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 log

Release files / orbtile_adapter-0.2.0-py3-none-any.whl

Download URL orbtile_adapter-0.2.0-py3-none-any.whl
Size 12.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b6a35590786e0cbcc3e48d23031e0e446109789cd4173e71edffb40140500a0c
BLAKE2b-256 checksum
How to use checksums
45f29920525936cfe362c9d8ded572c91893f27d075082f116f7037156734f5d
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 log

Security for orbtile-adapter 0.2.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.

Select from 2 files

Attestation for orbtile_adapter-0.2.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 log

A 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.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page