Engineering Philosophy
The principles behind Hanzo V8 — one and one way, decomplect, ZAP-native, the language seam is the wire not FFI, one contract to N SDKs to thin CLIs.
Engineering Philosophy
Hanzo V8 · Open Edition is composed from a small set of decisions applied everywhere, so that no consumer ever needs to know or care which part is Go and which is Rust. This page is the why — the design pedagogy. The canonical, normative version lives in HIP-0127.
One rule ties the whole platform together: one contract, many bindings, thin clients, and a wire — never FFI — between languages.
One and one way
There is exactly one way to do everything, by construction. A capability is
one name = one /v1/<name> = one self-contained spec — no svc suffix, no
singular/plural twins, no facade. The capability manifest
(capabilities.yaml) is the single registry: every spec must appear there
exactly once, in exactly one of the eight movements. The build fails
on an orphan spec, an unlisted spec, or a name in two places. Orthogonality is a
build invariant, not a hope.
The same rule governs distribution: one contract, one client core per stack, one distribution harness. Every SDK and CLI is derived from the contract — none is hand-forked.
Decomplect — values, not places
Following Rich Hickey: a capability is named by its value (its /v1 route),
not by its place (which repo, language, or pod implements it). We decomplect
— unbraid — the things that naive designs fuse together.
Values, not places
A capability is its route, not its host. Callers bind to /v1/<name>, never to a machine, a process, or a language.
One concern per binary
The Go/Rust boundary is a value boundary (ZAP frames), not a place boundary (FFI in one address space). Each box does one thing.
Easy ≠ simple
FFI is easy — one repo, one process — but complects two toolchains. The wire seam is simpler: independent, composable, language-free at the edge.
Compose, don't inherit
Capabilities are composed over a uniform wire, not extended through shared implementation. Orthogonal and independently complete.
One binary, one contract
The application cloud is one Go binary (cloud, CGO_ENABLED=0, static),
embedding the platform's subsystems and mounting them behind a single public
surface: /v1/<capability> over HTTP + ZAP. That is the ONE contract every
consumer speaks. Capabilities are grouped into the eight movements of the
manifest; each is one name, one route, one spec.
Keeping it pure Go with no cgo is what preserves the single static binary — the thing that makes "run the whole cloud anywhere" true.
The language seam is the wire, never FFI
Hanzo is Go and Rust. The cloud is Go; the engine,
the dev agent, and the ML kernels are Rust. They compose over
ZAP — network or local socket — each a clean single-language
binary. Go cloud and the Rust components never link each other's code; they
exchange ZAP frames whose schema lives beside the product that implements it.
Two naive urges, both rejected:
Don't fuse over FFI
cgo/uniffi in one process destroys the CGO_ENABLED=0 static binary and complects two toolchains. Rejected.
Don't split orgs by language
No hanzo-go / hanzo-rs. That leaks an implementation detail into the org and forces users to know which half a capability lives in. Rejected.
Everything canonical lives under hanzoai/<product> — organized by
capability, not by language. Users never know which language answered, because
the org is product-first and the wire is uniform — not because the languages
are fused.
One contract → N SDKs → thin CLIs
Distribution is a single derivation tree. The one contract generates the language bindings and the wire types; the clients are thin frontends over a shared core.
hanzo.yaml the ONE contract — /v1 over HTTP + ZAP
│ generate ↓
go-sdk · rust-sdk · js-sdk language bindings (derived)
zap-spec the ZAP wire types
│
hanzo-client (Rust: ZAP bridge + hanzo.id auth + rust-sdk)
├── hanzo — the control CLI → @hanzo/cli
└── dev — the coding agent → @hanzo/dev- The CLI is a client, never the server. It speaks ZAP (or its SDK) to a live cloud — production, a laptop, or a self-host — and never imports the cloud. That coupling is the trap that bloats a client to hundreds of megabytes.
- One client core, two thin frontends.
hanzo(the control CLI) anddev(the coding agent) share one Rusthanzo-client: one auth stack, one ZAP client, one SDK. The result is a ~15 MB binary — small enough to ship over npm. - One harness, many channels. Per-platform prebuilt binaries on GitHub
Releases fan out to
@hanzo/cli/@hanzo/dev(npm),hanzo.sh(curl | sh), Homebrew, andgo install. One binary per tool, N channels.
.zap and OpenAPI are two transports of the same /v1 contract — both
derived from the per-service spec, never hand-maintained separately. One
contract → HTTP + ZAP + SDKs, all generated.
Deploy: native PaaS, no second deployer
Deploys go through the native PaaS (hanzoai/platform), which merge-patches the
operator's Service resource; the operator reconciles the rollout. No second
deployer. It is driven by the hanzo CLI or the platform UI — the
same one contract, all the way to production.
Read the specs
Architecture
How Hanzo Cloud is built today and the direction it is converging on.
The Network
The AI cloud you can run yourself — one binary, BYO GPU, the network is the cloud.
ZAP Protocol
Zero-Copy App Proto — the wire the Go and Rust halves speak.
Hanzo Improvement Proposals
HIP-0127 and the specs it ties together: the unified binary, ZAP, the SDKs, the CLI.
How is this guide?
Last updated on
Architecture
How Hanzo Cloud is built today, and the plugin-platform direction it is evolving toward.
The Platform Algebra
The whole cloud is a small set of primitives — Principal, Tenant, Resource, Policy, Ledger, Meter, Schedule, Bus, Gateway, Store, Money — and every product is a composition of them. Declare a schema, attach a policy, and persistence, tenancy, audit, and metering come free.