The `Multiplexer` can be used stand-alone. This way a developer can utilise the protocols and connections indendent of the `Agent` or `AEA` classes.

First, import the python and application specific libraries and set the static variables.
``` python
import os
import time
from copy import copy
from threading import Thread
from typing import Optional

from aea.connections.stub.connection import StubConnection
from aea.mail.base import Envelope, Multiplexer

INPUT_FILE = "input.txt"
OUTPUT_FILE = "output.txt"
```

## Instantiate a `Multiplexer`

A `Multiplexer` only needs a list of connections. The `StubConnection` is a simple connection which reads from and writes to file.

``` python
    # Ensure the input and output files do not exist initially
    if os.path.isfile(INPUT_FILE):
        os.remove(INPUT_FILE)
    if os.path.isfile(OUTPUT_FILE):
        os.remove(OUTPUT_FILE)

    # create the connection and multiplexer objects
    stub_connection = StubConnection(
        input_file_path=INPUT_FILE, output_file_path=OUTPUT_FILE
    )
    multiplexer = Multiplexer([stub_connection])
```

## Start the `Multiplexer`

We can run a multiplexer by calling, `connect()` which starts the receive and sending loops. We run the multiplexer from a different thread so that we can still use the main thread to pass it messages.

``` python
    try:
        # Set the multiplexer running in a different thread
        t = Thread(target=multiplexer.connect)
        t.start()

        # Wait for everything to start up
        time.sleep(3)
```

## Send and receive an envelope
We use the input and output text files to send an envelope to our agent and receive a response
``` python
        # Create a message inside an envelope and get the stub connection to pass it into the multiplexer
        message_text = (
            "multiplexer,some_agent,fetchai/default:0.1.0,\x08\x01*\x07\n\x05hello"
        )
        with open(INPUT_FILE, "w") as f:
            f.write(message_text)

        # Wait for the envelope to get processed
        time.sleep(2)

        # get the envelope
        envelope = multiplexer.get()  # type: Optional[Envelope]
        assert envelope is not None

        # Inspect its contents
        print(
            "Envelope received by Multiplexer: sender={}, to={}, protocol_id={}, message={}".format(
                envelope.sender, envelope.to, envelope.protocol_id, envelope.message
            )
        )

        # Create a mirrored response envelope
        response_envelope = copy(envelope)
        response_envelope.to = envelope.sender
        response_envelope.sender = envelope.to

        # Send the envelope back
        multiplexer.put(response_envelope)

        # Read the output envelope generated by the multiplexer
        with open(OUTPUT_FILE, "r") as f:
            print("Envelope received from Multiplexer: " + f.readline())
```

## Shutdown
Finally stop our multiplexer and wait for it to finish
``` python
    finally:
        # Shut down the multiplexer
        multiplexer.disconnect()
        t.join()
```

## Your turn

Now it is your turn to develop a simple usecase which utilises the `Multiplexer` to send and receive Envelopes.

## Entire code listing
If you just want to copy and paste the entire script in you can find it here:

<details><summary>Click here to see full listing</summary>
<p>

``` python
import os
import time
from copy import copy
from threading import Thread
from typing import Optional

from aea.connections.stub.connection import StubConnection
from aea.mail.base import Envelope, Multiplexer

INPUT_FILE = "input.txt"
OUTPUT_FILE = "output.txt"


def run():
    # Ensure the input and output files do not exist initially
    if os.path.isfile(INPUT_FILE):
        os.remove(INPUT_FILE)
    if os.path.isfile(OUTPUT_FILE):
        os.remove(OUTPUT_FILE)

    # create the connection and multiplexer objects
    stub_connection = StubConnection(
        input_file_path=INPUT_FILE, output_file_path=OUTPUT_FILE
    )
    multiplexer = Multiplexer([stub_connection])
    try:
        # Set the multiplexer running in a different thread
        t = Thread(target=multiplexer.connect)
        t.start()

        # Wait for everything to start up
        time.sleep(3)

        # Create a message inside an envelope and get the stub connection to pass it into the multiplexer
        message_text = (
            "multiplexer,some_agent,fetchai/default:0.1.0,\x08\x01*\x07\n\x05hello"
        )
        with open(INPUT_FILE, "w") as f:
            f.write(message_text)

        # Wait for the envelope to get processed
        time.sleep(2)

        # get the envelope
        envelope = multiplexer.get()  # type: Optional[Envelope]
        assert envelope is not None

        # Inspect its contents
        print(
            "Envelope received by Multiplexer: sender={}, to={}, protocol_id={}, message={}".format(
                envelope.sender, envelope.to, envelope.protocol_id, envelope.message
            )
        )

        # Create a mirrored response envelope
        response_envelope = copy(envelope)
        response_envelope.to = envelope.sender
        response_envelope.sender = envelope.to

        # Send the envelope back
        multiplexer.put(response_envelope)

        # Read the output envelope generated by the multiplexer
        with open(OUTPUT_FILE, "r") as f:
            print("Envelope received from Multiplexer: " + f.readline())
    finally:
        # Shut down the multiplexer
        multiplexer.disconnect()
        t.join()


if __name__ == "__main__":
    run()
```

<br />
