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 .
- How to create an agent .
- Registering in the Almanac Contract .
- Creating an interval task
- Communicating with other agents
Pre-requisites
- Python: Download and install from Python official website (opens in a new tab).
- Poetry: Install by following the instructions on Poetry's official website (opens in a new tab).
- Docker: Download and install from Docker official website (opens in a new tab).
- Docker Compose: Download and install from Docker Compose official documentation (opens in a new tab).
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.
agent.pyfrom 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.
DockerfileFROM 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.
docker-compose.ymlversion: '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