Remote instrument proxy
IvoryOS can expose a real Python instrument as an HTTP-backed instrument server. Other IvoryOS platforms, scripts, or workflow runners can import a generated proxy client and call the remote instrument as if it were a local Python object.
Use this pattern when:
one instrument must be shared by multiple platforms;
one machine owns the hardware connection, driver, license, or API credentials;
a workflow on another machine needs a small number of direct instrument calls;
you want IvoryOS to be the access-control and logging boundary for an instrument.
Model
Platform A Workflow Platform B Workflow
| |
| imports proxy client | imports proxy client
v v
balance.read_mass_mg() balance.read_mass_mg()
| |
+------------- HTTP POST -----------+
|
v
IvoryOS Instrument Server
/ivoryos/instruments/deck.balance
|
v
Real Python Driver
AnalyticalBalance.read_mass_mg()
|
v
Balance on COM4 / USB / LAN
The instrument server owns the real driver object. Proxy clients only send method names and arguments to the server.
1. Start an instrument server
On the machine connected to the real instrument, create a normal IvoryOS deck script. This example uses a shared analytical balance. Replace vendor_balance_sdk with the driver package for the actual balance.
from vendor_balance_sdk import BalanceDriver
class AnalyticalBalance:
def __init__(self, port: str):
self.driver = BalanceDriver(port=port)
def tare(self) -> None:
"""Tare the balance."""
...
balance = AnalyticalBalance(port="COM4")
import ivoryos
ivoryos.run(__name__, host="0.0.0.0", port=8000)
IvoryOS inspects balance and exposes it as:
/ivoryos/instruments/deck.balance
2. Generate the proxy client
Open the instrument server in a browser and download the generated proxy Python interface:
http://<host>:<port>/ivoryos/instruments/files/proxy
The generated file contains one Python class per exposed instrument and a default instance for convenience. For deck.balance, the default instance is balance.
Place the generated proxy file somewhere importable by the remote workflow, for example beside the Platform A or Platform B workflow script.
3. Use the proxy in another workflow
In a different platform workflow, import the generated proxy and call the remote instrument method.
from generated_proxy import balance
balance.tare()
From the workflow author’s perspective, balance.read_mass_mg() looks like a local Python call. At runtime it sends an authenticated HTTP POST to the IvoryOS instrument server.
What the proxy sends
The proxy sends JSON to the direct-control route:
POST /ivoryos/instruments/deck.balance
{
"hidden_name": "read_mass_mg"
}
The server converts argument types using the real method signature, executes the driver method, stores a single-step record, and returns JSON:
{
"success": true,
"output": 10.12
}
Authentication
The generated proxy uses an authenticated requests.Session. By default it tries the local default credentials:
from generated_proxy import Balance
balance = Balance(username="admin", password="admin")
Use deployment-specific accounts for shared instruments. Avoid sharing administrator credentials between platforms.
Concurrency
Direct-control calls use the shared runner lock. If a second caller reaches the same IvoryOS server while another task is active, the server returns a busy response unless the call explicitly overrides the busy lock.
For shared physical instruments, treat the IvoryOS instrument server as the serialization point. This prevents two platforms from driving the same hardware at the same time.
When not to use this pattern
Do not use the proxy client as a replacement for every integration:
Use a plugin when the remote system needs a custom UI page.
Use the Python client or MCP server when the remote system needs workflow-level operations such as loading scripts, running campaigns, or reading records.
Use a dedicated instrument SDK when several systems need rich local driver behavior and can safely manage their own connections.
Operational notes
Keep the server reachable from all client platforms.
Keep the IvoryOS URL prefix as
/ivoryosunless the generated proxy and deployment agree on another path.Regenerate the proxy after changing exposed instrument method signatures.
Put stable type hints on remote instrument methods so the generated proxy and server-side conversion stay predictable.
Keep long-running methods synchronous from the caller’s perspective unless the workflow is designed around background execution.