Skip to main content

a3s_flow/
lib.rs

1//! # a3s-flow
2//!
3//! A3S workflow engine — JSON DAG execution for agentic workflows.
4//!
5//! ## Architecture (Minimal Core + Extensions)
6//!
7//! **Core components:**
8//! - [`FlowEngine`] — lifecycle API: start, pause, resume, terminate, query state
9//! - [`DagGraph`] — parse + validate the JSON DAG, topological sort
10//! - [`FlowRunner`] — wave-based concurrent execution engine
11//! - [`NodeRegistry`] — maps type strings to [`Node`] implementations
12//! - [`ExecContext`] — per-node runtime context (config + inputs + variables)
13//!
14//! **Extension point:** implement [`Node`] to add any node type.
15//!
16//! ## Built-in nodes (Dify-compatible)
17//!
18//! | Type string | Purpose |
19//! |-------------|---------|
20//! | `"noop"` | Pass inputs through (placeholder / fan-in join) |
21//! | `"start"` | Dify-compatible entry point with typed input declaration |
22//! | `"end"` | Dify-compatible output collector (JSON pointer paths) |
23//! | `"http-request"` | HTTP GET / POST / PUT / DELETE / PATCH |
24//! | `"if-else"` | Multi-case conditional routing → `{ "branch": "case_id" }` |
25//! | `"template-transform"` | Jinja2 string rendering |
26//! | `"variable-aggregator"` | First non-null fan-in from multiple branches |
27//! | `"code"` | Sandboxed Rhai script execution |
28//! | `"iteration"` | Concurrent or sequential sub-flow loop over an array |
29//! | `"sub-flow"` | Execute a named flow as an inline step |
30//! | `"llm"` | OpenAI-compatible chat completion with Jinja2 prompt templates |
31//! | `"question-classifier"` | LLM-powered routing into N user-defined classes |
32//! | `"assign"` | Write key-value pairs into the live flow variable scope |
33//! | `"parameter-extractor"` | LLM-powered structured parameter extraction from natural language |
34//! | `"loop"` | While-loop over inline sub-flow with break condition |
35//! | `"list-operator"` | Filter / sort / deduplicate / limit a JSON array |
36//!
37//! ## Quick start — via `FlowEngine` (recommended)
38//!
39//! ```rust,no_run
40//! use a3s_flow::{FlowEngine, NodeRegistry};
41//! use serde_json::json;
42//! use std::collections::HashMap;
43//!
44//! #[tokio::main]
45//! async fn main() -> a3s_flow::Result<()> {
46//!     let engine = FlowEngine::new(NodeRegistry::with_defaults());
47//!
48//!     let def = json!({
49//!         "nodes": [
50//!             { "id": "start",   "type": "noop" },
51//!             { "id": "process", "type": "noop" }
52//!         ],
53//!         "edges": [{ "source": "start", "target": "process" }]
54//!     });
55//!     let id = engine.start(&def, HashMap::new()).await?;
56//!
57//!     engine.pause(id).await?;
58//!     engine.resume(id).await?;
59//!     println!("{:?}", engine.state(id).await?);
60//!     Ok(())
61//! }
62//! ```
63
64pub mod condition;
65pub mod engine;
66pub mod error;
67pub mod event;
68pub mod execution;
69pub mod flow_store;
70pub mod graph;
71pub mod node;
72pub mod nodes;
73pub mod registry;
74pub mod result;
75pub mod runner;
76pub mod store;
77pub mod validation;
78
79pub use condition::{Case, CondOp, Condition, LogicalOp};
80pub use engine::FlowEngine;
81pub use error::{FlowError, Result};
82pub use event::{EventEmitter, FlowEvent, NoopEventEmitter};
83pub use execution::ExecutionState;
84pub use flow_store::{FlowStore, MemoryFlowStore};
85pub use graph::{DagGraph, EdgeDef, NodeDef};
86pub use node::{ExecContext, Node, RetryPolicy};
87pub use registry::NodeRegistry;
88pub use result::FlowResult;
89pub use runner::FlowRunner;
90pub use store::{ExecutionStore, MemoryExecutionStore};
91pub use validation::ValidationIssue;