Skip to content
Closed

wip #14

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 31 additions & 30 deletions .github/workflows/build-agent.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: Build and Push Agent Image

on:
pull_request:
push:
branches:
- main
Expand All @@ -14,33 +15,33 @@ jobs:
packages: write

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Python environment
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install BeeAI CLI
run: pip install beeai-cli

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker
uses: docker/setup-docker-action@v4
with:
daemon-config: '{"features": {"containerd-snapshotter": true}}'

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and Push
run: |
beeai build ./ --tag ghcr.io/${{ github.repository }}/my-agent:latest --no-import --multi-platform
docker push ghcr.io/${{ github.repository }}/my-agent:latest
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Python environment
uses: actions/setup-python@v4
with:
python-version: '3.x'

- name: Install BeeAI CLI
run: pip install -U "git+https://github.com/i-am-bee/beeai-platform.git@switch-to-a2a-protocol#subdirectory=apps/beeai-cli"

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker
uses: docker/setup-docker-action@v4
with:
daemon-config: '{"features": {"containerd-snapshotter": true}}'

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build and Push
run: |
beeai build ./ --tag ghcr.io/${{ github.repository }}/my-agent-a2a:latest --no-import --multi-platform
docker push ghcr.io/${{ github.repository }}/my-agent-a2a:latest
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.11-slim-bookworm
FROM python:3.13-slim-bookworm
COPY --from=ghcr.io/astral-sh/uv:0.6.16 /uv /bin/

ENV UV_LINK_MODE=copy \
Expand Down
40 changes: 28 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# BeeAI Platform Agent Template

This repository provides a template for creating a Python agent that can be used with the [BeeAI Platform](https://docs.beeai.dev).
# TODO: update readme

This repository provides a template for creating a Python agent that can be used with
the [BeeAI Platform](https://docs.beeai.dev).

## Overview

BeeAI agents are Python-based services that can be run locally or deployed to the BeeAI Platform. Each agent exposes specific functionality through the ACP (Agent Communication Protocol) which is implemented via SDK.
BeeAI agents are Python-based services that can be run locally or deployed to the BeeAI Platform. Each agent exposes
specific functionality through the ACP (Agent Communication Protocol) which is implemented via SDK.

In this template, you'll find:

- A basic agent implementation
- Docker configuration to ease the build of agent
- Project structure for building your own agents
Expand Down Expand Up @@ -38,11 +43,13 @@ In this template, you'll find:

## Getting Started

1. **Set up your project**. Start by using this template for your own agent. You may use this as a template or fork this repository.
1. **Set up your project**. Start by using this template for your own agent. You may use this as a template or fork this
repository.

2. **Install dependencies** using `uv sync`.

3. **Implement your agent** by modifying the source code located in [src/beeai_agents/server.py](src/beeai_agents/agent.py).
3. **Implement your agent** by modifying the source code located
in [src/beeai_agents/server.py](src/hello_world/agent.py).

Here's an example of the included template agent:

Expand All @@ -61,7 +68,9 @@ async def example_agent(input: list[Message], context: Context) -> AsyncGenerato
```

Modify this file to implement your own agent's logic. Here are some key points to consider when creating your agent:
- The function name (example_agent above) is used as the unique id for the agent in the platform. You can override this in the metadata.

- The function name (example_agent above) is used as the unique id for the agent in the platform. You can override this
in the metadata.
- The docstring is used as the agent's description in the platform UI. You can also override this in the metadata.
- The `@server.agent()` decorator registers your function as an agent and can customize its appearance and behavior
- Your agent receives messages in the `input` list, with the most recent message at the end
Expand All @@ -73,14 +82,15 @@ Modify this file to implement your own agent's logic. Here are some key points t

### 🖥️ Enhancing the User Experience with `PlatformUIAnnotation`

To create the most engaging and helpful interface for your users, define the following metadata in your agent decorator. This information shapes how your agent is presented in the GUI.
To create the most engaging and helpful interface for your users, define the following metadata in your agent decorator.
This information shapes how your agent is presented in the GUI.

```py
@server.agent(
name="chat",
description=(
"Conversational agent with memory, supporting real-time search, "
"Wikipedia lookups, and weather updates through integrated tools"
"Conversational agent with memory, supporting real-time search, "
"Wikipedia lookups, and weather updates through integrated tools"
),
metadata=Metadata(
annotations=Annotations(
Expand Down Expand Up @@ -108,10 +118,13 @@ To create the most engaging and helpful interface for your users, define the fol
)
```

>[!Note]
>The example above highlights the components that directly impact the **GUI experience**. For the complete metadata specification, see the [ACP Agent Detail](https://agentcommunicationprotocol.dev/core-concepts/agent-detail) documentation.
> [!Note]
> The example above highlights the components that directly impact the **GUI experience**. For the complete metadata
> specification, see the [ACP Agent Detail](https://agentcommunicationprotocol.dev/core-concepts/agent-detail)
> documentation.

4. **Update project metadata and dependencies** in the `pyproject.toml` file. After updating, synchronize with `uv sync`.
4. **Update project metadata and dependencies** in the `pyproject.toml` file. After updating, synchronize with
`uv sync`.

## Running Agents Locally

Expand Down Expand Up @@ -147,7 +160,9 @@ There are two ways to add your agent to the BeeAI Platform:

### Local Development Mode

When running agents locally with `uv run server`, they are automatically registered with the BeeAI Platform. In this mode:
When running agents locally with `uv run server`, they are automatically registered with the BeeAI Platform. In this
mode:

- The BeeAI Platform will communicate with your local server
- You manage the agent's lifecycle (starting/stopping)
- Changes are immediately available without redeployment
Expand All @@ -160,6 +175,7 @@ To share your agent with others or deploy it to the BeeAI Platform:
- Add the agent to BeeAI using: `beeai add https://github.com/your-username/your-repo-name`

The BeeAI Platform will automatically:

- Clone your repository
- Build a Docker image
- Start the agent container
Expand Down
11 changes: 6 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
[project]
name = "beeai-agents"
name = "hello-world"
version = "0.1.1"
description = "Add your description here"
description = "hello world agent"
readme = "README.md"
authors = [{ name = "IBM Corp." }]
requires-python = ">=3.11,<4.0"
requires-python = ">=3.13,<4.0"
dependencies = [
"acp-sdk>=0.13.0",
"a2a-sdk>=0.2.12",
"pyyaml>=6.0.2",
"uvicorn>=0.35.0",
]

[tool.ruff]
line-length = 120
target-version = "py311"

[project.scripts]
server = "beeai_agents.agent:run"
server = "hello_world.__main__:run"

[build-system]
requires = ["hatchling"]
Expand Down
30 changes: 0 additions & 30 deletions src/beeai_agents/agent.py

This file was deleted.

File renamed without changes.
34 changes: 34 additions & 0 deletions src/hello_world/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import uvicorn

from a2a.server.apps import A2AStarletteApplication
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard, AgentSkill, AgentExtension

from hello_world.agent import HelloWorldAgentExecutor


def run():
agent_card = AgentCard(
name="Hello World Agent",
description="Just a hello world agent",
url="http://localhost:8000/",
version="1.0.0",
defaultInputModes=["text"],
defaultOutputModes=["text"],
capabilities=AgentCapabilities(
extensions=[
AgentExtension(uri="beeai_ui", params={"ui_type": "chat"}),
AgentExtension(uri="required_env", params={"env": [{"name": "HELLO_TEMPLATE", "required": False}]}),
]
),
skills=[AgentSkill(id="hello_world", name="hello_world", description="returns hello world", tags=["hello"])],
)

request_handler = DefaultRequestHandler(agent_executor=HelloWorldAgentExecutor(), task_store=InMemoryTaskStore())
server = A2AStarletteApplication(agent_card=agent_card, http_handler=request_handler)
uvicorn.run(server.build(), host="0.0.0.0", port=8000)


if __name__ == "__main__":
run()
15 changes: 15 additions & 0 deletions src/hello_world/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import os

from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue
from a2a.utils import new_agent_text_message


class HelloWorldAgentExecutor(AgentExecutor):
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
hello_template: str = os.getenv("HELLO_TEMPLATE", "Ciao %s!")
result = hello_template % context.message.parts[0].root.text
await event_queue.enqueue_event(new_agent_text_message(result))

async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
raise NotImplementedError("cancel not supported")
Loading