Architecture
Product boundary
OpenSDL is the portable foundation around a laboratory implementation. It owns contracts, reference execution, extension interfaces, conformance, provenance, and developer tooling. It does not attempt to replace every instrument driver, robot framework, LIMS, ELN, workflow engine, scientific solver, optimizer, or safety controller.
Reference topology
The reference system is a modular monolith by default: one process composes the registry, policy engine, runtime, repositories, artifact store, and operator gateway. This is intentionally easier to understand and deploy than an initial microservice architecture.
Components can be separated when scale or equipment-network boundaries justify it. Public contracts and adapters remain stable as deployment topology changes.
Two-repository model
Framework repository
The public monorepo contains reusable packages, applications, adapters, domain packs, templates, and tests.
Laboratory repository
An organization repository contains the concrete laboratory manifest, private workflows, local adapters, domain extensions, deployment settings, and validation evidence. It depends on released OpenSDL packages and can selectively override components through extension interfaces.
This separation prevents proprietary operational state from leaking into the public framework while preserving a standard implementation shape.
Package dependency direction
flowchart LR
subgraph Foundation
CORE[core]
SCH[schemas]
end
subgraph Contracts
TWIN[twin]
CAP[capabilities]
POL[policy]
WF[workflows]
ST[storage]
end
subgraph Execution
SIM[simulation]
RT[runtime]
PROV[provenance]
OPS[operators]
end
subgraph Interfaces
SDK[sdk]
CTRL[controller]
API[api]
CLI[cli]
end
subgraph Extensions
AD[adapters]
DP[domain packs]
end
CORE --> SCH
CORE --> TWIN
CORE --> CAP
CORE --> POL
CORE --> WF
CORE --> ST
CORE --> SIM
CORE --> RT
CORE --> PROV
CORE --> OPS
CORE --> SDK
CORE --> CTRL
CORE --> API
CORE --> AD
CORE --> DP
SCH --> OPS
SCH --> SDK
SCH --> CTRL
SCH --> CLI
TWIN --> CTRL
TWIN --> CLI
CAP --> SIM
CAP --> RT
CAP --> OPS
CAP --> CTRL
CAP --> AD
POL --> RT
POL --> CTRL
WF --> RT
WF --> CTRL
ST --> RT
ST --> PROV
ST --> OPS
ST --> CTRL
SIM --> AD
RT --> OPS
RT --> CTRL
RT --> AD
PROV --> CTRL
PROV --> CLI
OPS --> CTRL
CTRL --> API
CTRL --> CLI
API --> CLI
The boxes are dependency tiers, not packages. adapters and domain packs are grouped nodes; an
edge into a group holds for at least one member.
Rules:
coreimports no internal package.- Applications compose packages; domain behavior does not live in applications.
- Vendor and facility code belongs in adapters.
- Schemas remain language-neutral even when Pydantic is the Python implementation.
- Storage is accessed through repository interfaces.
- Simulation is available without importing physical adapters.
- Operator transports depend on the runtime; the runtime does not depend on a particular transport.
- The digital twin imports
coreonly; nothing on the execution path depends on it. - The allowed map grants only what the code imports. Widening it is a deliberate change, so an unused permission is removed rather than left standing.
scripts/check-boundaries.py enforces these rules. Every edge above is an allowed import direction
in that map, and each one is currently exercised.
Execution model
A workflow is a directed acyclic graph of capability invocations. The reference runtime:
- validates the graph;
- creates or resumes a durable run;
- evaluates policy for each step;
- leases required resources;
- resolves inputs from workflow inputs and predecessor outputs;
- executes ready steps concurrently;
- records attempts, outputs, failures, and events;
- releases leases;
- resolves workflow outputs;
- stores a content-addressed run record.
Running tasks found after a controller restart are marked intervention_required. A caller can then inspect physical state before resuming. This avoids pretending database rollback reverses a physical action.
Capability contract
Each capability declares:
- stable identifier and version;
- executor type;
- JSON input and output schemas;
- resources and side effects;
- risk class;
- timeout, retries, and whether cancellation is supported;
- simulator availability;
- extension metadata.
The adapter controls transport details. Workflows request semantic capabilities rather than vendor commands. The v0.1 runtime records each capability's cancellation declaration. It does not expose an end-to-end cancellation or abort workflow. Explicit cancellation and abort receipts remain v0.2 work. Operational behavior remains deployment-specific.
Persistence
Relational tables store runs, tasks, events, capabilities, resources, leases, artifacts, and schema versions. SQLite is the default local profile; SQLAlchemy keeps the model portable to PostgreSQL.
Artifact bytes live outside the relational database. The local store uses SHA-256-addressed paths and verifies content on read. S3-compatible storage is a planned adapter.
Provenance and graphs
The append-only event stream is the historical source. Current state and research graphs are projections. Portable exports package run metadata, tasks, events, and artifact bytes.
The repository propagation graph is separate from the scientific graph. It tracks implementation dependencies such as schema → adapter → tests → examples → docs.
Digital twin projection
opensdl-twin binds an authored 3D scene to the semantic laboratory. A versioned definition declares
a coordinate frame, a digest-pinned scene asset, stable entities and anchors, and rules that map
persisted events to visual cues. The package imports core only. The controller loads the configured
definition, verifies the scene digest, and projects one stored run. The CLI and the HTTP API expose
that result read-only.
The twin is a projection of the recorded event stream, like the research graph. It does not execute capabilities, command equipment, advance a run, or report physical state. It does not sit on the execution path, and a laboratory that declares no twin runs identically. The framework carries one reference showcase; each laboratory owns its scene source. See lab-specific digital twins.
Operator interfaces
The same contracts are exposed through:
- the Python SDK;
- CLI commands;
- the HTTP API;
- a transport-neutral operator gateway;
- an optional MCP server when the MCP package is installed.
No operator receives raw device transport as a framework primitive. An organization may grant broad authority, but execution remains represented through declared capabilities and recorded receipts.
Extensibility
Entry-point groups:
opensdl.adaptersopensdl.optimizersopensdl.domain_packs
Future extension groups will cover storage, artifact stores, policy providers, exporters, and orchestration backends once two independent implementations justify a stable interface.
Deployment profiles
simulation: virtual equipment and compute, suitable for CI.assisted: structured human tasks mixed with connected systems.automated: validated deterministic workcells.closed-loop: optimization selects subsequent work inside declared bounds.air-gapped: local models and services with controlled package promotion.
The current reference implementation fully supports the simulation profile and a basic assisted path through structured human attestations. Interactive queues, electronic signatures, and deployment-specific identity controls remain future integrations.