Architecture overview¶
Operonx ships as a single Python package with optional extras and a single Rust crate. Both backends share the same workflow contract — a graph defined once, runnable on either runtime.
Component map¶
flowchart TB
User["User code<br/>(@op functions, @graph builders)"]
subgraph CORE["operonx.core"]
Operon["Operon (engine)"]
GraphOp["GraphOp"]
Op["Op (FuncOp / BranchOp / GraphOp)"]
State["MemoryState<br/>(PARENT / op refs)"]
ResourceHub["ResourceHub<br/>(resources.yaml)"]
Tracers["Tracers<br/>(local, Langfuse, OTEL)"]
end
subgraph PROV["operonx.providers"]
LLMOp["LLMOp"]
EmbeddingOp["EmbeddingOp"]
RerankOp["RerankOp"]
end
subgraph RUST["rust/operonx"]
OperonRs["Operon (Rust)"]
Scheduler["GraphScheduler<br/>(+ child schedulers)"]
Inventory["#[op] inventory"]
end
User -->|builds| GraphOp
GraphOp -->|owns| Op
Op -.->|reads/writes| State
User -->|constructs| Operon
Operon -->|drives| GraphOp
Operon -.->|emits frames| Tracers
Op -.->|resolves resource:name| ResourceHub
LLMOp & EmbeddingOp & RerankOp -.->|are kinds of| Op
GraphOp ==>|graph.serialize()<br/>JSON spec| OperonRs
OperonRs --> Scheduler
Scheduler -.->|looks up #[op] funcs| Inventory
classDef core fill:#ede7f6,stroke:#5e35b1,color:#311b92
classDef prov fill:#e0f2f1,stroke:#00897b,color:#004d40
classDef rust fill:#fff3e0,stroke:#f57c00,color:#e65100
class Operon,GraphOp,Op,State,ResourceHub,Tracers core
class LLMOp,EmbeddingOp,RerankOp prov
class OperonRs,Scheduler,Inventory rust
The thick arrow from GraphOp to the Rust Operon is the JSON
hand-off: graph.serialize() produces a portable spec the Rust
runtime loads and runs against the same op semantics. See
Rust and Python for the parity contract.
Source layout¶
Operonx/
├── operonx/ # Python package
│ ├── core/ # Engine, ops, state, tracing, registry
│ ├── providers/ # LLM, embedding, reranker, ONNX backends
│ └── telemetry/ # Langfuse, OTEL, local tracers
├── rust/ # Rust workspace
│ ├── operonx/ # Engine + providers + telemetry
│ └── operonx-macros/ # Proc-macros (#[op], #[model], #[resource])
├── examples/python/ # Runnable examples
├── tests/
│ ├── internal/ # Backend-specific unit tests
│ └── spec/ # JSON-fixture tests shared with Rust
└── docs/ # This site
Glossary¶
| Term | Meaning |
|---|---|
Engine (Operon) |
Pure orchestrator. Takes a graph, runs it, emits frames. |
Graph (GraphOp) |
A DAG of ops. Built with with GraphOp(...) as g: + >> edges. |
| Op | A node in the graph. Created via @op, LLMOp.of(...), etc. |
| Edge | >> (hard) or >>~ (soft, branch-conditional). |
| Frame | One execution step — when an op produces output, a frame is emitted. |
| PARENT | Marker for inputs from engine.run() or the parent graph. |
| op["key"] | Reference to a sibling op's output within the same graph. |
| ResourceHub | Singleton resolving resource="gpt-4o" → backend config. |
| Bootstrap | Explicit setup call: operonx.bootstrap() loads .env + resources.yaml. |
Core invariants¶
Operon(graph)is a pure orchestrator. It does not load.envorresources.yaml. It does not clobber a pre-installedResourceHub. See Resource hub for the setup model.- State is referenced by symbol, not by string.
PARENT["x"]andop["y"]resolve through the schema layer, so renames are checked before the engine runs. >> ENDauto-forwards the last op's outputs to the graph result. Explicit mapping usesop["src"] >> PARENT["dest"]oroutputs={"src": PARENT["dest"]}.- Ops are async-first. Even a
defop (noasync) is wrapped and awaited by the scheduler — concurrency is the default.
Package dependencies¶
operonx.core (foundation — no operonx siblings)
↓
operonx.providers (depends on core)
↓
operonx.telemetry (depends on core)
Rust mirrors the same shape inside the operonx crate; operonx-macros is a
proc-macro crate consumed only via re-exports.
Where to read next¶
- Execution flow — engine init, warmup, run loop.
- State model —
PARENT,op[key], output mapping. - Streaming — generator ops and frame iteration.
- Rust and Python — choosing a backend, parity guarantees.
- Resource hub — the full setup model.