Shared Lab Operations
This page is the workflow companion to Lab and device claims.
Use it when the commands themselves are already familiar, but the question is operational:
- how should we shape
--device-queryin a shared pool? - when should we use
lab planbeforelab claimorrun --claim-device? - how should CI jobs behave when the selected hardware is leased or quarantined?
Query rules that matter in practice
Section titled “Query rules that matter in practice”--device-query is deliberately simple:
- clauses use exact-match
key=valuesyntax - clauses are comma-separated
- matching is case-insensitive
- Luotsi expects one selected target for commands such as
device-status,view,inspect, orrun --claim-device
The useful public keys are:
serialstatetransporttypemodelproductdeviceavailability
Two fields are especially useful in shared labs:
state=onlinenarrows to transports that adb currently considers usableavailability=availablemirrors the adb-derived availability field fromluotsi devices; lease and quarantine gates are still applied separately bylab status,lab plan,lab claim, andrun --claim-device
If you want raw inventory, use luotsi devices. If you want selection semantics, use lab status or lab plan. devices intentionally does not accept --device-query.
Inventory-backed admission
Section titled “Inventory-backed admission”When the shared lab keeps durable pool or capability metadata, treat that as a second admission layer instead of trying to encode everything into the query itself.
luotsi lab inventory listluotsi lab status --device-query state=online,type=physical --device-pool checkout --require-capabilities camera,nfcluotsi lab plan --device-query state=online,type=physical --device-pool checkout --require-capabilities camera,nfc--device-pool <pool> and --require-capabilities <csv> sit beside --device-query: the query still filters live adb and device fields, while the inventory admission filters require a matching durable registration before Luotsi selects or claims hardware.
Example query patterns
Section titled “Example query patterns”| Goal | Query |
|---|---|
| Any online physical device | state=online,type=physical |
| One specific shared phone model | state=online,type=physical,model=Pixel_9 |
| Only adb-available pool hardware | state=online,type=physical,availability=available |
| One Wi-Fi attached device class | state=online,transport=wifi,model=Pixel_9 |
| One emulator lane | state=online,type=emulator |
Treat queries as selection contracts, not fuzzy searches. When a query is too broad, refine it with one more clause instead of relying on incidental device order.
Why lab plan should come before a claim
Section titled “Why lab plan should come before a claim”lab plan is the dry-run allocator. It answers two questions without mutating lab state:
- which device would Luotsi pick for this query?
- if nothing can be picked, what command should the operator or agent run next?
luotsi lab status --device-query state=online,type=physical,availability=availableluotsi lab plan --device-query state=online,type=physical,availability=available,model=Pixel_9Use lab plan as the decision point before claiming or starting a CI run. It is the safest way to turn a broad pool into one explicit target and it already returns recommended_commands when the selection is blocked.
That matters because availability=available only reflects adb-level readiness. Lease and quarantine blockers are surfaced by the lab commands themselves.
Workflow: one engineer, several attached devices
Section titled “Workflow: one engineer, several attached devices”This is the local debugging case where multiple transports are visible and you want one reliable target without guessing.
luotsi lab status --device-query state=online,type=physicalluotsi lab plan --device-query state=online,type=physical,model=Pixel_9luotsi device-status --device-query state=online,type=physical,model=Pixel_9luotsi view --device-query state=online,type=physical,model=Pixel_9Use device-status --device-query ... once the query is narrow enough to select exactly one target. If it still matches multiple devices, go back to lab status or lab plan and add another clause.
Workflow: one CI job, one leased device
Section titled “Workflow: one CI job, one leased device”This is the default pool-safe automation pattern.
luotsi lab plan --device-query state=online,type=physical,availability=available,model=Pixel_9 --device-pool checkout --require-capabilities camera,nfcluotsi run --path scenarios --device-query state=online,type=physical,availability=available,model=Pixel_9 --claim-device --device-pool checkout --require-capabilities camera,nfc --owner gh-actions-4821 --ttl-sec 1800 --report-junit junit.xmlWhy this pattern works:
lab planproves the query is sane before the job mutates lease staterun --claim-devicekeeps the lease lifecycle attached to the scenario run itself--ownermakes the lease visible as a CI job, not just as a generic host user- the lease is released from the run’s cleanup path instead of relying on a separate human release step
Use explicit lab claim first only when the lease boundary needs to outlive one command.
Workflow: one pool, multiple job classes
Section titled “Workflow: one pool, multiple job classes”When different jobs target different hardware classes, keep the distinction in the query itself.
Examples:
- smoke tests on emulators:
state=online,type=emulator - camera-sensitive runs on physical Wi-Fi devices:
state=online,type=physical,transport=wifi - one model-specific regression lane:
state=online,type=physical,model=Pixel_9,availability=available
That keeps the allocation policy visible in source control instead of hidden in whoever happens to know the current lab state.
Workflow: blocked by an existing lease
Section titled “Workflow: blocked by an existing lease”When a query matches only leased devices, Luotsi will fail selection on purpose instead of silently stealing hardware.
luotsi lab plan --device-query state=online,type=physical,model=Pixel_9luotsi lab leasesluotsi lab release --serial <serial>Use lab plan first because it already tells you whether the blocked state is a lease problem and suggests the next commands. Use lab extend instead of release/reclaim if the current owner is still valid and the job simply needs more time.
Workflow: blocked by quarantine
Section titled “Workflow: blocked by quarantine”Quarantine is not just another failure. It is an explicit operator decision that the device should stay out of rotation.
luotsi lab plan --device-query state=online,type=physical,model=Pixel_9luotsi lab quarantinesluotsi lab unquarantine --serial <serial>Only unquarantine after the hardware is actually healthy again. If the issue is still real, keep the device quarantined and adjust the selection query or pool routing instead.
When to use lab claim directly
Section titled “When to use lab claim directly”Use explicit lab claim when the device lease needs to span more than one Luotsi command, for example:
- a human operator is about to do
view,inspect, and thenrun - a CI workflow has a preflight/setup stage before the scenario run starts
- a device should be reserved while another system prepares the app or environment
luotsi lab claim --device-query state=online,type=physical,model=Pixel_9 --owner local-debug --ttl-sec 3600luotsi view --device-query state=online,type=physical,model=Pixel_9luotsi inspect --device-query state=online,type=physical,model=Pixel_9luotsi lab release --serial <serial>If the unit of ownership is the scenario run itself, prefer run --claim-device instead.
Common operator rules
Section titled “Common operator rules”- Prefer
state=onlineover guessing from raw adb status text. - Prefer
lab statusorlab planwhen the pool is shared and lease or quarantine state matters;availability=availableonly reflects adb-level readiness. - Use
lab statusfor explanation,lab planfor dry-run allocation,lab claimfor longer-lived reservation, andrun --claim-devicefor run-scoped reservation. - Use either
--deviceor--device-query, never both.