The graph-native programming language

Programs are graphs.

flowg stores code as what it actually is — a typed dataflow graph, not text. Materialize it to many languages. Lower it to many silicons. Meter every operation in picojoules.

Scroll
I · The Problem

Text is a lossy serialization
of a computation graph.

Every program is a network of operations connected by typed, directed data flows. Every language is syntactic sugar over that structure. Flattening it to 1-D text destroys ownership, dataflow direction, concurrency shape, and type invariants — and then every tool spends cycles reconstructing the graph from the text, only to flatten it again.

22
Primitive node
kinds (closed set)
11
Wire kinds
(ownership semantics)
many
Languages emitted
from one graph
pJ
Cost unit, per op,
per silicon
"The graph is canonical. Text in any language is just one projection of it — produced by lookup, not guessed token by token." The flowg premise
II · The Graph

A typed hypergraph,
not a text file.

Nodes are computation primitives. Edges are resource-semantic wires — Rust's ownership generalized: Move, Borrow, Stream, Feedback, and more. Each Apply node carries an operation with physical cost metadata. This is the IR — the same one the runtime executes.

scale_and_sum.fg
// flowg graph: scale_and_sum  (the graph is the program)
graph scale_and_sum(xs: tensor<f32>, k: f32) -> f32 {
  n0  Param          xs
  n1  Param          k
  n2  Apply mul      (n0, n1)        // Custom("mul")
  n3  Apply reduce_sum (n2)         // → backend chosen by joules
  return n3
}
// wires carry ownership: n0 ──Move──▶ n2 ──Move──▶ n3
Closed kernel
22 universal primitives in 7 categories — computation, resource, error, concurrency, data/state, temporal — cover every programming pattern.
Ownership in the wires
11 wire kinds carry the semantics text throws away: who owns a value, what borrows it, what streams, what loops back.
Capabilities & effects
No ambient authority. Effects are declared on the node and checked at dispatch; capability handles are unforgeable and delegable.
III · Materialize

One graph.
Many languages.

The same graph projects to source in many target languages — deterministically, the same output on every machine, every run. Text becomes a view, not the source of truth.

→ rust
fn scale_and_sum(xs: &[f32], k: f32) -> f32 {
    xs.iter().map(|x| x * k).sum()
}
→ python
def scale_and_sum(xs, k):
    return sum(x * k for x in xs)
→ wgsl
// emitted WGSL compute shader (WebGPU)
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) g: vec3<u32>) {
    out[g.x] = xs[g.x] * k;
}
RustPythonGoTypeScriptCWGSLONNXStableHLOMLIRTritonWASM
IV · Energy

Routed to the silicon that
does it for the fewest joules.

Each operation carries a cost. flowg's placement pass picks the backend — CPU, Metal, AMX, CUDA, WebGPU, Wasm — that runs it at the lowest verifiable joules, with no default to any one device. Every run can produce an energy receipt.

Energy Receipt · scale_and_sum @ apple-m3
total_energy8.42 µJ
  mul → op-metal (gpu)5.91 µJ
  reduce_sum → op-blas (cpu)2.51 µJ
placementmin-joule (measured)
vs cpu-only−38%
determinismstrict · bit-reproducible

Picojoule cost model · analytical prior refined by measured calibration.

V · The Substrate

The shared target
beneath the languages.

flowg is the graph every sibling language lowers into. They differ in surface; the target is identical. A program written in Joule runs a fused kernel on Metal without the language ever naming Metal.

VI · Get Started

Inspect a graph.

Build the toolchain, make a sample graph, and watch it run across devices with a joule receipt.

terminal
$ cargo install flowg-cli
$ flowg make-sample > scale_and_sum.fg
$ flowg inspect scale_and_sum.fg
$ flowg run scale_and_sum.fg --receipt
  total: 8.42 μJ  ·  placement: min-joule  ·  determinism: strict
Graph-nativeDeterministicHeterogeneousEnergy-meteredWASMWebGPUCapability-typedEdge AI