greentic-flow 0.4.6

Generic YGTC flow schema/loader/IR for self-describing component nodes.
Documentation

Greentic Flow

Generic schema, loader, and intermediate representation for YGTC flows composed of self-describing component nodes.

Quickstart

use greentic_flow::{compile_flow, load_and_validate_bundle, resolve::resolve_parameters, loader};
use greentic_types::NodeId;

let yaml = std::fs::read_to_string("fixtures/weather_bot.ygtc")?;
let bundle = load_and_validate_bundle(&yaml, None)?;
println!("Bundle entry node: {}", bundle.entry);

let doc = loader::load_ygtc_from_str(&yaml)?;
let flow = compile_flow(doc)?;
let node = flow.nodes.get(&NodeId::new("forecast_weather")?).unwrap();
let resolved = resolve_parameters(&node.input.mapping, &flow.metadata.extra, "nodes.forecast_weather")?;
# Ok::<_, greentic_flow::error::FlowError>(())

Design Highlights

  • JSON Schema (schemas/ygtc.flow.schema.json) enforces exactly one component key per node plus optional routing metadata.
  • Loader converts YAML documents to FlowDoc, validates against the schema, extracts component metadata, and performs basic graph checks.
  • Compiler emits canonical greentic_types::Flow nodes so runtimes can post-process component payloads while exposing NodeKind classification for adapters.
  • NodeKind::Adapter recognises node component strings shaped as <namespace>.<adapter>.<operation> and keeps the trailing segments joined so nested operations are preserved.
  • resolve::resolve_parameters pre-resolves only parameters.* references, leaving other runtime bindings intact.
  • start is optional; if omitted and an in node exists, the loader defaults start to in.

Adapter Registry Format

Adapter-backed nodes can be linted against an on-disk catalog that maps <namespace>.<adapter> pairs to the operations they expose. The registry is JSON by default, with optional TOML support via the toml feature.

{
  "adapters": {
    "messaging.telegram": ["sendMessage", "editMessage"],
    "email.google": ["send", "draft.create"]
  }
}

With the registry loaded, the adapter_resolvable rule reports any node whose component string cannot be found in the catalog.

Development

  • cargo fmt --check
  • cargo clippy -D warnings
  • cargo test

Fixtures under fixtures/ mirror common success and failure scenarios.

Run all CI-equivalent checks locally via:

LOCAL_CHECK_ONLINE=1 ci/local_check.sh

Toggles:

  • LOCAL_CHECK_ONLINE=1 — enable networked checks (schema fetch, etc.)
  • LOCAL_CHECK_STRICT=1 — treat missing tools as immediate failures (default already fails required skips unless LOCAL_CHECK_ALLOW_SKIP=1)
  • LOCAL_CHECK_VERBOSE=1 — echo each command
  • LOCAL_CHECK_ALLOW_SKIP=1 — allow required CI steps to be skipped (not recommended)

CLI

Flow scaffolding

greentic-flow ships with a lightweight scaffolder for new .ygtc files:

cargo run --bin greentic-flow -- new flows/demo.ygtc --kind messaging

Flags of note:

  • --kind messaging|events|deployment controls the template. --kind deployment is just sugar for type: events plus a first node that assumes access to the greentic:deploy-plan@1.0.0 world.
  • --deployment aliases --kind deployment.
  • --pack-manifest <path> (or a local manifest.yaml if no flag is provided) lets the tool peek at pack metadata. It will:
    • default --kind to deployment when the pack declares kind: deployment,
    • append the new flow to the manifest's flows: array (path stored relative to the manifest directory), and
    • emit informational hints (for example, when a deployment pack scaffolds a messaging flow anyway).
  • --id, --description, and --force cover the usual ergonomics.

Running the command writes a ready-to-edit .ygtc file and reports any hints.

Flow linting

Run cargo run --bin ygtc-lint -- <paths> to validate flows. Example:

cargo run --bin ygtc-lint -- fixtures --schema schemas/ygtc.flow.schema.json

To enable adapter linting, provide --registry:

cargo run --bin ygtc-lint -- \
  --schema schemas/ygtc.flow.schema.json \
  --registry tests/data/registry_ok.json \
  tests/data/flow_ok.ygtc

For machine-readable CI, use --json; the command exits non-zero on any error and prints the validated bundle plus diagnostics:

cargo run --quiet --bin ygtc-lint -- --json tests/data/flow_ok.ygtc
# { "ok": true, "bundle": { "id": "flow_ok", ... } }

Pipelines can also stream flows via stdin:

cat tests/data/flow_ok.ygtc | cargo run --quiet --bin ygtc-lint -- --json --stdin

And in CI you can assert the BLAKE3 hash is present:

ygtc-lint --json --stdin < flow.ygtc | jq -e '.ok and .hash_blake3 != null'

The CLI recursively walks any directories provided, only inspecting files with a .ygtc extension. Schema validation always runs; adapter checks are additive when a registry is supplied.

The shared flow schema is published from this repository at https://raw.githubusercontent.com/greentic-ai/greentic-flow/refs/heads/master/schemas/ygtc.flow.schema.json and matches the $id embedded in schemas/ygtc.flow.schema.json.

Secrets workflow

  • .ygtc flows do not embed secret requirements or values.
  • Secret requirements are emitted by components/packs and surfaced by tooling such as greentic-secrets init --pack <pack>.
  • Runtimes and preflight tooling should rely on the aggregated pack metadata (and the secrets-store interface) rather than extending the flow schema.

Config flows (convention)

A config flow is a regular flow whose kind may be component-config (or any other string) and whose final node emits a payload shaped as:

{ "node_id": "some_step", "node": { /* full node object with one component key plus routing */ } }

Tools like greentic-dev can execute these flows and splice the emitted node into another flow. The engine itself does not special-case config flows: node components such as questions (prompting for values) and template (rendering a JSON template) are handled like any other component.

For lightweight automation in this crate, config_flow::run_config_flow can execute simple config flows by seeding answers for questions fields and rendering the final template payload into { node_id, node }.

Deployment flows (events-based)

Deployment flows are standard type: events flows that operate on a DeploymentPlan provided by hosting tooling. Use

greentic-flow new flows/deploy_stack.ygtc --kind deployment

to scaffold one quickly. The template creates a first node that highlights the greentic:deploy-plan@1.0.0 world so the component can read the plan and emit status updates. Node IDs and component kinds remain opaque strings; nothing in this crate hard-codes provider-specific behaviour.

See docs/deployment-flows.md for a deeper dive covering plan access, CLI helpers, and authoring guidelines.

A pack may declare kind: deployment in its manifest to signal that most of its flows are deployment-oriented. The scaffolder simply treats that as a hint and emits an informational message if you add a messaging flow to such a pack. Mixed packs remain perfectly valid.

Environment

  • OTEL_EXPORTER_OTLP_ENDPOINT (default http://localhost:4317) targets your collector.
  • RUST_LOG controls log verbosity; e.g. greentic_flow=info.
  • OTEL_RESOURCE_ATTRIBUTES=deployment.environment=dev tags spans with the active environment.

Maintenance Notes

  • Keep shared primitives flowing through greentic-types and greentic-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 master compares 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.