Greentic Flow
Human-friendly YGTc v2 flow authoring: create flows, add component steps, keep routing safe, and validate everything with one CLI.
Why flows?
- Readable YAML: node key = node name, one operation key inside, routing shorthand (
out|reply|[...]). - Component-free authoring: flows stay human; component sources live in a sidecar resolve file.
- Safe edits: add/update/delete steps rewrite routing deterministically and validate against the schema.
- CI-ready: built-in validator (
doctor) and binstall-friendly releases.
Install
- GitHub Releases (binstall-ready):
cargo binstall greentic-flow - crates.io (no bundled binaries):
cargo install --locked greentic-flow - Direct download: pick the
.tgzfor your target from the latest release and putgreentic-flowon yourPATH.
Create your first flow
new writes an empty v2 skeleton (nodes: {}) so you can start from a clean slate. If you want a ready-to-run “hello” flow, copy the example file we keep in the repo:
That example (also covered by tests) is small and readable:
id: hello-flow
type: messaging
schema_version: 2
start: start
nodes:
start:
templating.handlebars:
text: "Hello from greentic-flow!"
routing: out
Add a component step (scaffold + build with greentic-component)
First scaffold the component with greentic-component new --name hello-world --non-interactive (run it in your desired components directory; it creates hello-world/ with a manifest), then build it:
This produces hello-world/target/wasm32-wasip2/release/hello_world.wasm and dev_flows with defaults. Then add it to a flow:
This inserts a hello-world node (ordering preserved) and writes a sidecar docs/examples/hello_with_component.ygtc.resolve.json that binds the node to your local wasm (add --pin to hash it). The resulting flow looks like:
Local wasm bindings are stored in the sidecar as file://<relative/path> from the flow directory.
id: hello-component
type: messaging
schema_version: 2
start: hello-world
nodes:
hello-world:
handle_message:
input:
input: "Hello from hello-world!"
routing: out
Use public components (remote + pin)
The sidecar records the remote reference and resolved digest (--pin). Perfect for CI where you want reproducible pulls.
Update or delete steps safely
greentic-flow update-step --flow flows/main.ygtc --step hello --answers '{"input":"hi again"}' --routing-reply- Re-materializes using the sidecar binding, prefills current payload, merges your answers, and rewrites routing to
reply.
- Re-materializes using the sidecar binding, prefills current payload, merges your answers, and rewrites routing to
greentic-flow delete-step --flow flows/main.ygtc --step mid --strategy splice- Removes
midand splices predecessors to the deleted node’s targets; removes the sidecar entry too.
- Removes
Validate flows (CI & local)
greentic-flow doctor flows/ # recursive over .ygtc
greentic-flow doctor --json flows/main.ygtc # machine-readable
Uses the embedded schemas/ygtc.flow.schema.json by default; add --registry <adapter_catalog.json> for adapter linting.
Deep dives
- CLI details and routing flags:
docs/cli.md - Add-step design and routing rules:
docs/add_step_design.md - Deployment flows:
docs/deployment-flows.md - Config flow execution:
docs/add_step_design.md
Development
cargo fmt --checkcargo clippy --all-targets -- -D warningscargo test
Or run everything: LOCAL_CHECK_ONLINE=1 ci/local_check.sh
Environment
OTEL_EXPORTER_OTLP_ENDPOINT(defaulthttp://localhost:4317) targets your collector.RUST_LOGcontrols log verbosity; e.g.greentic_flow=info.OTEL_RESOURCE_ATTRIBUTES=deployment.environment=devtags spans with the active environment.
Maintenance Notes
- Keep shared primitives flowing through
greentic-typesandgreentic-interfaces. - Prefer zero-copy patterns and stay within safe Rust (
#![forbid(unsafe_code)]is enabled). - Update the adapter registry fixtures under
tests/data/when new adapters or operations are introduced. - Dependabot auto-merge is enabled for Cargo updates; repository settings must allow auto-merge and branch protections should list the required checks to gate merges.
Releases & Publishing
- Crate versions are sourced directly from each crate's
Cargo.toml. - Every push to
mastercompares the previous commit; if a crate version changed, a tag<crate-name>-v<semver>is created and pushed automatically. - The publish workflow runs on the tagged commit and attempts to publish all changed crates to crates.io using
katyo/publish-crates@v2. - Publishing is idempotent: if the version already exists on crates.io, the workflow succeeds without error.