Preliminaries

These instructions detail the Python code you need for running an AEA outside the cli tool, using the code interface.

This guide assumes you have already followed the Preliminaries and Installation section in the quick start guide and so have the framework installed and the packages and scripts directory downloaded into the directory you are working in.

Imports

First, import the necessary common Python libraries and classes.

import os
import time
from threading import Thread

Then, import the application specific libraries.

from aea import AEA_DIR
from aea.aea import AEA
from aea.connections.stub.connection import StubConnection
from aea.crypto.fetchai import FETCHAI
from aea.crypto.helpers import FETCHAI_PRIVATE_KEY_FILE, _create_fetchai_private_key
from aea.crypto.ledger_apis import LedgerApis
from aea.crypto.wallet import Wallet
from aea.identity.base import Identity
from aea.protocols.base import Protocol
from aea.registries.base import Resources
from aea.skills.base import Skill

Set up a variable pointing to where the packages directory is located - this should be our current directory - and where the input and output files are located.

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

Create a private key

We need a private key to populate the AEA's wallet.

    # Create a private key
    _create_fetchai_private_key()

Clearing the input and output files

We will use the stub connection to pass envelopes in and out of the AEA. Ensure that any input and output text files are removed before we start.

    # 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)

Initialise the AEA

We use the private key file we created to initialise a wallet, we also create the stub connection, tell it what Ledger APIs we are going to use (none in this example) and create a resources object containing skills, protocols and connections (this is initially empty).

Then we pass all of this into the AEA constructor to create our AEA.

    # Set up the Wallet, stub connection, ledger and (empty) resources
    wallet = Wallet({FETCHAI: FETCHAI_PRIVATE_KEY_FILE})
    stub_connection = StubConnection(
        input_file_path=INPUT_FILE, output_file_path=OUTPUT_FILE
    )
    ledger_apis = LedgerApis({"fetchai": {"network": "testnet"}}, "fetchai")
    resources = Resources()
    # Create an identity
    identity = Identity(
        name="my_aea",
        address=wallet.addresses.get(FETCHAI),
        default_address_key=FETCHAI,
    )

    # Create our AEA
    my_aea = AEA(identity, [stub_connection], wallet, ledger_apis, resources)

Create the default protocol and add it to the AEA.

    # Add the default protocol (which is part of the AEA distribution)
    default_protocol = Protocol.from_dir(os.path.join(AEA_DIR, "protocols", "default"))
    resources.add_protocol(default_protocol)

Create the error skill (needed by all AEAs) and the echo skill which will bounce our messages back to us, and add them both to the AEA.

    # Add the error skill (from the local packages dir) and the echo skill (which is part of the AEA distribution)
    echo_skill = Skill.from_dir(
        os.path.join(ROOT_DIR, "packages", "fetchai", "skills", "echo"), my_aea.context,
    )
    resources.add_skill(echo_skill)
    error_skill = Skill.from_dir(
        os.path.join(AEA_DIR, "skills", "error"), my_aea.context
    )
    resources.add_skill(error_skill)

Start the AEA

We run the AEA from a different thread so that we can still use the main thread to pass it messages.

    # Set the AEA running in a different thread
    try:
        t = Thread(target=my_aea.start)
        t.start()

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

Send and receive an envelope

We use the input and output text files to send an envelope to our AEA and receive a response (from the echo skill)

        # Create a message inside an envelope and get the stub connection to pass it on to the echo skill
        message_text = (
            "my_aea,other_agent,fetchai/default:0.1.0,\x08\x01*\x07\n\x05hello,"
        )
        with open(INPUT_FILE, "w") as f:
            f.write(message_text)
            print("input message: " + message_text)

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

        # Read the output envelope generated by the echo skill
        with open(OUTPUT_FILE, "r") as f:
            print("output message: " + f.readline())

Shutdown

Finally stop our AEA and wait for it to finish

    finally:
        # Shut down the AEA
        my_aea.stop()
        t.join()
        t = None

Running the AEA

If you now run this python script file, you should see this output:

input message: my_aea,other_agent,fetchai/default:0.1.0,\x08\x01*\x07\n\x05hello
output message: other_agent,my_aea,fetchai/default:0.1.0,\x08\x01*\x07\n\x05hello

Entire code listing

If you just want to copy and past the entire script in you can find it here:

Click here to see full listing

import os
import time
from threading import Thread

from aea import AEA_DIR
from aea.aea import AEA
from aea.connections.stub.connection import StubConnection
from aea.crypto.fetchai import FETCHAI
from aea.crypto.helpers import FETCHAI_PRIVATE_KEY_FILE, _create_fetchai_private_key
from aea.crypto.ledger_apis import LedgerApis
from aea.crypto.wallet import Wallet
from aea.identity.base import Identity
from aea.protocols.base import Protocol
from aea.registries.base import Resources
from aea.skills.base import Skill

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


def run():
    # Create a private key
    _create_fetchai_private_key()

    # 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)

    # Set up the Wallet, stub connection, ledger and (empty) resources
    wallet = Wallet({FETCHAI: FETCHAI_PRIVATE_KEY_FILE})
    stub_connection = StubConnection(
        input_file_path=INPUT_FILE, output_file_path=OUTPUT_FILE
    )
    ledger_apis = LedgerApis({"fetchai": {"network": "testnet"}}, "fetchai")
    resources = Resources()
    # Create an identity
    identity = Identity(
        name="my_aea",
        address=wallet.addresses.get(FETCHAI),
        default_address_key=FETCHAI,
    )

    # Create our AEA
    my_aea = AEA(identity, [stub_connection], wallet, ledger_apis, resources)

    # Add the default protocol (which is part of the AEA distribution)
    default_protocol = Protocol.from_dir(os.path.join(AEA_DIR, "protocols", "default"))
    resources.add_protocol(default_protocol)

    # Add the error skill (from the local packages dir) and the echo skill (which is part of the AEA distribution)
    echo_skill = Skill.from_dir(
        os.path.join(ROOT_DIR, "packages", "fetchai", "skills", "echo"), my_aea.context,
    )
    resources.add_skill(echo_skill)
    error_skill = Skill.from_dir(
        os.path.join(AEA_DIR, "skills", "error"), my_aea.context
    )
    resources.add_skill(error_skill)

    # Set the AEA running in a different thread
    try:
        t = Thread(target=my_aea.start)
        t.start()

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

        # Create a message inside an envelope and get the stub connection to pass it on to the echo skill
        message_text = (
            "my_aea,other_agent,fetchai/default:0.1.0,\x08\x01*\x07\n\x05hello,"
        )
        with open(INPUT_FILE, "w") as f:
            f.write(message_text)
            print("input message: " + message_text)

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

        # Read the output envelope generated by the echo skill
        with open(OUTPUT_FILE, "r") as f:
            print("output message: " + f.readline())
    finally:
        # Shut down the AEA
        my_aea.stop()
        t.join()
        t = None


if __name__ == "__main__":
    run()