From e86b7a1ccef0d859e816780b33ee10d4e5f7cc78 Mon Sep 17 00:00:00 2001 From: gautamgambhir97 <140384949+gautamgambhir97@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:31:07 +0530 Subject: [PATCH] feat(docs): added example of running agent with docker (#899) Co-authored-by: felix.bucsa <72919584+FelixNicolaeBucsa@users.noreply.github.com> Co-authored-by: Joshua Croft <32483134+devjsc@users.noreply.github.com> --- pages/examples/intermediate/_meta.json | 5 + .../intermediate/agents-with-docker.mdx | 181 ++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 pages/examples/intermediate/agents-with-docker.mdx diff --git a/pages/examples/intermediate/_meta.json b/pages/examples/intermediate/_meta.json index b6b694978..97535e20d 100644 --- a/pages/examples/intermediate/_meta.json +++ b/pages/examples/intermediate/_meta.json @@ -134,6 +134,11 @@ "tags": ["Intermediate", "Python", "Functions", "OpenAI", "Use Cases"], "timestamp": true }, + "agents-with-docker": { + "title": "Running an Agent with Docker", + "tags": ["Intermediate", "Python", "Docker", "Use Cases"], + "timestamp": true + }, "postgres-database-with-an-agent": { "title": "Utilize the PostgreSQL database with the Agent.", "tags": ["Intermediate", "Python", "Docker", "PostgreSQL", "Use Cases"], diff --git a/pages/examples/intermediate/agents-with-docker.mdx b/pages/examples/intermediate/agents-with-docker.mdx new file mode 100644 index 000000000..abbd9de38 --- /dev/null +++ b/pages/examples/intermediate/agents-with-docker.mdx @@ -0,0 +1,181 @@ + +# Running an Agent with Docker + +## Introduction + + +This example shows how to run an agent using the uAgents library inside a Docker container with Docker Compose. It walks you through setting up everything you need so you can easily build and run the agent. + + +### Supporting Documents + + - [Almanac contract overview ↗️](../../references/contracts/uagents-almanac/almanac-overview). + - [How to create an agent ↗️](../../guides/agents/create-a-uagent). + - [Registering in the Almanac Contract ↗️](../../guides/agents/register-in-almanac). + - [Creating an interval task ↗️](/guides/agents/interval-task) + - [Communicating with other agents ↗️](/guides/agents/communicating-with-other-agents) + + +## Pre-requisites + +- **Python:** Download and install from [Python official website ↗️](https://www.python.org/downloads/). +- **Poetry:** Install by following the instructions on [Poetry's official website ↗️](https://python-poetry.org/docs/#installation). +- **Docker:** Download and install from [Docker official website ↗️](https://docs.docker.com/get-docker/). +- **Docker Compose:** Download and install from [Docker Compose official documentation ↗️](https://docs.docker.com/compose/). + +## Project Structure + +``` +.agent_with_docker +├── docker-compose.yml +├── Dockerfile +├── poetry.lock +├── pyproject.toml +├── README.md +└── src + └── agent.py +``` + +## Agent with Docker + +### `agent.py` + +This example demonstrates a simple agent-based communication system using the uAgents library. The `data_sender` agent sends a `DataPacket` message to the `data_receiver` agent every 4 seconds. Upon receiving the message, `data_receiver` logs it and sends an acknowledgment back to data_sender. Both agents log the messages they receive. The agents are running with Docker Compose using Docker. + + +```py copy filename="agent.py" + +from uagents import Agent, Bureau, Context, Model + + +class DataPacket(Model): + message: str + + +data_sender = Agent(name="data_sender", seed="data_sender recovery phrase") +data_receiver = Agent(name="data_receiver", seed="data_receiver recovery phrase") + + +@data_sender.on_interval(period=4.0) +async def send_data_packet(ctx: Context): + """ + Event handler that gets triggered at regular intervals (every 4 seconds). + + Args: + ctx (Context): The context in which the event is triggered. + + Returns: + None: This function does not return any value but sends a DataPacket message from data_sender to data_receiver at intervals of (every 4 seconds). + """ + await ctx.send( + data_receiver.address, DataPacket(message="Initiating data transfer") + ) + + +@data_sender.on_message(model=DataPacket) +async def data_sender_message_handler(ctx: Context, sender: str, msg: DataPacket): + """ + Event handler that gets triggered when data_sender receives a DataPacket message. + + Args: + ctx (Context): The context in which the event is triggered. + sender (str): The address of the sender. + msg (DataPacket): The message received. + + Returns: + None: This function does not return any value but logs the received message. + """ + ctx.logger.info(f"Data Sender received a message from {sender}: {msg.message}") + + +@data_receiver.on_message(model=DataPacket) +async def data_receiver_message_handler(ctx: Context, sender: str, msg: DataPacket): + """ + Event handler that gets triggered when data_receiver receives a DataPacket message. + + Args: + ctx (Context): The context in which the event is triggered. + sender (str): The address of the sender. + msg (DataPacket): The message received. + + Returns: + None: This function does not return any value but logs the received message and sends an acknowledgment back to data_sender. + """ + ctx.logger.info(f"Data Receiver received a message from {sender}: {msg.message}") + await ctx.send( + data_sender.address, DataPacket(message="Acknowledging data transfer") + ) + + +bureau = Bureau() +bureau.add(data_sender) +bureau.add(data_receiver) + +if __name__ == "__main__": + bureau.run() +``` + +### `Dockerfile` + +This Dockerfile sets up a Python environment with Poetry for dependency management. It installs necessary system packages, sets up the working directory, installs dependencies specified in `pyproject.toml`, and runs `agent.py` using Poetry. The application listens on port 8000. + +```Dockerfile copy filename="Dockerfile" +FROM python:3.12-slim +ENV PATH="$PATH:/root/.local/bin" + +RUN apt-get update && \ + apt-get install -y curl gcc && \ + curl -sSL https://install.python-poetry.org/ | python3 - + +WORKDIR /app +ADD pyproject.toml poetry.lock /app/ +RUN poetry install +ADD . /app +EXPOSE 8000 + +ENTRYPOINT ["poetry", "run"] +CMD ["python", "agent.py"] +``` + +### `docker-compose.yml` +This Docker Compose configuration builds and runs a Python app using Poetry. It maps the current directory to the container, exposes port 8000, and starts the `agent.py` script. + +```yml copy filename="docker-compose.yml" +version: '3.8' + +services: + app: + build: . + container_name: poetry_app + volumes: + - .:/app + ports: + - "8000:8000" + command: poetry run python src/agent.py +``` + +## Poetry Dependencies + +``` +[tool.poetry.dependencies] +python = "^3.10" +uagents = { version = "^0.13.0", python = ">=3.10,<3.13" } +``` + +## How to Run This Example + +- Navigate to the root Folder of the Example. +- Run `docker-compose build` +- Run `docker-compose up` + +## Expected Output + +``` +Creating network "agent_with_docker_default" with the default driver +Creating poetry_app ... done +Attaching to poetry_app +poetry_app | INFO: [data_receiver]: Data Receiver received a message from agent1qdccxu8z03y3m27p22emtuffjxng8ks3pm69yn703eec6pk5a8p5vzf97qz: Initiating data transfer +poetry_app | INFO: [bureau]: Starting server on http://0.0.0.0:8000 (Press CTRL+C to quit) +poetry_app | INFO: [data_sender]: Data Sender received a message from agent1qg0ejev64auhjg7c7xsd32v7npflvhvs5afe43r4gzm4eqmhqgxs7mlfss0: Acknowledging data transfer +poetry_app | INFO: [data_receiver]: Data Receiver received a message from agent1qdccxu8z03y3m27p22emtuffjxng8ks3pm69yn703eec6pk5a8p5vzf97qz: Initiating data transfer +```