How the TinyFlows Workflow Engine Drives OpenHuman's Visual Automation Canvas
The TinyFlows workflow engine executes user-drawn automation graphs by compiling visual canvas nodes into a runtime representation and orchestrating execution through capability adapters that bridge the engine to OpenHuman's LLM, memory, and telemetry subsystems.
OpenHuman's visual automation canvas provides a node-based interface for constructing complex workflows. At the runtime layer, the TinyFlows engine serves as the execution core that interprets these persisted graphs, orchestrating every step from initial compilation through final state persistence.
Architecture Overview: Three Integration Layers
The integration between the visual canvas and the execution engine operates through three distinct architectural layers, each defined by specific responsibilities in the OpenHuman source code.
Canvas to Graph Translation
When users draw workflows in the visual interface, the frontend serializes node positions, edge connections, and configuration data into a JSON representation. This data maps directly to the tinyflows::model::WorkflowGraph struct. In src/openhuman/flows/types.rs, OpenHuman defines wrapper types that extend the core TinyFlows graph with application-specific metadata such as workflow names, descriptions, and timestamps. The RPC controllers exposed in src/openhuman/flows/bus.rs—including openhuman.flows_import, openhuman.flows_run, and openhuman.flows_resume—handle the transfer of these graph definitions between the UI and the backend storage layer.
Engine Invocation and Compilation
The runtime entry point resides in src/openhuman/flows/tinyflows/mod.rs. When a run request arrives, the controller retrieves the stored graph and invokes tinyflows::compiler::compile to validate the node graph and produce a compiled runtime representation. The engine then executes via tinyflows::engine::run(&compiled, seed, caps), where seed represents the initial input data and caps represents the capability adapters that provide external system access.
Capability Adapter Pattern
TinyFlows expects a standard set of capabilities (LLM, HTTP, Memory, State, Tier, and ToolInvoker) that the host application must implement. OpenHuman supplies these adapters in the src/openhuman/flows/tinyflows/caps/ package:
src/openhuman/flows/tinyflows/caps/state.rsimplements theStateStorecapability, persisting step-wise execution state across asynchronous operations.src/openhuman/flows/tinyflows/caps/memory_adapter.rswires the TinyFlowsMemoryProviderinterface to OpenHuman's memory subsystem, enabling vector search and context retrieval within workflow nodes.src/openhuman/flows/tinyflows/caps/llm.rsprovides the LLM capability that forwards generation requests to OpenHuman's model provider infrastructure.
Execution Pipeline Step-by-Step
The complete execution flow follows six distinct phases that transform a visual design into operational automation.
-
Graph Construction: Users build workflows in the canvas, which serializes the graph to JSON and transmits it via the
openhuman.flows_importRPC endpoint. -
Persistence: The controller in
src/openhuman/flows/store.rspersists the WorkflowGraph alongside metadata, enabling versioned workflow storage and retrieval. -
Run Initialization: The UI issues
openhuman.flows_run(orflows_resumefor interrupted flows). The backend resolves the stored graph, compiles it usingtinyflows::compiler::compile, and constructs aCapsstruct bundling all capability adapters. -
Engine Execution:
tinyflows::engine::runtraverses the compiled graph, invoking the appropriate capability for each node type—whether LLM inference calls, HTTP requests, memory reads, or custom tool invocations. -
Observability Streaming: After each node execution, TinyFlows emits events to the RunObserver implementation defined in
src/openhuman/flows/tinyflows/observability.rs. This handler forwards step status, timestamps, and optional trace data to Langfuse or other telemetry backends. -
Result Delivery: The final output or partial execution state returns via RPC to the UI, where the canvas updates node visualizations to reflect completion status, errors, or intermediate results.
Implementation Examples
The following code demonstrates how OpenHuman invokes the TinyFlows engine from Rust and how the frontend initiates execution via RPC.
Running a Flow from the Backend
This Rust example from src/openhuman/flows/tinyflows/mod.rs demonstrates graph compilation and engine invocation:
use tinyflows::engine::{self, GraphObservation};
use tinyflows::compiler;
use tinyflows::model::WorkflowGraph;
use openhuman::flows::tinyflows::caps::{self, Capabilities};
// Retrieve stored graph JSON
let graph: WorkflowGraph = serde_json::from_str(&graph_json)?;
// Compile validates node connections and produces optimized runtime graph
let compiled = compiler::compile(&graph).expect("invalid workflow");
// Initialize capabilities bridging to OpenHuman subsystems
let caps = caps::Capabilities::new(/* LLM, HTTP, Memory, State, etc. */);
// Execute with seed input
let outcome = engine::run(&compiled, json!({ "seed": 1 }), &caps);
match outcome {
Ok(run) => println!("Flow succeeded: {:?}", run.state()),
Err(e) => eprintln!("Execution failed: {}", e),
}
Initiating Execution from the Frontend
The React frontend communicates with the engine through the RPC bridge defined in src/openhuman/flows/bus.rs:
import { coreRpcClient } from '@/services/coreRpcClient';
// Trigger workflow execution
await coreRpcClient.call('openhuman.flows_run', {
workflow_id: 'abc123',
input: { seed: 1, query: "analyze sentiment" },
});
// Subscribe to real-time execution events
coreRpcClient.on('flows.run', (event) => {
updateCanvasNode(event.node_id, event.status, event.output);
});
Summary
- The TinyFlows workflow engine serves as the runtime interpreter for OpenHuman's visual automation canvas, executing compiled graphs through capability adapters.
- WorkflowGraph definitions transit from UI to storage via RPC endpoints in
src/openhuman/flows/bus.rs, with persistence handled bysrc/openhuman/flows/store.rs. - The engine requires six capability implementations—LLM, HTTP, Memory, State, Tier, and ToolInvoker—provided in
src/openhuman/flows/tinyflows/caps/to interface with OpenHuman infrastructure. - RunObserver events in
src/openhuman/flows/tinyflows/observability.rsenable real-time telemetry streaming to external monitoring systems. - Execution flows through compilation (
tinyflows::compiler::compile), runtime invocation (tinyflows::engine::run), and RPC result delivery back to the visual canvas.
Frequently Asked Questions
What is the TinyFlows workflow engine?
TinyFlows is a Rust-based workflow execution engine that interprets node-based automation graphs. It operates independently of the visual interface, expecting only a compiled graph and a set of capability adapters to execute business logic, making it suitable for embedding in applications like OpenHuman that require robust, observable automation backends.
How does OpenHuman persist workflow graphs created in the visual canvas?
OpenHuman persists workflows through the openhuman.flows_import RPC endpoint, which stores the graph definition in src/openhuman/flows/store.rs. The storage layer maintains the JSON representation of the tinyflows::model::WorkflowGraph alongside metadata such as creation timestamps and workflow descriptions, enabling versioned retrieval when runs are initiated.
What capabilities must the host application provide to TinyFlows?
TinyFlows requires six capability interfaces: StateStore for persistence across steps, MemoryProvider for context retrieval, LLM for model inference, HTTP for external requests, Tier for execution environment management, and ToolInvoker for custom tool execution. OpenHuman implements these in the src/openhuman/flows/tinyflows/caps/ directory, bridging the engine to the host's existing subsystems.
How is execution telemetry handled during workflow runs?
During execution, TinyFlows emits step-level events to the RunObserver trait implemented in src/openhuman/flows/tinyflows/observability.rs. This implementation captures node execution status, timing data, and outputs, forwarding the telemetry to Langfuse or other observability platforms, providing full traceability of automation execution from the visual canvas through to completion.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →