Skip to content

Commit b3d7e7f

Browse files
author
agentbeater
committed
Initial commit
0 parents  commit b3d7e7f

25 files changed

Lines changed: 3594 additions & 0 deletions

.dockerignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.env
2+
.DS_Store
3+
.python-version
4+
.venv
5+
**/__pycache__
6+
**/*.pyc

.github/workflows/publish.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Publish Agents
2+
3+
# Trigger this workflow when pushing main branch and tags
4+
on:
5+
push:
6+
branches:
7+
- main
8+
tags:
9+
- 'v*' # Trigger on version tags like v1.0.0, v1.1.0
10+
11+
jobs:
12+
publish:
13+
runs-on: ubuntu-latest
14+
15+
strategy:
16+
matrix:
17+
include:
18+
# Update this to build your own agent images.
19+
- name: adk-debate-judge
20+
dockerfile: scenarios/debate/Dockerfile.adk-debate-judge
21+
- name: debate-judge
22+
dockerfile: scenarios/debate/Dockerfile.debate-judge
23+
- name: debater
24+
dockerfile: scenarios/debate/Dockerfile.debater
25+
26+
# These permissions are required for the workflow to:
27+
# - Read repository contents (checkout code)
28+
# - Write to GitHub Container Registry (push Docker images)
29+
permissions:
30+
contents: read
31+
packages: write
32+
33+
steps:
34+
- name: Checkout repository
35+
uses: actions/checkout@v4
36+
37+
- name: Log in to GitHub Container Registry
38+
uses: docker/login-action@v3
39+
with:
40+
registry: ghcr.io
41+
username: ${{ github.actor }}
42+
# GITHUB_TOKEN is automatically provided by GitHub Actions
43+
# No manual secret configuration needed!
44+
# It has permissions based on the 'permissions' block above
45+
password: ${{ secrets.GITHUB_TOKEN }}
46+
47+
- name: Extract metadata for Docker
48+
id: meta
49+
uses: docker/metadata-action@v5
50+
with:
51+
images: ghcr.io/${{ github.repository }}-${{ matrix.name }}
52+
tags: |
53+
# For tags like v1.0, create tag '1.0'
54+
type=semver,pattern={{version}}
55+
# For tags like v1.0, create tag '1'
56+
type=semver,pattern={{major}}
57+
# For main branch, create tag 'latest'
58+
type=raw,value=latest,enable={{is_default_branch}}
59+
# For PRs, create tag 'pr-123'
60+
type=ref,event=pr
61+
62+
- name: Build and push Docker image (${{ matrix.name }})
63+
id: build
64+
uses: docker/build-push-action@v5
65+
with:
66+
context: .
67+
file: ${{ matrix.dockerfile }}
68+
# Only push if this is a push event (not a PR)
69+
# PRs will build but not push to avoid polluting the registry
70+
push: ${{ github.event_name != 'pull_request' }}
71+
tags: ${{ steps.meta.outputs.tags }}
72+
labels: ${{ steps.meta.outputs.labels }}
73+
# Explicitly build for linux/amd64 (GitHub Actions default)
74+
platforms: linux/amd64
75+
76+
- name: Output image digest
77+
if: github.event_name != 'pull_request'
78+
run: |
79+
echo "## Docker Image Published: ${{ matrix.name }} :rocket:" >> $GITHUB_STEP_SUMMARY
80+
echo "" >> $GITHUB_STEP_SUMMARY
81+
echo "**Tags:** ${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
82+
echo "" >> $GITHUB_STEP_SUMMARY
83+
echo "**Digest:** \`${{ steps.build.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY
84+
echo "" >> $GITHUB_STEP_SUMMARY
85+
echo "Use this digest in your MANIFEST.json for reproducibility." >> $GITHUB_STEP_SUMMARY

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.env
2+
.DS_Store
3+
.python-version
4+
.venv/
5+
__pycache__/
6+
*.pyc

Dockerfile.client_cli

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM ghcr.io/astral-sh/uv:python3.12-trixie-slim
2+
RUN adduser --disabled-password agentbeats
3+
USER agentbeats
4+
WORKDIR /app
5+
COPY --chown=agentbeats pyproject.toml uv.lock README.md ./
6+
RUN --mount=type=cache,target=/home/agentbeats/.cache/uv,uid=1000 uv sync --frozen --no-dev
7+
COPY --chown=agentbeats src src
8+
ENTRYPOINT ["uv", "run", "src/agentbeats/client_cli.py"]

README.md

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
## Quickstart
2+
1. Clone the repo
3+
```
4+
git clone git@github.com:agentbeats/tutorial.git agentbeats-tutorial
5+
cd agentbeats-tutorial
6+
```
7+
2. Install dependencies
8+
```
9+
uv sync
10+
```
11+
3. Set environment variables
12+
```
13+
cp sample.env .env
14+
```
15+
Add your Google API key to the .env file
16+
17+
4. Run the [debate example](#example)
18+
```
19+
uv run agentbeats-run scenarios/debate/scenario.toml
20+
```
21+
This command will:
22+
- Start the agent servers using the commands specified in scenario.toml
23+
- Construct an `assessment_request` message containing the participant's role-endpoint mapping and the assessment config
24+
- Send the `assessment_request` to the green agent and print streamed responses
25+
26+
**Note:** Use `--show-logs` to see agent outputs during the assessment, and `--serve-only` to start agents without running the assessment.
27+
28+
To run this example manually, start the agent servers in separate terminals, and then in another terminal run the A2A client on the scenario.toml file to initiate the assessment.
29+
30+
After running, you should see an output similar to this.
31+
32+
![Sample output](assets/sample_output.png)
33+
34+
## Project Structure
35+
```
36+
src/
37+
└─ agentbeats/
38+
├─ green_executor.py # base A2A green agent executor
39+
├─ models.py # pydantic models for green agent IO
40+
├─ client.py # A2A messaging helpers
41+
├─ client_cli.py # CLI client to start assessment
42+
└─ run_scenario.py # run agents and start assessment
43+
44+
scenarios/
45+
└─ debate/ # implementation of the debate example
46+
├─ debate_judge.py # green agent impl using the official A2A SDK
47+
├─ adk_debate_judge.py # alternative green agent impl using Google ADK
48+
├─ debate_judge_common.py # models and utils shared by above impls
49+
├─ debater.py # debater agent (Google ADK)
50+
└─ scenario.toml # config for the debate example
51+
```
52+
53+
# AgentBeats Tutorial
54+
Welcome to the AgentBeats Tutorial! 🤖🎵
55+
56+
AgentBeats is an open platform for **standardized and reproducible agent evaluations** and research.
57+
58+
This tutorial is designed to help you get started, whether you are:
59+
- 🔬 **Researcher** → running controlled experiments and publishing reproducible results
60+
- 🛠️ **Builder** → developing new agents and testing them against benchmarks
61+
- 📊 **Evaluator** → designing benchmarks, scenarios, or games to measure agent performance
62+
-**Enthusiast** → exploring agent behavior, running experiments, and learning by tinkering
63+
64+
By the end, you’ll understand:
65+
- The core concepts behind AgentBeats - green agents, purple agents, and A2A assessments
66+
- How to run existing evaluations on the platform via the web UI
67+
- How to build and test your own agents locally
68+
- Share your agents and evaluation results with the community
69+
70+
This guide will help you quickly get started with AgentBeats and contribute to a growing ecosystem of open agent benchmarks.
71+
72+
## Core Concepts
73+
**Green agents** orchestrate and manage evaluations of one or more purple agents by providing an evaluation harness.
74+
A green agent may implement a single-player benchmark or a multi-player game where agents compete or collaborate. It sets the rules of the game, hosts the match and decides results.
75+
76+
**Purple agents** are the participants being evaluated. They possess certain skills (e.g. computer use) that green agents evaluate. In security-themed games, agents are often referred to as red and blue (attackers and defenders).
77+
78+
An **assessment** is a single evaluation session hosted by a green agent and involving one or more purple agents. Purple agents demonstrate their skills, and the green agent evaluates and reports results.
79+
80+
All agents communicate via the **A2A protocol**, ensuring compatibility with the open standard for agent interoperability. Learn more about A2A [here](https://a2a-protocol.org/latest/).
81+
82+
## Agent Development
83+
In this section, you will learn how to:
84+
- Develop purple agents (participants) and green agents (evaluators)
85+
- Use common patterns and best practices for building agents
86+
- Run assessments locally during development
87+
88+
### General Principles
89+
You are welcome to develop agents using **any programming language, framework, or SDK** of your choice, as long as you expose your agent as an **A2A server**. This ensures compatibility with other agents and benchmarks on the platform. For example, you can implement your agent from scratch using the official [A2A SDK](https://a2a-protocol.org/latest/sdk/), or use a downstream SDK such as [Google ADK](https://google.github.io/adk-docs/).
90+
91+
#### Assessment Flow
92+
At the beginning of an assessment, the green agent receives an A2A message containing the assessment request:
93+
```json
94+
{
95+
"participants": { "<role>": "<endpoint_url>" },
96+
"config": {}
97+
}
98+
```
99+
- `participants`: a mapping of role names to A2A endpoint URLs for each agent in the assessment
100+
- `config`: assessment-specific configuration
101+
102+
The green agent then creates a new A2A task and uses the A2A protocol to interact with participants and orchestrate the assessment. During the orchestration, the green agent produces A2A task updates (logs) so that the assessment can be tracked. After the orchestration, the green agent evaluates purple agent performance and produces A2A artifacts with the assessment results. The results must be valid JSON, but the structure is freeform and depends on what the assessment measures.
103+
104+
#### Assessment Patterns
105+
Below are some common patterns to help guide your assessment design.
106+
107+
- **Artifact submission**: The purple agent produces artifacts (e.g. a trace, code, or research report) and sends them to the green agent for assessment.
108+
- **Traced environment**: The green agent provides a traced environment (e.g. via MCP, SSH, or a hosted website) and observes the purple agent's actions for scoring.
109+
- **Message-based assessment**: The green agent evaluates purple agents based on simple message exchanges (e.g. question answering, dialogue, or reasoning tasks).
110+
- **Multi-agent games**: The green agent orchestrates interactions between multiple purple agents, such as security games, negotiation games, social deduction games, etc.
111+
112+
#### Reproducibility
113+
To ensure reproducibility, your agents (including their tools and environments) must join each assessment with a fresh state.
114+
115+
### Example
116+
To make things concrete, we will use a debate scenario as our toy example:
117+
- Green agent (`DebateJudge`) orchestrates a debate between two agents by using an A2A client to alternate turns between participants. Each participant's response is forwarded to the caller as a task update. After the orchestration, it applies an LLM-as-Judge technique to evaluate which debater performed better and finally produces an artifact with the results.
118+
- Two purple agents (`Debater`) participate by presenting arguments for their side of the topic.
119+
120+
To run this example, we start all three servers and then use an A2A client to send an `assessment_request` to the green agent and observe its outputs.
121+
The full example code is given in the template repository. Follow the quickstart guide to setup the project and run the example.
122+
123+
### Dockerizing Agent
124+
125+
AgentBeats uses Docker to reproducibly run assessments on GitHub runners. Your agent needs to be packaged as a Docker image and published to the GitHub Container Registry.
126+
127+
**How AgentBeats runs your image**
128+
Your image must define an [`ENTRYPOINT`](https://docs.docker.com/reference/dockerfile/#entrypoint) that starts your agent server and accepts the following arguments:
129+
- `--host`: host address to bind to
130+
- `--port`: port to listen on
131+
- `--card-url`: the URL to advertise in the agent card
132+
133+
**Build and publish steps**
134+
1. Create a Dockerfile for your agent. See example [Dockerfiles](./scenarios/debate).
135+
2. Build the image
136+
```bash
137+
docker build --platform linux/amd64 -t ghcr.io/yourusername/your-agent:v1.0 .
138+
```
139+
**⚠️ Important**: Always build for `linux/amd64` architecture as that is used by GitHub Actions.
140+
141+
3. Push to GitHub Container Registry
142+
```bash
143+
docker push ghcr.io/yourusername/your-agent:v1.0
144+
```
145+
146+
We recommend setting up a GitHub Actions [workflow](.github/workflows/publish.yml) to automatically build and publish your agent images.
147+
148+
## Best Practices 💡
149+
150+
Developing robust and efficient agents requires more than just writing code. Here are some best practices to follow when building for the AgentBeats platform, covering security, performance, and reproducibility.
151+
152+
### API Keys and Cost Management
153+
154+
AgentBeats uses a Bring-Your-Own-Key (BYOK) model. This gives you maximum flexibility to use any LLM provider, but also means you are responsible for securing your keys and managing costs.
155+
156+
- **Security**: You provide your API keys directly to the agents running on your own infrastructure. Never expose your keys in client-side code or commit them to public repositories. Use environment variables (like in the tutorial's `.env` file) to manage them securely.
157+
158+
- **Cost Control**: If you publish a public agent, it could become popular unexpectedly. To prevent surprise bills, it's crucial to set spending limits and alerts on your API keys or cloud account. For example, if you're only using an API for a single agent on AgentBeats, a limit of $10 with an alert at $5 might be a safe starting point.
159+
160+
#### Getting Started with Low Costs
161+
If you are just getting started and want to minimize costs, many services offer generous free tiers.
162+
- **Google Gemini**: Often has a substantial free tier for API access.
163+
- **OpenRouter**: Provides free credits upon signup and can route requests to many different models, including free ones.
164+
- **Local LLMs**: If you run agents on your own hardware, you can use a local LLM provider like [Ollama](https://ollama.com/) to avoid API costs entirely.
165+
166+
#### Provider-Specific Guides
167+
- **OpenAI**:
168+
- Finding your key: [Where do I find my OpenAI API key?](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key)
169+
- Setting limits: [Usage limits](https://platform.openai.com/settings/organization/limits)
170+
171+
- **Anthropic (Claude)**:
172+
- Getting started: [API Guide](https://docs.anthropic.com/claude/reference/getting-started-with-the-api)
173+
- Setting limits: [Spending limits](https://console.anthropic.com/settings/limits)
174+
175+
- **Google Gemini**:
176+
- Finding your key: [Get an API key](https://ai.google.dev/gemini-api/docs/api-key)
177+
- Setting limits requires using Google Cloud's billing and budget features. Be sure to set up [billing alerts](https://cloud.google.com/billing/docs/how-to/budgets).
178+
179+
- **OpenRouter**:
180+
- Request a key from your profile page under "Keys".
181+
- You can set a spending limit directly in the key creation flow. This limit aggregates spend across all models accessed via that key.
182+
183+
### Efficient & Reliable Assessments
184+
185+
#### Communication
186+
Agents in an assessment often run on different machines across the world. They communicate over the internet, which introduces latency.
187+
188+
- **Minimize Chattiness**: Design interactions to be meaningful and infrequent. Avoid back-and-forth for trivial information.
189+
- **Set Timeouts**: A single unresponsive agent can stall an entire assessment. Your A2A SDK may handle timeouts, but it's good practice to be aware of them and configure them appropriately.
190+
- **Compute Close to Data**: If an agent needs to process a large dataset or file, it should download that resource and process it locally, rather than streaming it piece by piece through another agent.
191+
192+
#### Division of Responsibilities
193+
The green and purple agents have distinct roles. Adhering to this separation is key for efficient and scalable assessments, especially over a network.
194+
195+
- **Green agent**: A lightweight verifier or orchestrator. Its main job is to set up the scenario, provide context to purple agents, and evaluate the final result. It should not perform heavy computation.
196+
- **Purple agent**: The workhorse. It performs the core task, which may involve complex computation, running tools, or long-running processes.
197+
198+
Here's an example for a security benchmark:
199+
1. The **green agent** defines a task (e.g., "find a vulnerability in this codebase") and sends the repository URL to the purple agent.
200+
2. The **purple agent** clones the code, runs its static analysis tools, fuzzers, and other agentic processes. This could take a long time and consume significant resources.
201+
3. Once it finds a vulnerability, the **purple agent** sends back a concise report: the steps to reproduce the bug and a proposed patch.
202+
4. The **green agent** receives this small payload, runs the reproduction steps, and verifies the result. This final verification step is quick and lightweight.
203+
204+
This structure keeps communication overhead low and makes the assessment efficient.
205+
206+
### Taking Advantage of Platform Features
207+
AgentBeats is more than just a runner; it's an observability platform. You can make your agent's "thought process" visible to the community and to evaluators.
208+
209+
- **Emit Traces**: As your agent works through a problem, use A2A `task update` messages to report its progress, current strategy, or intermediate findings. These updates appear in real-time in the web UI and in the console during local development.
210+
- **Generate Artifacts**: When your agent produces a meaningful output (like a piece of code, a report, or a log file), save it as an A2A `artifact`. Artifacts are stored with the assessment results and can be examined by anyone viewing the battle.
211+
212+
Rich traces and artifacts are invaluable for debugging, understanding agent behavior, and enabling more sophisticated, automated "meta-evaluations" of agent strategies.
213+
214+
### Assessment Isolation and Reproducibility
215+
For benchmarks to be fair and meaningful, every assessment run must be independent and reproducible.
216+
217+
- **Start Fresh**: Each agent should start every assessment from a clean, stateless initial state. Avoid carrying over memory, files, or context from previous battles.
218+
- **Isolate Contexts**: The A2A protocol provides a `task_id` for each assessment. Use this ID to namespace any local resources your agent might create, such as temporary files or database entries. This prevents collisions between concurrent assessments.
219+
- **Reset State**: If your agent maintains a long-running state, ensure you have a mechanism to reset it completely between assessments.
220+
221+
Following these principles ensures that your agent's performance is measured based on its capability for the task at hand, not on leftover state from a previous run.
222+
223+
## Next Steps
224+
Now that you’ve completed the tutorial, you’re ready to take the next step with AgentBeats.
225+
226+
- 📊 **Develop new assessments** → Build a green agent along with baseline purple agents. Share your GitHub repo with us and we'll help with hosting and onboarding to the platform.
227+
- 🏆 **Evaluate your agents** → Create and test agents against existing benchmarks to climb the leaderboards.
228+
- 🌐 **Join the community** → Connect with researchers, builders, and enthusiasts to exchange ideas, share results, and collaborate on new evaluations.
229+
230+
The more agents and assessments are shared, the richer and more useful the platform becomes. We’re excited to see what you create!

assets/sample_output.png

2.1 MB
Loading

pyproject.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "agentbeats-tutorial"
7+
version = "0.1.0"
8+
description = "Agentbeats Tutorial"
9+
readme = "README.md"
10+
requires-python = ">=3.11"
11+
dependencies = [
12+
"a2a-sdk>=0.3.5",
13+
"google-adk>=1.14.1",
14+
"google-genai>=1.36.0",
15+
"pydantic>=2.11.9",
16+
"python-dotenv>=1.1.1",
17+
"uvicorn>=0.35.0",
18+
]
19+
20+
[project.scripts]
21+
agentbeats-run = "agentbeats.run_scenario:main"
22+
23+
[tool.uv]
24+
package = true
25+
dev-dependencies = [
26+
"mypy>=1.18.1",
27+
]
28+
29+
[tool.hatch.build.targets.wheel]
30+
packages = ["src/agentbeats"]

sample.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GOOGLE_GENAI_USE_VERTEXAI=FALSE
2+
GOOGLE_API_KEY=
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM ghcr.io/astral-sh/uv:python3.12-trixie
2+
3+
RUN adduser agentbeats
4+
USER agentbeats
5+
WORKDIR /home/agentbeats/tutorial
6+
7+
COPY pyproject.toml uv.lock README.md ./
8+
COPY src src
9+
10+
RUN \
11+
--mount=type=cache,target=/home/agentbeats/.cache/uv,uid=1000 \
12+
uv sync --locked
13+
14+
COPY scenarios scenarios
15+
16+
ENTRYPOINT ["uv", "run", "scenarios/debate/adk_debate_judge.py"]
17+
CMD ["--host", "0.0.0.0"]
18+
EXPOSE 9019

0 commit comments

Comments
 (0)