Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6363ce2

Browse files
committed
feat: polish a2a demo
- Add README - Add gif - Remove requirement to specify empty model/skill - Delete taskfile - Remove requirements.txt - Move ruff config to a separate file, to align with other examples
1 parent 613e182 commit 6363ce2

12 files changed

Lines changed: 186 additions & 119 deletions

File tree

.github/workflows/a2a.yaml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: A2A CI
2+
3+
on:
4+
push:
5+
paths:
6+
- '.github/workflows/a2a.yaml'
7+
- 'a2a/**'
8+
branches:
9+
- main
10+
pull_request:
11+
paths:
12+
- '.github/workflows/a2a.yaml'
13+
- 'a2a/**'
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
check:
20+
name: Format & Type Check
21+
runs-on: ubuntu-latest
22+
23+
defaults:
24+
run:
25+
working-directory: a2a
26+
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
31+
- name: Install uv
32+
run: |
33+
curl -LsSf https://astral.sh/uv/install.sh | sh
34+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH # Make uv available
35+
36+
- name: Check format
37+
run: uv run ruff format --check
38+
39+
- name: Check lint
40+
run: uv run ruff check
41+
42+
- name: Check types
43+
run: uv run pyright

a2a/.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/.vscode
22
/.venv
3-
/.ruff_cache
43
/.mypy_cache
5-
/build
4+
/.ruff_cache
5+
/.python-version
66
__pycache__
7-
.python-version
7+
*.pyc

a2a/.ruff.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[lint]
2+
select = ["E4", "E7", "E9", "F", "I", "RUF022"]
3+
4+
[lint.isort]
5+
force-sort-within-sections = true

a2a/Dockerfile

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
##### Base image
22
FROM python:3.13-slim AS base
33

4-
ENV PYTHONUNBUFFERED=1 \
5-
UV_COMPILE_BYTECODE=1 \
6-
UV_NO_CACHE=1
7-
4+
ENV PYTHONUNBUFFERED=1
85
RUN pip install uv
96

107
WORKDIR /app
118
COPY pyproject.toml uv.lock ./
12-
RUN uv pip install --system .
9+
RUN --mount=type=cache,target=/root/.cache/uv \
10+
UV_COMPILE_BYTECODE=1 uv pip install --system .
1311
COPY main.py src ./
1412
RUN python -m compileall -q .
1513

@@ -41,5 +39,6 @@ FROM base AS auditor-agent
4139

4240
COPY --chown=app:app agents/auditor.yaml /app/agent.yaml
4341
EXPOSE 8002
44-
CMD ["./entrypoint.sh", "adk", "web", ".", "--host", "0.0.0.0", "--port", "8002"]
42+
CMD ["./entrypoint.sh", "adk", "web", ".", "--host", "0.0.0.0", "--port", "8080"]
43+
# Use this to expose the agent as a web service instead of a UI
4544
#CMD ["python", "main.py", "--host", "0.0.0.0", "--port", "8002"]

a2a/README.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# 🧠 A2A Multi-Agent Fact Checker
2+
3+
This project demonstrates a **collaborative multi-agent system** built with the **Agent2Agent SDK** ([A2A]),
4+
where a top-level Auditor agent coordinates the workflow to verify facts. The Critic agent gathers evidence
5+
via live internet searches using **DuckDuckGo** through the Model Context Protocol (**MCP**), while the Reviser
6+
agent analyzes and refines the conclusion using internal reasoning alone. The system showcases how agents
7+
with distinct roles and tools can **collaborate under orchestration**.
8+
9+
> [!Tip]
10+
> ✨ No configuration needed — run it with a single command.
11+
12+
13+
<p align="center">
14+
<img src="demo.gif"
15+
alt="A2A Multi-Agent Fact Check Demo"
16+
width="500"
17+
style="border: 1px solid #ccc; border-radius: 8px;" />
18+
</p>
19+
20+
# 🚀 Getting Started
21+
22+
### Requirements
23+
24+
- 🐳 [Docker Desktop] **v4.43.0+**
25+
26+
### Run the project
27+
28+
29+
```sh
30+
docker compose up --build
31+
```
32+
33+
No configuration needed — everything runs from the container. Open `http://localhost:8080` in your browser to and select `AgentKit` in the selector at the top right, then chat with
34+
the agents.
35+
36+
37+
# ❓ What Can It Do?
38+
39+
This system performs multi-agent fact verification, coordinated by an **Auditor**:
40+
41+
- 🧑‍⚖️ **Auditor**:
42+
- Orchestrates the process from input to verdict.
43+
- Delegates tasks to Critic and Reviser agents.
44+
- 🧠 **Critic**:
45+
- Uses DuckDuckGo via MCP to gather real-time external evidence.
46+
- ✍️ **Reviser**:
47+
- Refines and verifies the Critic’s conclusions using only reasoning.
48+
49+
**🧠 All agents use the Docker Model Runner for LLM-based inference.**
50+
51+
Example question:
52+
53+
> “Is the universe infinite?"
54+
55+
# 🧱 Project Structure
56+
57+
| **File/Folder** | **Purpose** |
58+
| --------------- | --------------------------------------- |
59+
| `compose.yaml` | Launches app and MCP DuckDuckGo Gateway |
60+
| `Dockerfile` | Builds the agent container |
61+
| `src/AgentKit` | Agent runtime |
62+
| `agents/*.yaml` | Agent definitions |
63+
64+
65+
# 🔧 Architecture Overview
66+
67+
```mermaid
68+
69+
flowchart TD
70+
input[📝 User Question] --> auditor[🧑‍⚖️ Auditor Sequential Agent]
71+
auditor --> critic[🧠 Critic Agent]
72+
critic -->|uses| mcp[MCP Gateway<br/>DuckDuckGo Search]
73+
mcp --> duck[🌐 DuckDuckGo API]
74+
duck --> mcp --> critic
75+
critic --> reviser[(✍️ Reviser Agent<br/>No tools)]
76+
auditor --> reviser
77+
reviser --> auditor
78+
auditor --> result[✅ Final Answer]
79+
80+
critic -->|inference| model[(🧠 Docker Model Runner<br/>LLM)]
81+
reviser -->|inference| model
82+
83+
subgraph Infra
84+
mcp
85+
model
86+
end
87+
88+
```
89+
90+
- The Auditor is a Sequential Agent, it coordinates Critic and Reviser agents to verify user-provided claims.
91+
- The Critic agent performs live web searches through DuckDuckGo using an MCP-compatible gateway.
92+
- The Reviser agent refines the Critic’s conclusions using internal reasoning alone.
93+
- All agents run inference through a Docker-hosted Model Runner, enabling fully containerized LLM reasoning.
94+
95+
# 🤝 Agent Roles
96+
97+
| **Agent** | **Tools Used** | **Role Description** |
98+
| ----------- | --------------------- | ---------------------------------------------------------------------------- |
99+
| **Auditor** | ❌ None | Coordinates the entire fact-checking workflow and delivers the final answer. |
100+
| **Critic** | ✅ DuckDuckGo via MCP | Gathers evidence to support or refute the claim |
101+
| **Reviser** | ❌ None | Refines and finalizes the answer without external input |
102+
103+
104+
# 🧹 Cleanup
105+
106+
To stop and remove containers and volumes:
107+
108+
```sh
109+
docker compose down -v
110+
```
111+
112+
113+
# 📎 Credits
114+
- [A2A]
115+
- [DuckDuckGo]
116+
- [Docker Compose]
117+
118+
119+
[A2A]: https://github.com/a2aproject/a2a-python
120+
[DuckDuckGo]: https://duckduckgo.com
121+
[Docker Compose]: https://github.com/docker/compose
122+
[Docker Desktop]: https://www.docker.com/products/docker-desktop/

a2a/Taskfile.yml

Lines changed: 0 additions & 66 deletions
This file was deleted.

a2a/compose.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ services:
1515
build:
1616
target: auditor-agent
1717
ports:
18-
- "8002:8002"
18+
- "8080:8080"
1919
environment:
2020
- CRITIC_AGENT_URL=http://critic-agent-a2a:8001
2121
depends_on:
@@ -28,14 +28,11 @@ services:
2828
type: model
2929
options:
3030
# pre-pull the model on Docker Model Runner
31-
#model: olegselajev241/qwen3:14B-Q6_K
3231
model: ai/gemma3-qat:27B-Q4_K_M
3332
context-size: 20000
3433

3534
mcp-gateway:
3635
image: docker/agents_gateway:v2
37-
ports:
38-
- "8811:8811"
3936
command:
4037
- --transport=sse
4138
- --servers=duckduckgo

a2a/demo.gif

2.39 MB
Loading

a2a/pyproject.toml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,3 @@ dev = [
2525
"ruff>=0.12.0",
2626
"types-pyyaml>=6.0.12.20250516",
2727
]
28-
29-
[tool.pyright]
30-
venvPath = "."
31-
venv = ".venv"
32-
typeCheckingMode = "strict"
33-
reportMissingImports = true
34-
35-
[tool.ruff.lint]
36-
select = ["E4", "E7", "E9", "F", "I", "RUF022"]
37-
38-
[tool.ruff.lint.isort]
39-
force-sort-within-sections = true

a2a/requirements.txt

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)