name and id fields in a Flow (input names, node ids, the flow’s own id) are user-defined. You pick them when authoring; the compiler uses them only to correlate outputs with downstream bindings. Pick short, meaningful names like amountIn, swap, zap. They’re what you read when debugging the wire-format JSON.
Top-level shape
chainId is the EVM chain every call in this Flow targets; inputs whose resource is on a different chain are rejected at build time. inputs declares the named values the flow consumes; nodes is the ordered list of op calls. For the field-by-field reference of every key, see Flow Schema.
Inputs
Each input is either a resource input (a token, with linear consumption) or a handle input (a typed scalar likeuint256 or address, copy-mode).
Resource inputs carry a balance through the flow. By default exactly one downstream call consumes them. A copy-mode binding can read a resource without consuming it — core.approve, for example, references a resource to approve a spender while leaving the balance available for a later consuming binding. A copy-mode read can coexist with one consuming binding for the same resource. The op manifest’s port metadata determines which binding consumes and which only reads.
Handle inputs are non-linear: a uint256 representing a deadline or slippage tolerance can be wired into every op that needs it.
Calls (nodes)
ACall is a single op invocation. The order of nodes is the order the compiler lowers them. Each call has a user-defined id (referenced by downstream calls as <id>.<port>), an op name from the manifest, a bind map wiring its input ports to refs or literal values, op-specific config, and optional guards enforcing invariants.
See References for the ref grammar and Guards for what guards do.
Ports and handles
Ops declare typed input and output ports in the manifest. Each port has a type (resource or handle), a mode for resource ports (consuming vs read-only), and an availability (input vs output). The SDK hands you handles for those ports (builder.inputs.amountIn, or the object returned by a previous op call) and converts them to wire-format $ref strings when it serialises the Flow. The validator rejects bindings whose handle type or mode doesn’t match the port.
See References for scope rules, reserved prefixes, and handle-to-ref conversion.
Putting it together
Theswap-and-zap quickstart produces a Flow that, after builder.build(), looks roughly like:
Inputs and node bindings carry resources (token balances) and handles (typed scalars). The next page, Resource Model, covers how those behave at runtime.
See also
- Flow Schema — field-by-field reference of every key.
- Resource Model — how resources and handles behave at runtime.
- References — how
input.*,context.*, and<nodeId>.<port>refs resolve. - Execution Model — how a Flow becomes calldata.

