Ogol exists to make automation programming easier for humans to understand. As AI takes on more of the work of generating automation logic, people still need to review that logic, trust it, and stay responsible for its behavior. The goal of Ogol is to make automation code, whether written by a person or generated by AI, easy to inspect, explain, and verify.
Ogol is the host architecture and execution model; the authored modules are the domain program it edits, projects, compiles, and runs.
In practice, Ogol is a BEAM-native automation language and Studio for source-backed authoring. It treats automation artifacts as source first, projects them into Studio views when possible, and keeps runtime state separate from authored intent.
Ogol is built around one practical requirement: automation logic must remain inspectable by humans even when more of it is generated or assisted by AI.
That means:
- source stays authoritative
- visual editors are projections, not a second truth
- composition is explicit
- runtime state is observed, not confused with authored intent
- humans stay responsible for understanding what will run
The repo currently includes:
- a Spark-backed machine DSL that generates OTP runtime modules
- explicit topology composition with one active topology per node
- source-backed artifact types for machines, topology, hardware configs, simulator configs, sequences, and HMIs
- EtherCAT simulator and master integration
- Phoenix LiveView runtime surfaces under
/ops - Studio authoring surfaces under
/studio - bundle import/export in
.ogol.exformat - Playwright-backed end-to-end integration tests
The public machine model is intentionally small:
skillsstatussignals
Typical runtime interaction looks like this:
MyMachine.skills()
MyMachine.start(pid)
Ogol.Runtime.Delivery.invoke(target, :start, %{}, [])
MyMachine.status(target)Ogol.Runtime.Delivery.invoke/4 is the main composition primitive. Low-level
request and event plumbing exists, but it is not the long-term public API story.
Studio is organized around source-backed authoring surfaces:
/studio/machinesmachine authoring with compile/apply controls and visual/source views/studio/topologythe canonical authored topology for the current workspace, with apply/start/stop/studio/hardwareadapter-scoped hardware configuration authoring/studio/simulatoradapter-scoped simulator configuration authoring/studio/sequencessequence authoring, compile, and runtime inspection over source-derived machine contracts/studio/hmisHMI authoring for the current workspace
Embeddable cell-body routes also exist under /studio/cells/..., so the same
artifact body can be rendered inside the full Studio shell or in isolation.
Runtime-facing surfaces live under:
/ops/ops/hmis/ops/machines/:machine_id
/ops is the canonical runtime control plane. The overview at /ops owns
cell-level procedure control, Manual/Auto handoff, and operator recovery.
Sequence Studio may reflect live procedure state, but it is no longer a
runtime mutation surface.
Across Studio, source remains the durable truth. Visual editors are honest projections of that source and fall back to source editing when the authored artifact leaves the supported visual subset. Studio does not own a second artifact model; it renders and mutates the same source-backed program that the runtime later compiles and realizes.
The repo seeds a complete multi-machine demo into Studio:
- root machine:
pack_and_inspect_cell - child machines:
infeed_conveyorclamp_stationinspection_stationreject_gate
- topology:
pack_and_inspect_cell - simulator config:
Pack and Inspect Cell Ring
The scenario is a small inspection cell:
- feed a part in
- clamp it
- inspect it
- either pass it or reject it
This seed is meant to exercise the full stack:
- simulator
- EtherCAT master
- topology runtime
- multi-machine coordination
- topology-scoped HMI authoring
- runtime visualization under
/ops
Canonical examples now live as revision files under priv/examples.
They use the same source format as saved Studio revisions, so loading an example
is the same as opening a revision into the workspace.
Current checked-in example:
priv/examples/pump_skid_commissioning_bench.ogol.exreal EtherCAT commissioning bench with one coupler, one digital input card, one digital output card, explicit simulator loopback wiring, four hardware-bound machines, and one sequence that waits on machine signals
Load them from Studio Home or through Ogol.Studio.Examples.
This project depends on the sibling EtherCAT repository at ../ethercat.
Start the app with:
mix setup
mix phx.serverThen open http://localhost:4000.
Run the Elixir suite with:
mix testInstall Playwright once with:
mix integration.setupRun the main browser end-to-end flow with:
mix test test/integration/playwright/playwright_machine_hmi_e2e_test.exsRun the commissioning and procedure-control browser flow with:
mix test test/integration/playwright/playwright_commissioning_example_test.exsRun it visibly with slowdown:
PLAYWRIGHT_HEADLESS=false PLAYWRIGHT_SLOW_MO=250 mix test test/integration/playwright/playwright_machine_hmi_e2e_test.exs- source is the only durable truth
- visual editing is a projection of source, not a second authority
- desired state and observed state are different concerns
- topology is explicit and flat on a node
- only one topology may be active on a node at a time
- EtherCAT simulator and EtherCAT master are separate runtime roles
Useful design docs: