# Hybrid Engine

::alert
For a brief overview of the concept of combining Dataflow and Control flow, we recommend reading the [Hybrid](https://retejs.org/docs/concepts/engine#hybrid) article
::

::references
  :::ref-example{link="/examples/processing/hybrid-engine" title="Hybrid engine"}
  :::

  :::ref-example{link="/examples/chatbot" title="Chatbot"}
  :::

  :::ref-github{link="https://github.com/retejs/engine" title="Plugin"}
  :::

  :::ref-guide{link="/docs/guides/processing/dataflow" title="Dataflow"}
  :::

  :::ref-guide{link="/docs/guides/processing/control-flow" title="Control flow"}
  :::
::

## Install dependencies

::kit
::

```bash
npm i rete rete-engine
```

## Prepare nodes

In order to work properly, all node classes must implement `execute` method for Control flow and `data` method for Dataflow.

The `Start` class is designed to pass control and has a default `data` method that returns an empty object.

```ts
const socket = new ClassicPreset.Socket("socket");

class Start extends ClassicPreset.Node {
  constructor() {
    super("Start");
    this.addOutput("exec", new ClassicPreset.Output(socket, "Exec"));
  }

  execute(_: never, forward: (output: "exec") => void) {
    forward("exec");
  }

  data() {
    return {};
  }
}
```

Along with receiving control, the `Log` class can also request data from the incoming nodes through the `message` port using the `fetchInputs` method of the `DataflowEngine` instance.

```ts
class Log extends ClassicPreset.Node {
  constructor() {
    super("Log");

    this.addInput("exec", new ClassicPreset.Input(socket, "Exec", true));
    this.addInput("message", new ClassicPreset.Input(socket, "Text"));
    this.addOutput("exec", new ClassicPreset.Output(socket, "Exec"));
  }

  async execute(input: "exec", forward: (output: "exec") => void) {
    const inputs = (await dataflow.fetchInputs(this.id)) as {
      message: string[];
    };

    console.log((inputs.message && inputs.message[0]) || "");

    forward("exec");
  }

  data() {
    return {};
  }
}
```

The `TextNode` class is responsible only for providing data and cannot receive or pass control.

```ts
class TextNode extends ClassicPreset.Node {
  constructor(private text: string) {
    super("Text");
    this.addOutput("value", new ClassicPreset.Output(socket, "Number"));
  }

  execute() {}

  data(): { value: string } {
    return {
      value: this.text
    };
  }
}

class Connection<A extends NodeProps, B extends NodeProps> extends ClassicPreset.Connection<A, B> {}

type NodeProps = Start | Log | TextNode;
type ConnProps = Connection<Start, Log> | Connection<TextNode, Log>;
type Schemes = GetSchemes<NodeProps, ConnProps>;

```

## Connect

```ts
import { NodeEditor } from "rete";
import { DataflowEngine, ControlFlowEngine } from "rete-engine";

const editor = new NodeEditor<Schemes>();
const dataflow = new DataflowEngine<Schemes>(({ inputs, outputs }) => {
  return {
    inputs: () => Object.keys(inputs).filter((name) => name !== "exec"),
    outputs: () => Object.keys(outputs).filter((name) => name !== "exec")
  };
});
const controlflow = new ControlFlowEngine<Schemes>(() => {
  return {
    inputs: () => ["exec"],
    outputs: () => ["exec"]
  };
});

editor.use(dataflow);
editor.use(controlflow);
```

## Add nodes and connections

```ts
const start = new Start();
const text1 = new TextNode("log");
const log1 = new Log();

const con1 = new Connection(start, "exec", log1, "exec");
const con2 = new Connection(text1, "value", log1, "message");

await editor.addNode(start);
await editor.addNode(text1);
await editor.addNode(log1);

await editor.addConnection(con1);
await editor.addConnection(con2);
```

## Execution

The node `start` serves as the starting point for the graph execution.

```ts
engine.execute(start.id);
```

As a result, the `start` node passes control to the `log1` node, which fetches data from the `text1` node using the `fetchInputs` method.

Check out the complete result on the [Hybrid engine](https://retejs.org/examples/processing/hybrid-engine) example page. Additionally, you can explore another more sophisticated [Chatbot](https://retejs.org/examples/chatbot) example employing this approach.