# How the TinyFlows Workflow Engine Integrates with the OpenHuman Orchestrator

> Learn how the TinyFlows workflow engine integrates with OpenHuman as an optional domain family, enabling RPC controllers and agent tools for graph-based workflow invocation via standard tool dispatch.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: how-to-guide
- Published: 2026-08-28

---

**The TinyFlows workflow engine integrates with the OpenHuman orchestrator as an optional domain family that registers RPC controllers and agent tools, enabling the orchestrator to invoke graph-based workflows through standard tool dispatch mechanisms.**

The TinyFlows engine provides comprehensive workflow orchestration to the OpenHuman agent runtime. In the `tinyhumansai/openhuman` repository, this integration operates through a modular domain system where the engine registers its controllers and tools with the core orchestrator, allowing AI agents to execute complex multi-step workflows defined in YAML or JSON.

## Integration Architecture

### Domain Registration

The integration begins at startup when the **Flows** domain group conditionally registers its components. In [`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs), the orchestrator pushes TinyFlows controllers into the global dispatcher **only when the `flows` feature flag is enabled**. This registration exposes RPC endpoints such as `run_workflow` and `await_workflow` through the `DomainGroup::Flows` implementation.

When constructing a `DomainSet::full()` instance, the orchestrator automatically includes the Flow namespace, making the workflow engine available to agent harnesses. This modular approach allows minimal builds to exclude the entire workflow system by disabling the feature flag during compilation.

### Tool Registration

Beyond RPC controllers, TinyFlows exposes its functionality through agent tools defined in [`src/openhuman/tools/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/ops.rs). The `all_tinyflows_agent_tools()` function generates tool entries prefixed with `tinyflows_*` that wrap individual workflow nodes including conditions, loops, and sub-flows.

During turn execution, when a language model requests to run a workflow, the orchestrator's tool-dispatch system (`tinyagents::harness::tool_calling`) resolves these `tinyflows_*` tool calls. The dispatcher validates requests against the tool schema before invoking the TinyFlows executor, treating workflow execution identically to standard tool calls like `http_request` or `shell`.

### Execution Runtime

At the core of the integration, [`src/openhuman/flows/tinyflows/engine.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/flows/tinyflows/engine.rs) parses workflow definitions into an internal abstract syntax tree representing a directed acyclic graph (DAG). The executor walks this graph, invoking dependent tools through the core's tool dispatcher while respecting the dependency chain defined in the workflow file.

The orchestrator monitors workflow execution through the **FlowTriggerSubscriber** registered in [`src/core/jsonrpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc.rs). This subscriber listens for flow-related events on the global event bus, allowing the runtime to re-hydrate paused workflows and stream execution results back into the turn transcript.

## Implementation Examples

### Initializing the Harness with TinyFlows Support

```rust
use openhuman_core::Harness;
use openhuman_core::provider::Provider;

// Build a harness that includes the Flow domain
let harness = Harness::builder()
    .provider(Provider::openai_compatible(
        "https://api.openai.com/v1".into(), 
        "MYKEY".into()
    ).model("gpt-4o-mini"))
    .domains(openhuman_core::core::runtime::DomainSet::full())
    .access(openhuman_core::access::Access::full())
    .build()
    .await?;

// Execute a prompt that triggers workflow execution
let result = harness
    .run("Run the workflow `my_flow.yaml`.")
    .await?;

println!("Workflow finished: {:?}", result);

```

This example from [`src/openhuman/agent/harness.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/agent/harness.rs) demonstrates how the `DomainSet::full()` configuration automatically loads the TinyFlows domain, exposing workflow tools to the agent.

### Defining a TinyFlows Workflow

```yaml

# my_flow.yaml

name: "Demo workflow"
steps:
  - id: fetch
    type: http_request
    args:
      method: GET
      url: https://api.example.com/data
  - id: process
    type: shell
    args:
      cmd: "jq .value"
    depends_on: [fetch]
  - id: reply
    type: reply
    args:
      message: "The value is {{process.stdout}}"
    depends_on: [process]

```

The engine in [`src/openhuman/flows/tinyflows/engine.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/flows/tinyflows/engine.rs) processes this YAML into a DAG where each step becomes a `tinyflows::engine::Node`. The executor handles dependency resolution, ensuring `fetch` completes before `process` begins, while [`src/openhuman/flows/tinyflows/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/flows/tinyflows/mod.rs) serves as the public entry point re-exporting these internal components.

### Subscribing to Flow Events

```rust
use openhuman_core::core::event_bus::{DomainEvent, EventBus};

// Register the Flow trigger subscriber at start-up
EventBus::global().subscribe_global(
    "flows.trigger",
    |event: DomainEvent| {
        if let DomainEvent::FlowTriggered { flow_id, .. } = event {
            tracing::info!("Flow {} triggered", flow_id);
        }
    },
);

```

This pattern from [`src/core/jsonrpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc.rs) shows how the orchestrator tracks workflow lifecycle events through the `FlowTriggerSubscriber`, enabling observability and conditional logic based on workflow state changes.

## Summary

- The TinyFlows engine integrates as a **conditional domain family** activated via the `flows` feature flag in [`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs).
- Tool registration occurs through `all_tinyflows_agent_tools()` in [`src/openhuman/tools/ops.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/tools/ops.rs), exposing workflow capabilities as standard agent tools.
- The execution engine in [`src/openhuman/flows/tinyflows/engine.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/flows/tinyflows/engine.rs) parses YAML/JSON workflows into DAGs and orchestrates step execution through the core tool dispatcher.
- Event-driven monitoring via `FlowTriggerSubscriber` in [`src/core/jsonrpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc.rs) allows the orchestrator to track and manage long-running workflow instances.

## Frequently Asked Questions

### How do I enable TinyFlows support in a minimal OpenHuman build?

Enable the `flows` feature flag when compiling the core crate. In [`src/core/all.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/all.rs), the Flow controllers are conditionally compiled using `#[cfg(feature = "flows")]`, ensuring the workflow engine only loads when explicitly requested. Without this flag, the `DomainSet::full()` method will exclude TinyFlows controllers and tools from the runtime.

### Can TinyFlows workflows invoke other agent tools?

Yes. The workflow engine delegates step execution to the orchestrator's standard tool dispatcher. When a workflow step specifies `type: http_request`, `type: shell`, or custom skill types, the TinyFlows executor in [`src/openhuman/flows/tinyflows/engine.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/flows/tinyflows/engine.rs) invokes these through the same interface used by direct agent tool calls, maintaining consistent sandbox and permission checks.

### What file formats does the TinyFlows engine support?

The engine accepts both YAML and JSON workflow definitions. The parser in [`src/openhuman/flows/tinyflows/engine.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/flows/tinyflows/engine.rs) deserializes these into an internal AST representation (`tinyflows::engine::Workflow`), constructing a dependency graph that respects the `depends_on` relationships defined between steps.

### How does the orchestrator handle asynchronous workflow execution?

The orchestrator treats workflow execution as an asynchronous tool call. The `FlowTriggerSubscriber` in [`src/core/jsonrpc.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/core/jsonrpc.rs) monitors the event bus for `FlowTriggered` events, allowing the system to manage paused workflows and stream partial results back to the agent transcript without blocking the main execution thread.