riceprompt-engine: a YAML workflow graph for LLM agents, written in Rust
YAML-native agent workflow execution engine, written in Rust
At a glance
- What is it?
- The crate riceprompt-engine (repository jieyefriic/rp-engine) parses a single YAML file that describes nodes, edges, prompts and data sources, then executes that graph as an agent workflow. It is a 0.1.x library with an explicit warning that the API may change between minor versions, so the decision to adopt it is a decision about pinning and about how much of the YAML spec you are willing to track.
- Who is it for?
- Adopt riceprompt-engine if you want the workflow graph to live in version control as YAML and you are willing to pin an exact 0.1.x version, because the README states the API may change between minor releases. Do not adopt it if you need a stable public API today, if you want a user-facing guide rather than a specification, or if you cannot read docs/FLOW_SPEC.md before writing your first flow.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 141 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: agent logic spread across code instead of a file
Most agent code starts as a function that calls a model, then grows a loop, then a branch, then a second model, and within a few weeks the control flow lives in Rust or Python while the prompts live somewhere else entirely. riceprompt-engine inverts that. The README states that you describe the workflow as a YAML file containing nodes, edges, prompts, data sources and MCP tools, and the engine parses it, resolves dependencies and executes the graph. The unit of review becomes a diff on a YAML file rather than a diff on imperative code.
The audience is narrow and identifiable. It is engineers building multi-step LLM pipelines who already accept YAML as a configuration surface (Kubernetes, GitHub Actions, dbt) and who want the graph itself to be portable. It is also, implicitly, anyone building a visual editor: the README says this engine powers RicePrompt, a visual agent IDE where the same YAML is produced by a graph editor and exported for the engine to consume. If you are writing a one-shot prompt call, none of this applies to you and a plain HTTP client is less machinery.
How execution works: a parsed graph, typed nodes, and a harness injected into every generate
The engine is a library, not a server. The quick start shows the shape: read the YAML into a string, construct an Engine through Engine::builder().build(), then call engine.run_yaml(&yaml, json!({ "name": "Ada" })). The second argument is the run input, and the return value is an ExecutionResult serialised with serde_json. So the data flow is: YAML string plus JSON input goes in, a structured result comes out, and your application decides what to do with it.
The graph is explicit. Nodes have an id and a type, and edges connect them with from and to. The README lists the node types: generate for model calls, transform for Rhai scripting, iterator, supervisor for multi-agent routing, subgraph, data_connector, skill_set described as progressive-disclosure knowledge bundles, and mcp or mcp_tools for Model Context Protocol. Values move between nodes by path reference, which the example makes concrete: a generate node declares variables: name: "start.name", and a response node declares output: greeting: "greet.output". That path syntax is the wiring, and it is the part most likely to break silently when you rename a node id.
Two mechanisms deserve attention because they change how you write prompts. The harness layer injects workflow-level instructions, described in the README as CLAUDE.md-style, into every generate node, with persistent memory support. That is a global prompt prefix you do not repeat per node. Separately, templates are declared once under a top-level templates key and referenced by name from a generate node, so the prompt text and the node wiring stay apart. The README also notes that ExecutionResult can include the source YAML so downstream tooling renders topology and per-node results from one file, which is a deliberate choice to make the output self-describing rather than requiring the caller to hold the original file.
Getting it running: one dependency line, one YAML file, one async call
The installation is the ordinary Cargo path. The README gives [dependencies] with riceprompt-engine = "0.1". The homepage points at crates.io/crates/riceprompt-engine, so the crate is published under that name, while the repository is jieyefriic/rp-engine. Note that mismatch when you search for issues or source; they are the same project under two names.
The minimal flow in the README has three nodes. A start node with type: start and no config. A greet node of type: generate whose config carries provider: openai, model: gpt-4o-mini, template: tpl_greet and a variables map binding name to "start.name". A response node whose config.output maps greeting to "greet.output". Two edges chain start to greet and greet to response. Under templates, tpl_greet has user_prompt: "Greet {{name}} warmly in one sentence." Providers are declared at the top level, in the example as openai with api_key: "${OPENAI_API_KEY}", which means the engine performs environment substitution on that string rather than requiring you to pass the key programmatically.
The Rust side is short: a #[tokio::main] async main, std::fs::read_to_string on the YAML, Engine::builder().build()?, then run_yaml with a serde_json::json! input. The README points to examples/ for more runnable examples, and names docs/FLOW_SPEC.md as the authoritative spec for node types, fields, providers, data sources, harness, skills and MCP. That spec is where you should start, not the README, because the README only demonstrates the smallest possible graph. The README also states that a user-facing usage guide, called a skill guide, will be published separately, which means today the specification is the documentation.
Where it will bite you: 0.1.x churn, a spec-first docs gap, and a wide provider surface
The project status section is unusually direct: 0.1.x, and the API may change between minor versions while the spec stabilises, with the recommendation to pin an exact version if you need stability. Take that literally. A caret requirement on a 0.1.x crate already constrains you to 0.1.z, but pinning to an exact version is what the README asks for, and that means every upgrade is a deliberate act with a changelog read. There are no releases retrieved in the material supplied here, so I cannot tell you how often minor versions land or what has broken between them. That is itself a reason to check the crate page before committing.
The documentation split is a real constraint. The README says the YAML spec is authoritative and that the user-facing guide will be published separately, in the future tense. Anyone who wants a tutorial rather than a grammar will be reading a specification. For a tool whose selling point is that non-Rust authors can edit the workflow, that is a gap: the people writing YAML may not be the people reading FLOW_SPEC.md.
The breadth of the surface is the other risk. The README claims multi-provider support across OpenAI, Anthropic, Gemini, DeepSeek, Qwen, Zhipu, Moonshot, MiniMax, xAI, Huoshan and any OpenAI-compatible endpoint, plus streaming, tool calling and structured output described as first-class across providers. It also lists built-in connectors for PostgreSQL, MySQL, MongoDB, Redis, Qdrant, S3-compatible storage and REST. Breadth of that kind usually means uneven depth. I cannot confirm from the supplied material which providers have parity on streaming or structured output, and the README does not say. If your workflow depends on a specific provider feature, verify it against FLOW_SPEC.md and the examples directory before you design around it. The transform node's Rhai scripting is a second place to check: Rhai is a separate language with its own semantics, and the README does not describe what the script receives or returns.
The alternative: LangGraph, and the difference is where the graph lives
The obvious comparison is LangGraph, which also models an agent as a graph of nodes and edges. The difference is where the graph is defined. In LangGraph you construct the graph in Python code: you add nodes as callables and edges as method calls, and the topology is whatever your program builds at runtime. In riceprompt-engine the topology is data. A YAML file declares nodes, edges, templates and providers, and the engine resolves dependencies and executes them.
That single difference drives the rest. A YAML graph can be diffed, reviewed and generated by a tool, which is exactly what RicePrompt does as a visual editor exporting the same YAML. A Python graph can call arbitrary code inline, which a declarative node list cannot; riceprompt-engine answers that with the transform node running Rhai, a deliberately smaller scripting language. If your workflow needs to branch on logic that only exists in your application, or to call libraries that have no node type, the declarative model is working against you. If your workflow is a pipeline of model calls, data lookups and routing decisions that you want a non-Rust colleague to read, the file is the better artefact. Choose on that axis, not on which one is more capable in the abstract.
Maintenance cost, licensing, and what dual licensing means for you
The maintenance burden has three parts. First, version pinning: the README tells you the API may change between minor versions, so budget for reading release notes at each bump rather than letting a lockfile drift. Second, spec tracking: the contributing guide requires that changes touching the YAML surface update docs/FLOW_SPEC.md in the same pull request, which is a good sign for spec discipline but also means the spec is the contract you are coding against, and it moves. Third, provider drift: upstream APIs for the listed providers change on their own schedule, and a crate that supports a dozen of them carries that maintenance whether or not you use more than one.
On licensing, the README states the project is licensed under either Apache License 2.0 or the MIT license, at your option, and that contributions are dual licensed the same way unless stated otherwise. The repository metadata supplied here lists Apache-2.0, which is one half of that pair. If you need the MIT terms, confirm the LICENSE-MIT file exists in the repository before you rely on it, because the metadata and the README do not agree on the surface. I am not giving legal advice; the practical point is that a permissive dual licence is the easy case, and the thing to check is that both licence files are present and that the crate published on crates.io carries the same terms as the repository.
Who should adopt this, and the first thing to verify
Adopt it if your agent logic is a graph you want to keep as data, if you are comfortable reading a specification to learn the node vocabulary, and if you can pin an exact 0.1.x version and treat upgrades as scheduled work. It fits teams already running Rust services, and it fits anyone building a tool that generates workflows programmatically, since the engine accepts a YAML string and returns a structured result with the source YAML optionally embedded.
Do not adopt it if you need a frozen API, if you want a tutorial before a spec, or if your workflow depends on calling arbitrary Rust or Python from inside a node in ways the listed node types do not cover. The transform node is Rhai, not Rust, and that boundary is deliberate.
The first thing to verify is concrete: open docs/FLOW_SPEC.md and confirm that every node type your workflow needs is documented there, with the fields you intend to set. The README demonstrates exactly one graph, a three-node greeting, and everything else it lists (supervisor, subgraph, skill_set, mcp_tools, the connectors, the harness layer with persistent memory, checkpoint and resume) is named but not shown. The examples/ directory is the second stop. Until those two sources cover your node types, you are reading a feature list, not an interface.
Editorial conclusion
Adopt riceprompt-engine if you want the workflow graph to live in version control as YAML and you are willing to pin an exact 0.1.x version, because the README states the API may change between minor releases. Do not adopt it if you need a stable public API today, if you want a user-facing guide rather than a specification, or if you cannot read docs/FLOW_SPEC.md before writing your first flow. Verify three things first: that the node types you need are documented in FLOW_SPEC.md, that the provider you intend to call has a working path in the crate rather than only in RicePrompt, and whether the dual Apache-2.0 / MIT licensing of the repository matches the terms you distribute under.
Community notes