How the TinyFlows Engine Integrates with the Workflow Domain in OpenHuman
The TinyFlows engine integrates with OpenHuman's workflow domain through a layered architecture that separates RPC schema validation, core orchestration logic, and execution runtime, connected via capability traits (caps) that supply LLM prompting, HTTP requests, and agent tools.
The OpenHuman repository implements a robust workflow automation system where the TinyFlows execution engine serves as the runtime core. This integration allows the workflow domain to handle high-level concerns like persistence and RPC interfaces while delegating graph interpretation to a specialized Rust engine. Understanding this architecture reveals how the system maintains clean separation between domain orchestration and execution semantics.
Domain Structure and Entry Points
The workflow domain resides under src/openhuman/flows/ and serves as the primary interface for flow management. This directory encapsulates the public API, core operations, and the TinyFlows engine integration.
The domain exposes JSON-RPC endpoints defined in src/openhuman/flows/schemas.rs, which validate incoming requests before forwarding them to operation handlers. These controllers handle methods like openhuman.flows_run and openhuman.flows_create, providing the external interface for workflow interaction.
Core business logic lives in src/openhuman/flows/ops.rs, which implements functions such as handle_create_flow and handle_run_flow. These operations construct an EngineContext that bridges the domain layer with the execution engine, ensuring that the TinyFlows runtime receives properly validated inputs and necessary host dependencies.
The TinyFlows Execution Engine
The actual execution logic resides in src/openhuman/flows/tinyflows/mod.rs, which exports the TinyFlowsEngine type and the run_flow entry point. Unlike the domain layer, which manages drafts and runs through database operations, the engine focuses purely on interpreting stored automation graphs.
When ops.rs invokes the engine, it passes an EngineContext containing references to the TinyFlowsEngine instance. The engine then reads the flow graph from the draft store and executes it turn-by-turn, resolving each node according to the graph's definition. This design keeps execution semantics isolated from persistence concerns, allowing the engine to operate as a pure Rust library without runtime overhead.
Capability Bridge (Caps)
Integration between the engine and host services occurs through the caps layer located in src/openhuman/flows/tinyflows/caps/. Each capability implements a trait that the engine calls during execution, enabling the workflow domain to inject host-specific behavior without modifying engine code.
The four primary capabilities include:
- PromptCap (
src/openhuman/flows/tinyflows/caps/prompt.rs): Constructs LLM prompts based on the flow's current state, allowing the engine to generate context-aware AI requests. - HttpCap (
src/openhuman/flows/tinyflows/caps/http.rs): Performs outbound HTTP requests defined in flow nodes, handling external API integrations. - CodeCap (
src/openhuman/flows/tinyflows/caps/code.rs): Executes sandboxed scripts as part of flow progression, enabling dynamic computation steps. - AgentCap (
src/openhuman/flows/tinyflows/caps/agent.rs): Invokes OpenHuman agent tools such asrun_workflowandawait_workflow, facilitating complex multi-agent orchestration.
Because these capabilities are supplied as trait objects, the host can swap implementations—for example, switching LLM providers or sandbox environments—without changing the core TinyFlows engine.
Observability and Persistence Integration
The workflow domain tracks execution progress through dedicated observability and persistence adapters. During runtime, the engine emits FlowProgressEvent structures defined in src/openhuman/flows/tinyflows/observability.rs, which the domain publishes to the core event bus. UI components subscribe to this bus to receive live execution updates.
State management flows through src/openhuman/flows/tinyflows/memory_adapter.rs, which implements the FlowMemory trait used by the engine. This adapter stores flow state, checkpoints, and draft revisions, allowing the execution to resume from interruptions or maintain history for debugging purposes.
Execution Flow: From RPC to Runtime
When a client invokes the openhuman.flows_run method via JSON-RPC, the integration follows a precise sequence:
- Schema validation occurs in
src/openhuman/flows/schemas.rs, ensuring the request contains validdraft_idand input parameters. - Operation handling in
src/openhuman/flows/ops.rscreates anEngineContextand retrieves the stored flow definition. - Engine initialization loads the graph into
TinyFlowsEnginefromsrc/openhuman/flows/tinyflows/mod.rs. - Node resolution proceeds iteratively, with the engine calling
caps::agentto invoke tools andcaps::promptto generate AI contexts. - Side-effect execution happens through
caps::httpandcaps::codefor external calls and computation. - Progress emission sends events through
src/openhuman/flows/tinyflows/observability.rsto update listening clients.
Practical Implementation Examples
To execute a flow programmatically from within the Rust codebase:
use openhuman_core::flows::tinyflows::{EngineContext, TinyFlowsEngine};
use openhuman_core::flows::ops::run_flow;
// Initialize the engine with default capabilities
let engine = TinyFlowsEngine::default();
// Construct context with database and service references
let ctx = EngineContext::new(&engine, /* DB, RPC client */);
// Execute the stored draft
let result = run_flow(&ctx, "draft-12345".into()).await?;
println!("Flow output: {:?}", result);
Client applications can trigger flows through the JSON-RPC interface:
// Using the OpenHuman JavaScript client
const result = await coreRpcClient.call(
"openhuman.flows_run",
{ draft_id: "draft-12345", input: {} }
);
console.log("Execution completed", result);
Summary
- The workflow domain in
src/openhuman/flows/provides RPC schema definitions inschemas.rsand operation handlers inops.rsthat serve as the primary integration surface. TinyFlowsEnginefromsrc/openhuman/flows/tinyflows/mod.rshandles pure graph execution without domain concerns, accepting anEngineContextfor initialization.- Capability traits in
src/openhuman/flows/tinyflows/caps/supply the engine with LLM prompting, HTTP requests, code execution, and agent tool invocation. src/openhuman/flows/tinyflows/observability.rsandmemory_adapter.rshandle event emission and state persistence, connecting execution progress to UI components and storage systems.- This layered approach allows the TinyFlows engine to remain host-agnostic while the workflow domain manages lifecycle, persistence, and external interfaces.
Frequently Asked Questions
What role do the capability traits (caps) play in the TinyFlows integration?
The caps layer acts as a dependency injection mechanism that supplies the TinyFlows engine with host-specific behaviors. By implementing traits like PromptCap, HttpCap, CodeCap, and AgentCap in src/openhuman/flows/tinyflows/caps/, the workflow domain determines how the engine performs LLM calls, network requests, and code execution without the engine needing to know implementation details. This decoupling allows the same engine to run in different environments—development, production, or testing—simply by swapping capability implementations.
How does the workflow domain persist flow execution state?
State persistence occurs through the FlowMemory trait implemented in src/openhuman/flows/tinyflows/memory_adapter.rs. When the engine reaches checkpoints or completes steps, it calls methods on this trait to save current state, variables, and execution progress. The domain provides the concrete implementation backed by the core database, enabling features like resuming interrupted flows or auditing historical runs while keeping the engine itself stateless.
Can TinyFlows operate independently of the OpenHuman RPC layer?
Yes, the TinyFlows engine functions as a pure Rust library that requires only an EngineContext and capability implementations to run. While src/openhuman/flows/schemas.rs and ops.rs provide the JSON-RPC interface used by external clients, internal code can invoke run_flow directly from src/openhuman/flows/ops.rs or instantiate TinyFlowsEngine manually. This flexibility supports background job processors, embedded automation, or testing environments that bypass the RPC stack entirely.
How does the integration support real-time UI updates during flow execution?
The observability layer in src/openhuman/flows/tinyflows/observability.rs defines FlowProgressEvent structures that the engine emits at each execution step. These events propagate to the core event bus, which UI clients subscribe to via WebSocket or Server-Sent Events connections. Because the engine publishes these updates synchronously during graph traversal, interfaces can display live node activation, variable changes, and completion status without polling the database.
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 →