Model or dataset
a-agmon/rs-graph-llm avatar
a-agmon/rs-graph-llm

graph-flow: stateful agent workflows in Rust, with a LangGraph-style graph engine

High-performance framework for building interactive workflow systems in Rust. Designed for complex workflows and multi-agent systems

374 stars41 forksRustMIT

At a glance

What is it?
graph-flow is a Rust crate for building resumable, type-safe agent workflows on top of a task graph, with optional Rig integration for LLM calls. It is a good fit when you want step-by-step control and session persistence, and the wrong tool when you want a batteries-included agent runtime.
Who is it for?
Adopt graph-flow if you are building a Rust service that needs explicit control over when each workflow step runs, with sessions that survive a process restart. Do not adopt it if you expect the crate to give you an agent loop, tool calling or provider clients out of the box; the README points at rig-agent for that, and the two are separate dependencies.
Can I use it commercially?
Yes. MIT 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 11 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 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What graph-flow solves, and for whom

An LLM workflow that spans several steps has a state problem before it has a model problem. The first step reads a document, the second classifies it, the third asks a human to approve, and the fourth writes a result. If any of those steps fails, or the process restarts while a user is deciding, the state has to live somewhere that outlives the call stack.

graph-flow is a Rust crate that puts that state in a session and the steps in a directed graph. Tasks implement the Task trait, read and write shared state through Context, and return a NextAction that tells the engine where control goes next. The README describes the crate as "a type-safe, LangGraph-inspired framework for building complex, interactive, resumable agent workflows", and the repository layout backs this up: graph-flow/ is the published library, while insurance-claims-service/, recommendation-service/ and medical-document-service/ are worked examples of the pattern in production shape.

The audience is narrower than the description suggests. This is for Rust engineers who already know they want a graph, and who are comfortable wiring persistence and LLM calls themselves. If you have not decided on a language, the crate will not make that decision for you.

How the graph engine and sessions fit together

The mechanism is a load, execute one step, save cycle. FlowRunner::new takes a graph and a session storage, and runner.run(session_id) performs that cycle for you. The lower-level equivalent is three calls: storage.get, graph.execute_session, storage.save. The README states that this lower-level path "is exactly what FlowRunner does internally", which matters because it means you can replace the runner's persistence decisions without forking the crate.

Execution control is expressed through NextAction, and the choice is the interesting part of the design. Continue advances one edge and returns control to the caller, so a web handler can respond between steps. ContinueAndExecute keeps running tasks in the same call until something pauses. WaitForInput stops at the current task. GoTo jumps to a named task, and End completes the workflow. The README explicitly allows blending these in one graph, so an automated chain can end in an interactive pause without splitting the workflow into two systems.

Storage is pluggable. InMemorySessionStorage is the example implementation, and the postgres feature, which is enabled by default, provides PostgresSessionStorage with its SQLx dependency. The README notes you can set default-features = false to exclude it. The rig feature is separate and only bridges Context chat history to rig-core's Message type; the README is direct that "the agent runtime itself lives in the companion rig-agent crate". That separation is the single most important thing to understand before adopting this.

Installing graph-flow and running a first workflow

The crate is published on crates.io and documented on docs.rs, both linked from the README badge block. The README's dependency snippet pins version 0.8 and pulls in the rig feature, rig-core 0.42 and rig-agent 0.42. Drop the rig feature if you do not need the LLM helpers.

toml
[dependencies]
graph-flow = { version = "0.8", features = ["rig"] }
rig-core = "0.42"
rig-agent = "0.42"

A task is any type implementing Task with an async run method. It reads from Context with get, writes with set, and returns a TaskResult carrying an optional response and a NextAction. The id method defaults to the type name, which the README says you override only when you want a custom identifier.

rust
use async_trait::async_trait;
use graph_flow::{Context, NextAction, Task, TaskResult};

struct HelloTask;

#[async_trait]
impl Task for HelloTask {
    async fn run(&self, context: Context) -> graph_flow::Result<TaskResult> {
        let name: String = context.get("name").unwrap_or_default();
        let greeting = format!("Hello, {name}");
        context.set("greeting", greeting.clone())?;
        Ok(TaskResult::new(Some(greeting), NextAction::Continue))
    }
}

GraphBuilder collects the tasks and edges, and build validates the edges and the start task, returning a Result rather than panicking. From there you create a Session positioned at the first task, save it, and drive it with FlowRunner. The README's loop matches on ExecutionStatus: Completed breaks, Paused continues, and WaitingForInput breaks so you can collect user input, set it in the context, and run again. The repository's examples/ directory contains simple_example.rs, complex_example.rs, recommendation_flow.rs, fanout_basic.rs and terminal_client.rs, and the README says to start with simple_example.rs. Run it from the workspace with cargo run -p examples --bin simple_example if the binary names match the file names, and check examples/Cargo.toml first, because the README does not list the binary targets.

Where graph-flow stops and rig-agent begins

The most common misreading of this project is to treat it as an agent framework. It is a workflow engine with an LLM-shaped hole. The rig feature converts Context chat history into rig-core Message values, and that is the whole of the integration described in the README. Chat, Prompt and the .agent() constructor belong to rig-agent, a separate crate at the same 0.42 version line.

That split has consequences. You can build a graph-flow workflow that never calls a model at all, which is useful for approval chains and document pipelines. You can also swap the model layer without touching the graph, because the graph only sees Context and TaskResult. The cost is that you own the glue: retries around model calls, token accounting, and whatever error mapping you want between provider errors and your task results are not the crate's concern.

The README does not describe a tool-calling abstraction, a streaming interface, or a built-in agent loop. If your workflow is one prompt with a few tools, graph-flow adds a graph, a session store and a runner you do not need.

The Postgres default and what it costs you

The postgres feature is on by default, which means a plain graph-flow dependency pulls SQLx with the postgres, json, macros and uuid features. If you only want in-memory sessions, that is dead weight in your build, and the README gives the fix: default-features = false.

The more consequential point is that the README does not document session schema migrations, versioning of stored sessions, or rollback when a graph changes shape. A session records a position in a graph. Rename a task id or remove an edge, and sessions saved under the old graph have nowhere to resume. The README is silent on this, and it is the failure mode worth designing around before you persist anything: either keep task ids stable, or version graphs and treat old sessions as expired.

The worked services in the repository suggest the intended scale. insurance-claims-service is described as a production-style HTTP service with LLM-driven claim intake, conditional routing and human-in-the-loop approval, built on axum and tower-http. That is a real shape for the crate, but it is also a service you assemble, not one the crate hands you.

graph-flow against LangGraph and Swarms-rs

The README names its own reference point: graph-flow takes the two ideas that make LangGraph pleasant, a graph execution engine and LLM ecosystem integration, and rebuilds them in Rust. The difference in approach is not the graph model, which is deliberately similar, but where the state lives and what type system enforces it. LangGraph is Python, so a workflow's state is a dictionary or a typed state object checked at runtime; graph-flow's Context is read and written through typed get and set calls, and a Task that returns the wrong NextAction is a compile error rather than a runtime branch.

Swarms-rs is the other name that comes up in searches around this project. It is a Rust multi-agent framework, which is a different organising idea: agents that coordinate, rather than tasks on a graph with an explicit position. If your problem is genuinely a fixed sequence with branches and a human checkpoint, the graph is the simpler model and the session gives you resume for free. If your problem is agents deciding what to do next, a graph engine will feel like you are encoding a conversation as a state machine.

Rig is not an alternative here so much as the other half. The README treats graph-flow and Rig as complementary crates, and the version numbers in the workspace Cargo.toml line them up at 0.42.0.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-09-07, which is recent. The README lists no release notes and no retrieved releases, so version history has to be read from crates.io rather than from a changelog in the repository. The workspace pins rig-core and rig-agent at 0.42.0 and graph-flow is documented at 0.8, so the two version lines move independently and an upgrade on one side does not imply the other.

The practical upgrade cost sits in two places. First, task ids and graph shape are effectively part of your persisted data, per the schema point above. Second, the postgres feature ties you to SQLx 0.8.6 and its feature set in the workspace manifest; a SQLx major bump is a graph-flow bump. The rig feature is the cheapest to drop, since it only affects message conversion.

The licence is MIT, which is permissive and imposes no source-disclosure obligation on your own code. That is the extent of what can be said from the repository; the LICENSE file is the authority, and if you redistribute the crate or bundle it into a product, read it rather than this paragraph.

Editorial conclusion

Adopt graph-flow if you are building a Rust service that needs explicit control over when each workflow step runs, with sessions that survive a process restart. Do not adopt it if you expect the crate to give you an agent loop, tool calling or provider clients out of the box; the README points at rig-agent for that, and the two are separate dependencies. Before committing, read examples/simple_example.rs for the core concepts, then check whether PostgresSessionStorage matches the database you already run, because the postgres feature is on by default and the README does not document a rollback path for session schema changes.

Frequently asked questions

What is GraphFlow?

GraphFlow is the name used for graph-flow, a Rust crate for building stateful agent workflows as a graph of tasks. Tasks implement the Task trait, share state through Context, and return a NextAction that decides whether the workflow continues, pauses for input, jumps to another task or ends.

What is a graph in AI?

In this project a graph is a set of tasks connected by edges, built with GraphBuilder, where build validates the edges and the start task. Execution moves along those edges under the control of each task's NextAction, and the current position is stored in a session so the workflow can resume later.

Does graph-flow include an agent runtime or LLM provider clients?

No. The README states that the agent runtime lives in the companion rig-agent crate, and the optional rig feature only bridges Context chat history to rig-core's Message type. You add rig-core and rig-agent as separate dependencies when you need model calls.

Do I need PostgreSQL to use graph-flow?

No, but the postgres feature is enabled by default and brings in PostgresSessionStorage with its SQLx dependency. The README says to set default-features = false to exclude it, and InMemorySessionStorage is used in the quick start example.

Where should I start reading the graph-flow examples?

The README says to read examples/simple_example.rs for the core concepts, then the services in the repository for real-world patterns. The examples directory also contains complex_example.rs, recommendation_flow.rs, fanout_basic.rs and terminal_client.rs.

Official sources

  1. a-agmon/rs-graph-llm on GitHub
  2. Issues
  3. License: MIT
  4. README
Community notes

Community notes