| name | operate-kansasflex |
| description | Operates the local Opentrons Flex KansasFLEX through flex-testing-agent CLI and Python APIs only (never curl/ad-hoc robot HTTP). Use when inspecting robot state, status (instruments/door/subsystems), waiting for health after install, probing read-only endpoints, taking camera pictures, listing Flex OS releases, installing a robot OS build with ALLOW_MUTATIONS, running Pyro / protocol-subprocess validation, using the FTDI serial console (`flex-test serial`) instead of Tabby, running LPC jog timing (`flex-test lpc-jog-timing --confirm-clear-deck`), or archiving/reviewing diagnostic robot logs after seed-runs / api-suite (`flex-test logs archive`). |
Operate KansasFLEX
Hard rule: no ad-hoc robot HTTP
Do not curl, wget, or raw httpx against ROBOT_HOST / robot ports.
Do not invent robot URLs in agent glue.
Use only:
uv run flex-test … CLI, or
- Typed clients / capabilities via
FlexRobot (clients/ → capabilities/)
If a needed call is missing, extend the harness (skill
extend-flex-harness) instead of shelling out.
| Need | Use |
|---|
| Reachability / versions / CRS detect | flex-test inspect |
| Instruments, door, subsystems | flex-test status |
Post-install / reboot wait for /health | flex-test wait-health |
| Broad read-only GETs + optional picture | flex-test probe |
| Run presence | flex-test run-state |
| OS install | flex-test put … |
| Logs | flex-test logs list|archive |
| CRS-off API suite | flex-test probe|crs-off-b|c|api-suite |
| CRS-on API suite | flex-test crs lockdown|auth-matrix|probe|suite|settings-suite|users-api |
| CRS audit periods | flex-test audit list|download |
| Seed run history / LPC | flex-test seed-runs |
| LPC jog latency (safe box) | flex-test lpc-jog-timing --confirm-clear-deck |
| Boot / DHCP / SSH down | flex-test serial … (not HTTP) |
Prerequisites
.env with ROBOT_HOST (and usually ROBOT_NAME=KansasFLEX)
- Optional
ROBOT_HOST_CANDIDATES=192.168.0.21,192.168.0.20 (defaults in settings)
uv sync --all-extras
- Mutations only when
.env has ALLOW_MUTATIONS=true
- CLI/runners probe candidates via
GET /health and bind the live host
(DHCP has moved KansasFLEX between .20 and .21)
- CRS on: set
ROBOT_USERNAME / ROBOT_PASSWORD so mutating CLIs can OAuth
Preferred commands
uv run flex-test inspect
uv run flex-test status
uv run flex-test wait-health
uv run flex-test wait-health --timeout 1200 --interval 5
uv run flex-test run-state
ALLOW_MUTATIONS=true uv run flex-test run-state --ensure no-current
ALLOW_MUTATIONS=true uv run flex-test run-state --ensure current-idle
uv run flex-test probe
uv run flex-test probe --ensure-run-state
uv run flex-test probe --no-picture
uv run flex-test probe --picture ./artifacts/camera/kansasflex.jpg
ALLOW_MUTATIONS=true uv run flex-test api-suite
ALLOW_MUTATIONS=true uv run flex-test crs-off-b --create-fixtures
ALLOW_MUTATIONS=true uv run flex-test crs-off-c
ROBOT_USE_HTTPS=true uv run flex-test crs lockdown --show-failures
ROBOT_USE_HTTPS=true uv run flex-test crs auth-matrix
ALLOW_MUTATIONS=true ROBOT_USE_HTTPS=true uv run flex-test crs suite --include-lockdown
ALLOW_MUTATIONS=true ROBOT_USE_HTTPS=true uv run flex-test crs settings-suite
ALLOW_MUTATIONS=true ROBOT_USE_HTTPS=true uv run flex-test crs users-api
uv run flex-test audit list
ALLOW_MUTATIONS=true uv run flex-test seed-runs
ALLOW_MUTATIONS= uv run flex-test lpc-jog-timing --confirm-clear-deck
ALLOW_MUTATIONS= uv run flex-test lpc-jog-timing --confirm-clear-deck --jogs 200
uv run flex-test logs list
uv run flex-test logs archive
uv run flex-test releases
uv run flex-test releases --channel internal
ALLOW_MUTATIONS= uv run flex-test put 9.1.2-alpha.5 --channel external
ALLOW_MUTATIONS= uv run flex-test put 10.0.0-alpha.0 --channel external
ALLOW_MUTATIONS= uv run flex-test reset-data
ALLOW_MUTATIONS= uv run flex-test known-state
uv run flex-test timing
FTDI serial console (no Tabby)
Setup + agent rules: docs/serial-console.md.
Hardware photos / orientation:
Confluence FTDI guide.
Prefer HTTP/inspect/probe when the network works. Use serial for boot logs,
DHCP loss, or SSH unreachable. Close Tabby first (port is exclusive).
uv run flex-test serial list
uv run flex-test serial shell
uv run flex-test serial watch --seconds 30
uv run flex-test serial run "systemctl is-active opentrons-robot-server"
uv run flex-test serial remote-access-status
ALLOW_MUTATIONS=true uv run flex-test serial allow-remote-access
CRS-on: allow-remote-access restores SSH/Jupyter/devtools via
/etc/opentrons-allow-remote-access (does not turn CRS off; redo after OS
update). Kernel printk on the FTDI console is expected and useful
(docs/serial-console.md). Details:
docs/crs-testing.md.
Enter / exit CRS:
- Enable (gated, one-way):
ALLOW_MUTATIONS=true uv run flex-test crs enable --confirm-one-way
only when the operator explicitly asks. Catalog probes never PATCH enable.
- Password for ODD enter-CRS and for
opentrons_disable_crs: {robot_serial}-0000
- Create
testadmin / testuser yourself after enter CRS (no longer auto-created),
or use flex-test crs provision-users (flex_test_* fixtures)
- Disable: root SSH or serial
opentrons_disable_crs (not a protocol subprocess)
- Product model (21 CFR tooling, documentation required, pause-is-not-a-bug):
docs/crs-testing.md
On CRS-on App/ODD: Pause waits for a documentation note before the run
pauses. Expected. Open the door or E-Stop. Do not file as a bug.
Robot logs (audit / diagnostic / protocol run)
Chooser + definitions: docs/robot-logs.md.
- Audit (CRS on only): signed periods; who did what / who ran a protocol
(includes run logs; not diagnostic). File Manager is App/ODD; CRS does not
auto-delete records.
- Diagnostic: usual support logs (HTTP access, errors, robot-server / CAN / ODD, …)
- Protocol run: command timeline for app/ODD run UI (may include source / RTP)
Do not confuse those with FTDI harness tees in artifacts/serial/.
uv run flex-test logs list
uv run flex-test logs archive
uv run flex-test audit list
uv run flex-test audit download <period-id>
Post-suite log archive and review
Required after live seed-runs, api-suite, or install verification (and
whenever the user asks to verify a build and file bugs on an RQA epic).
- Archive diagnostic logs:
uv run flex-test logs archive
- Optionally note recent FTDI transcript paths under
artifacts/serial/ in the
review note. Do not treat harness FTDI tees as robot serial.log.
- Scan archived files for investigate signals:
ERROR, CRITICAL, Traceback, Exception
Application startup failed, CommunicationError
- Clustered nginx 502 / 5xx after
/health has recovered
- Unexpected Pyro /
hardware-api activity when
enableHardwareSubprocess / enableProtocolSubprocess are false
- Write
review.md in the archive directory: clean vs suspects, file paths,
timestamps, robot version / host.
- If clear product defects and the user named a parent epic (for example
RQA-5819): create RQA Bugs with
parent set to that epic. Otherwise
summarize in chat and/or an epic comment. Do not open noise bugs for expected
post-reboot 502 while firmware flashes.
- Always attach log evidence to every bug filed from this review (required):
- Build a focused pack under the archive:
evidence-<ISSUE_KEY>/ with the relevant excerpts (not necessarily the
full multi-MB serial.log / can_bus.log), plus review.md and
manifest.json, and zip it as evidence-<ISSUE_KEY>.zip.
- Put that evidence on the Jira issue before considering the bug done:
- Prefer native Jira file attachments when available (UI upload or
REST with
JIRA_API_TOKEN / email basic auth).
- If binary attach is unavailable (Atlassian MCP has no attachment API),
paste the focused excerpts into an issue comment (full traceback +
occurrence index) and note the local pack path / zip in that comment.
- Never leave a log-review bug with only a summary and no log excerpts on
the ticket.
Post-install recovery (Pyro / 10.0.0-alpha.* builds)
After put, update-server may already show the new version while nginx /health
returns 502 for several minutes (firmware flash + robot-server Pyro startup).
That is often expected; see RQA-5787.
- Wait for
/health 200, or SSH / serial and watch services / FW progress.
- SSH (lab key, not committed), or FTDI serial when DHCP/network is down:
ssh -i ~/.ssh/robot_key -o IdentitiesOnly=yes root@$ROBOT_HOST
uv run flex-test serial shell
uv run flex-test serial run "systemctl is-active opentrons-robot-server"
- If still broken after FW idle: full robot reboot (power cycle or
reboot),
then wait for /health 200 again. Do not prescribe ordered
systemctl restart of nameserver / hardware-api / robot-server as the
operator recovery path. Grouped PartOf= restart (oe-core#373) closed
RQA-5789 / RQA-5790 on v10.0.0-alpha.3; reboot is still the support path.
Full validation narrative: docs/pyro-testing.md. Checklist YAML:
docs/test-suggestions/10.0.0-alpha.0-pyro-subprocess.yaml.
Bug epic for 10.0.0-alpha.1: RQA-5847
(alpha.0: RQA-5831).
Triage / priority:
RBARM 10.0.0-alpha.1 triaging.
Filing bugs
- Parent under RQA-5847 for alpha.1 (or the epic the user names).
- Do not file duplicates. Search the triage page + open RQA bugs first; if a
match exists, comment with evidence on that ticket instead.
- Write for product developers, not harness maintainers:
- Reproduction steps as HTTP API calls (method, path, headers, body).
- Paste real response bodies and relevant server log excerpts (journal,
robot-server, audit-server).
- Include robot build, CRS/access-control state, and robot serial when known.
- Attach protocol files, request payloads, and sample responses (Jira
attachments or inline in the description/comment when upload is unavailable).
- PR links are fine for context; do not rely on them as the repro.
- Avoid harness-only vocab in Jira (
A4/C6, flex-test, api-suite, CRS suite
letters, artifact paths under artifacts/).
- Mention full robot reboot as recovery / workaround when relevant.
Pyro / protocol-subprocess smoke
On external 10.0.0-alpha.* (and historical internal 4.0.0-alpha.*) builds with
enableHardwareSubprocess / enableProtocolSubprocess default on
(/data/feature_flags.json):
- Prefer product HTTP (
/health, /instruments, /runs, door status) over raw
Pyro Proxy without the Opentrons Serpent type registry.
- Store protocol/run IDs as bare UUIDs only (never
PROTO_ID=<uuid> in files
you cat into JSON).
- Default checks: NS health, door, upload/analyze/create-run, uncurrent leak
(RQA-5791), serialization. Nameserver/hardware-api restart is optional
regression of grouped
PartOf= (RQA-5789 / RQA-5790 Closed; see
docs/pyro-testing.md).
- On-robot Serpent registry over SSH: use writable
HOME (e.g. /tmp/ot-home);
/root/.opentrons is often read-only.
- Helper:
scripts/run_pyro_d_suite.sh (full reboot if orphan processes linger).
Live protocol play (physical motion)
Gated motion CLIs (need ALLOW_MUTATIONS=true and an explicit operator request):
flex-test seed-runs (history seeding, including lpc_scripted)
flex-test lpc-jog-timing --confirm-clear-deck (random jogs in a high-Z box on empty C2; never toward the deck)
Do not invent ungated home/move/jog commands. Live protocol play (tip pickup)
only when the user explicitly asks.
When explicitly requested:
- Confirm deck/instruments (tiprack position, clear deck, door closed, estop clear).
- Use a documented protocol under
docs/test-suggestions/protocols/.
- Drive play via robot HTTP run actions (or the gated CLIs above), not ad-hoc shell.
- Prefer
return_tip when no trash is loaded.
Python entrypoints
from flex_testing_agent.config.settings import get_settings
from flex_testing_agent.robots.flex import FlexRobot
from flex_testing_agent.capabilities.probe import probe_robot
from flex_testing_agent.capabilities.inspect import inspect_robot
Use FlexRobot as async context manager. Prefer capabilities over raw clients for multi-step work.
Safety reminders
- Enable access control only via
flex-test crs enable --confirm-one-way when the operator explicitly asks
- Do not implement ungated motion; use
seed-runs / lpc-jog-timing or live play only on explicit user request
- Default pytest excludes
requires_robot / mutates_robot
- Live robot tests:
uv run pytest -m requires_robot
- Service restarts and run mutations may need operator approval in agent sessions
Artifacts
Evidence and photos land under ARTIFACT_DIRECTORY (default ./artifacts/).
Local pyro notes often under artifacts/pyro-tests/ (gitignored).
Test suggestions (GitHub Pages)
Author YAML under docs/test-suggestions/. Preview with make pages. Pushing to main publishes https://opentrons.github.io/flex-testing-agent/.