Pydantic v2 schemas, OpenAPI for free, mature async
Successor with same Pydantic + async story (Litestar)
Validation
Pydantic v2
De facto FastAPI schema standard
Coupled to HTTP framework
Settings
pydantic-settings
Env-var Settings class with Pydantic validation
Coupled to Validation
Runtime JSON Schema
jsonschema-rs
Rust-backed validator for schema-validated values (Capability / Method / Asset settings) at request time; distinct from Pydantic, which validates the HTTP envelope
Validator semantics or Draft support outgrowing the Rust binding
Backs the LLM port through the AnthropicLLM adapter; powers the RunDebriefer and CautionDrafter subscribers (reasoning generation is shipped). Subscribers, deciders, and tests use the port + FakeLLM, never the SDK
Provider change; a future OpenAILLM / local-model adapter slots behind the same port without subscriber changes
The ControlPort behind the Operation BC speaks EPICS or Tango, selected per control route. Production reads and writes go through the asyncio EPICS clients; tests drive a real softIOC subprocess rather than the production clients.
Role
Pick
Why
Swap trigger
EPICS Channel Access
aioca
Production asyncio CA client behind EpicsCaControlPort; Diamond Light Source-maintained
CA workload outgrowing the client
EPICS pvAccess
p4p
Production asyncio PVA client behind EpicsPvaControlPort; carries Normative Types (NTNDArray image streams CA cannot)
PVA workload outgrowing the client
EPICS test IOC
caproto + epicscorelibs
Test-only: epicscorelibs.ioc spawns a real softIOC subprocess; caproto backs the test-only CaprotoControlPort. caproto's own README warns against production use
Stays test-only; production CA/PVA go through aioca / p4p
Tango device attributes
pytango
Production Tango client behind TangoControlPort, the ESRF / MAX IV / Elettra / ALBA control-plane family; ships in the optional tango extra so an EPICS-only deployment does not carry it
The three remaining substrate-bearing ports behind the Operation BC. Each ships a production adapter alongside an in-memory one, and the two heavyweight ones sit in optional extras so a deployment that does not use them does not install them.
Role
Pick
Why
Swap trigger
Bulk data transfer
globus-sdk
Production Globus Transfer client behind GlobusTransferPort; the facility-to-facility movement path most light sources already operate. A base dependency, not an extra
A facility whose data path Globus does not reach
Remote compute submission
globus-sdk
GlobusComputePort submits jobs to a Globus Compute endpoint; FdtTransferPort and the in-memory adapter cover the other shapes
An HPC scheduler seam Globus Compute cannot express
HDF5 reads
h5py
Reads the detector-side HDF5 the acquisition path writes
Stays
Bayesian-optimization search
botorch (with torch, gpytorch)
Backs BoTorchDecidePort for steered experiments; SobolDecidePort covers the quasi-random baseline. Ships in the optional bo extra, MIT and BSD-3 licensed, and the adapters import it lazily so a deployment without the extra still boots
A search problem BoTorch's acquisition functions cannot express