Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

rhylthyme-galago

License: Apache-2.0 PyPI

Run lab instruments from Rhylthyme programs through galago-tools, Science Corporation's open-source (Apache-2.0) gRPC drivers for more than 20 kinds of instrument: shakers, incubators, plate readers, imagers, liquid handlers and robot arms. galago-tools is the driver layer of Science's Galago lab-automation stack; this package lets Rhylthyme's planner and runner be the scheduler on top of it. It is an independent project, not affiliated with or endorsed by Science Corporation.

rhylthyme run with three galago tools: the shake step is waiting on the shaker

A step names a galago command; the runner sends it when the step starts, and the step ends when the instrument replies:

{
  "stepId": "shake",
  "name": "Shake at 1000 rpm",
  "instrument": {
    "tool": "shaker",
    "toolType": "bioshake",
    "command": "start_shake",
    "params": { "speed": 1000, "acceleration": 5, "duration": 5 }
  },
  "startTrigger": { "type": "afterStep", "stepId": "load-plate" }
}

Programs name tools by role. A local workcell file says where each tool listens, and stays on the lab machine:

{
  "id": "simulated-bench",
  "tools": [
    { "name": "shaker", "type": "bioshake", "host": "localhost", "port": 50710,
      "config": { "com_port": "COM3" } }
  ]
}

Status: alpha (plan). Tools run in galago's simulated mode unless you pass --live.

Quick start (simulated, no hardware)

galago-tools needs Python 3.9; Rhylthyme needs 3.12+. They talk over gRPC, so each gets its own environment.

# 1. A simulated Bioshake from galago-tools
python3.9 -m venv .venv-galago
.venv-galago/bin/pip install galago-tools
.venv-galago/bin/galago-serve --tool bioshake --port 50710 &

# 2. Rhylthyme with instrument support
python3.12 -m venv .venv && source .venv/bin/activate
pip install "rhylthyme[galago]"

# 3. The example program, and a workcell pointing at that Bioshake
curl -sO https://raw.githubusercontent.com/rhylthyme/rhylthyme-galago/main/examples/shake-plate.json
curl -sO https://raw.githubusercontent.com/rhylthyme/rhylthyme-galago/main/examples/workcell-simulated.json

# 4. Run it: the tools are configured (simulated) and the run starts;
#    p pauses, q quits
rhylthyme run shake-plate.json --workcell workcell-simulated.json

While the command runs, the runner shows the step with a [shaker] badge and "waiting on shaker" (screenshot above), and the shaker is held as a resource until it replies. The run record (rhylthyme runs) marks it endedBy: "instrument" and keeps every reply, retries included, with any data the tool returned:

"instrument": {
  "tool": "shaker", "command": "start_shake",
  "replies": [
    { "attempt": 1, "at": 3.0, "code": "DRIVER_ERROR", "errorMessage": "lid open" },
    { "attempt": 2, "at": 41.2, "code": "SUCCESS", "metadata": { "wells": { "A1": 0.41 } } }
  ]
}

A three-tool example

examples/passage-check.json (in this repo) fetches a plate from a Liconic incubator, shakes it on a Bioshake, images it on a Cytation, has someone check the media, and stores it again, while media is warmed and aliquoted by hand on a second track:

for t in liconic:50721 bioshake:50722 cytation:50723; do
  .venv-galago/bin/galago-serve --tool ${t%%:*} --port ${t##*:} &
done
rhylthyme run examples/passage-check.json --workcell examples/workcell-cell-culture.json

It runs end to end in CI against these simulated servers (tests/test_integration.py). The screenshot at the top of this page is this program, a few seconds in: the plate has been fetched, the Bioshake is running, and someone is warming media on the other track.

On the web

Programs with instrument steps validate, visualize and publish on rhylthyme.com and through the Rhylthyme MCP server like any other: instrument steps carry a [tool] badge, and bars whose length is an estimate have a dotted outline. Workcells are never uploaded.

The web player: the shake step carries a [shaker] badge and a dotted outline

galago-tools 0.19.9 cannot simulate an Opentrons run_program (its simulated dispatch passes an argument RunProgram does not take, so the tool answers DRIVER_ERROR); other Opentrons commands, and real OT-2 runs, are unaffected.

Real hardware

rhylthyme run shake.json --workcell lab.json --live

--live first lists each tool (address and current status, read without configuring anything) and every instrument command the run will send, then asks you to type live. Only then are the tools configured for real; the run starts only if every tool reports READY. Scripts pass --confirm-live instead of answering; without a terminal and without that flag, a live run is refused.

Workcell files stay on the lab machine: rhylthyme publish and rhylthyme analyze refuse them, programs name tools only by role, and run records hold no tool addresses.

From a browser: rhylthyme bridge

rhylthyme login
rhylthyme bridge --workcell lab.json            # wait for runs started on the web
rhylthyme bridge run.json --workcell lab.json   # or run one program and publish it

The bridge lists the lab machine on the Bridges page of rhylthyme.com, for your account only. From there you can watch a run's timeline live, pause and resume it, answer a failed instrument step (retry, skip or abort), and start any program saved in your library on that workcell. The terminal shows the same runner UI, plus every command that came from the web; Ctrl-C at the lab machine always wins.

  • Outbound only. The bridge opens no port and needs no tunnel; it makes HTTPS calls to rhylthyme.com with your own login.
  • Nothing about the lab network leaves it. Tools are published by name, type and status only; addresses, ports and configs never are, including in error messages.
  • The lab machine decides. It rejects commands older than 30 seconds, acts on each command once, refuses programs with code blocks or that do not validate on its workcell, and configures the tools before accepting a start (a tool that is not ready is a refusal the browser sees).
  • Live from the web needs two keys. Start the bridge with --allow-live; the browser then shows the tools and every instrument command in the program and asks you to type live. Without --allow-live, web starts are simulated only.

Tools are resources

Each tool a program uses is a resource of capacity 1, so two steps never send commands to the same shaker at once: the second waits until the first is done. A tool needs no person (actor) while it works, so hand steps and instrument steps run side by side. To let a tool take more than one command at a time, declare a constraint with its name:

"resourceConstraints": [{ "task": "shaker", "maxConcurrent": 2, "description": "two-deck shaker" }]

When an instrument fails

Any reply other than SUCCESS (a driver error, a tool that is unreachable or not ready) and any command that outlives its timeoutSeconds marks the step FAILED. Nothing new starts; steps already running on other tools finish. The runner shows what failed (tool, command, response code, message) and waits:

  • r resends the command; if it succeeds the program carries on.
  • x marks the step done by hand (endedBy: "skipped") and releases what depends on it.
  • A twice aborts the program; the reason is kept in the run record (context.abortReason).

Ctrl-C stops the run at once and names any command still in flight.

A timed-out imaging step: FAILED in red, the banner names the tool, command and code, and media warming carries on

Planning with instrument durations

An instrument step may leave out its duration: at run time it ends when the tool replies. For planning, rhylthyme plan and rhylthyme analyze fill one in and flag it in metadata.durationEstimate:

$ rhylthyme plan shake.json planned.json --workcell lab.json
Estimated instrument durations:
  shake: 5 s (from shaker EstimateDuration)
Makespan (by start triggers and durations): 11 s

rhylthyme render of the three-tool example; dotted bars are estimated

The number comes from the tool's own EstimateDuration (with --workcell, for tools that are already configured; planning never configures a tool), else a duration-like command param (duration, timeout, ...), else 60 s. Authored durations are never changed.

Checking programs

rhylthyme validate checks every instrument step's command and params against galago's own definitions, naming the step, tool, command and field:

$ rhylthyme validate shake.json --workcell lab.json
  - [instrument_invalid_command] Step 'shake': shaker (bioshake) start_shake: unknown param 'rpm' (takes speed, acceleration, duration)

Without --workcell, steps are checked against their toolType; steps with neither get an instrument_unchecked warning. With --workcell, it also reports tools the workcell lacks and toolTypes that disagree with it. rhylthyme run runs the same checks before configuring any tool.

From Python: rhylthyme_galago.validate_command(tool_type, command, params) and check_program(program, workcell=None).

Development

pip install -e ".[dev]"
pytest                      # unit tests; integration tests need galago-serve
GALAGO_SERVE=/path/to/galago-serve pytest -m integration

The integration tests find galago-serve through GALAGO_SERVE, then .venv-galago/bin/galago-serve, then PATH, and are skipped when none exists.

galago protos

proto/galago/ holds galago-tools' .proto files, copied verbatim and pinned in proto/galago/UPSTREAM.json. The Python stubs in src/rhylthyme_galago/_gen/ are generated from them under this package's namespace (the wire format is galago's own):

python scripts/refresh_protos.py --ref <galago-tools commit or tag>  # re-vendor + regenerate
python scripts/refresh_protos.py                                      # regenerate only

License

rhylthyme-galago is licensed under the Apache License 2.0.

It includes material from galago-tools, Copyright 2025 - Science Corporation, also licensed under the Apache License 2.0 (copy):

  • proto/galago/: galago-tools' .proto files, unmodified, pinned in proto/galago/UPSTREAM.json;
  • src/rhylthyme_galago/_gen/: Python generated from them, with the proto import paths moved under this package (each file says so in its header);
  • catalog/galago-commands.json: a JSON description of their commands.

NOTICE lists these; the wheel and sdist carry LICENSE, NOTICE and LICENSES/galago-tools-LICENSE. galago-tools itself is not bundled: you install it separately, from Science Corporation.

Metadata

Release files for rhylthyme-galago 0.2.0a0

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

Source distribution (sdist)

Source distribution for rhylthyme-galago 0.2.0a0
File Size Uploaded Provenance Actions
rhylthyme_galago-0.2.0a0.tar.gz 84.1 kB Without provenance Details for rhylthyme_galago-0.2.0a0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for rhylthyme-galago 0.2.0a0
File Interpreter ABI Platform Actions
rhylthyme_galago-0.2.0a0-py3-none-any.whl Python 3 none any Details for rhylthyme_galago-0.2.0a0-py3-none-any.whl

Total release size: 205.9 kB

Release files / rhylthyme_galago-0.2.0a0.tar.gz

Download URL rhylthyme_galago-0.2.0a0.tar.gz
Size 84.1 kB
Tags Source
SHA-256 checksum
How to use checksums
986f8e63f97a4d15b1fcccaccad90e912fb6850c0b69482a9721c92099286560
BLAKE2b-256 checksum
How to use checksums
598db07d560be30183a15a1e6e9eb47aa5f4458e92a2b58ac33c1f943098b3ed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / rhylthyme_galago-0.2.0a0-py3-none-any.whl

Download URL rhylthyme_galago-0.2.0a0-py3-none-any.whl
Size 121.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aab9d9b608529106471b7870ff6fbe40926efe2a1beaafa3065f2173d08f8752
BLAKE2b-256 checksum
How to use checksums
8de8562b47fc83d8ab80be12115f2f441a9a5acef7c15d2e77a44c1e88a2c0b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Security for rhylthyme-galago 0.2.0a0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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.

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