-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(docs): added example of running agent with docker (#899)
Co-authored-by: felix.bucsa <[email protected]> Co-authored-by: Joshua Croft <[email protected]>
- Loading branch information
1 parent
65fbbfe
commit e86b7a1
Showing
2 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
``` |