Skip to content

Commit 8195a5e

Browse files
Merge pull request #9 from satendrakumar/develop
Docker build and run steps
2 parents 90dd73f + e223aee commit 8195a5e

File tree

5 files changed

+196
-35
lines changed

5 files changed

+196
-35
lines changed

.dockerignore

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
*.so
6+
.Python
7+
build/
8+
develop-eggs/
9+
dist/
10+
downloads/
11+
eggs/
12+
.eggs/
13+
lib/
14+
lib64/
15+
parts/
16+
sdist/
17+
var/
18+
wheels/
19+
share/python-wheels/
20+
*.egg-info/
21+
.installed.cfg
22+
*.egg
23+
MANIFEST
24+
25+
# Virtual environments
26+
.venv/
27+
venv/
28+
ENV/
29+
env/
30+
.env/
31+
32+
# Environment files
33+
.env
34+
.env.local
35+
.env.development
36+
.env.test
37+
.env.production
38+
39+
# IDE and editor files
40+
.vscode/
41+
.idea/
42+
*.swp
43+
*.swo
44+
*~
45+
46+
# OS generated files
47+
.DS_Store
48+
.DS_Store?
49+
._*
50+
.Spotlight-V100
51+
.Trashes
52+
ehthumbs.db
53+
Thumbs.db
54+
55+
# Git
56+
.git/
57+
.gitignore
58+
59+
# Testing
60+
.pytest_cache/
61+
.coverage
62+
htmlcov/
63+
.tox/
64+
.nox/
65+
.cache
66+
67+
# Documentation
68+
docs/_build/
69+
70+
# Jupyter Notebooks
71+
.ipynb_checkpoints
72+
73+
# MyPy
74+
.mypy_cache/
75+
.dmypy.json
76+
dmypy.json
77+
78+
# Logs
79+
*.log
80+
logs/
81+
82+
# Temporary files
83+
*.tmp
84+
*.temp
85+
86+
# Docker
87+
Dockerfile*
88+
docker-compose*.yml
89+
.dockerignore
90+
91+
# README and documentation
92+
README.md
93+
*.md
94+
95+
# Project specific
96+
checks.sh

Dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
FROM python:3.13-slim
2+
3+
# Set working directory
4+
WORKDIR /app
5+
6+
# Install uv
7+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
8+
9+
# Copy dependency files first for better caching
10+
COPY pyproject.toml uv.lock ./
11+
12+
# Install dependencies using uv
13+
RUN uv sync --frozen --no-cache
14+
15+
# Copy code
16+
COPY src ./src
17+
18+
COPY main.py .
19+
20+
COPY start.sh .
21+
22+
RUN chmod +x ./start.sh
23+
24+
# Use the startup script
25+
CMD ["./start.sh"]

README.md

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,46 +45,75 @@ Three agents running on the same host:
4545

4646
---
4747

48-
## 🧪 Testing the Agents:
49-
50-
Run the provided client app to send test requests:
51-
52-
```shell
53-
uv run a2a_client_app.py
54-
```
48+
## 🧪 Testing Agents using A2AClient:
49+
50+
Run the provided client app to send test requests:
51+
52+
```bash
53+
uv run a2a_client_app.py
54+
```
55+
56+
## Testing Agents Using CURL request:
57+
```bash
58+
Request:
59+
curl --location 'http://localhost:8000/a2a/conversation/' \
60+
--header 'Content-Type: application/json' \
61+
--header 'Accept: text/event-stream' \
62+
--data '{
63+
"id": "6a39c736-fff7-45f8-b2b0-c44e705d2474",
64+
"jsonrpc": "2.0",
65+
"method": "message/stream",
66+
"params": {
67+
"configuration": {
68+
"acceptedOutputModes": [],
69+
"blocking": "True"
70+
},
71+
"message": {
72+
"contextId": "8bffff7b-3abc-4d85-bcce-0bcdbe321017",
73+
"kind": "message",
74+
"messageId": "82642fd2-f270-4a56-a7d9-5d26fddabc95",
75+
"parts": [
76+
{
77+
"kind": "text",
78+
"text": "Who is PM of India?"
79+
}
80+
],
81+
"role": "user"
82+
}
83+
}
84+
}'
85+
Reponse:
86+
{
87+
"id": "6a39c736-fff7-45f8-b2b0-c44e705d2474",
88+
"jsonrpc": "2.0",
89+
"result": {
90+
"artifact": {
91+
"artifactId": "9474e1ac-1e35-425c-9c18-238b07739e6d",
92+
"parts": [
93+
{
94+
"kind": "text",
95+
"text": "As of today, August 16, 2025, the Prime Minister of India is **Narendra Modi**.\n\nHe has been serving as the Prime Minister since May 26, 2014, and was sworn in for his third consecutive term on June 9, 2024, following the 2024 Parliamentary elections."
96+
}
97+
]
98+
},
99+
"contextId": "8bffff7b-3abc-4d85-bcce-0bcdbe321017",
100+
"kind": "artifact-update",
101+
"lastChunk": true,
102+
"taskId": "23a93002-686b-4c8a-8bb6-ec649acea0c3"
103+
}
104+
}
105+
```
55106

56107
---
57108

58-
## 📂 Project Structure
59-
60-
```text
61-
├── README.md
62-
├── a2a_client_app.py
63-
├── main.py
64-
├── pyproject.toml
65-
├── src
66-
│ ├── __init__.py
67-
│ ├── a2a
68-
│ │ ├── __init__.py
69-
│ │ ├── a2a_client.py
70-
│ │ └── a2a_fastapi_app.py
71-
│ └── agent
72-
│ ├── __init__.py
73-
│ ├── analyzer_agent.py
74-
│ ├── conversation_agent.py
75-
│ └── trending_topics_agent.py
76-
└── uv.lock
77-
109+
## How to run inside Docker:
110+
```bash
111+
# Docker build
112+
docker build -t multiple-agents-on-single-a2a-server:v1.0.0 .
113+
# Docker run
114+
docker run --env-file ./.env -e PORT=8000 -p 8000:8000 multiple-agents-on-single-a2a-server:v1.0.0
78115
```
79116

80-
---
81-
82-
## ✅ Requirements
83-
84-
Key dependencies defined in `pyproject.toml`:
85-
86-
* `a2a-sdk`
87-
* `google-adk`
88117

89118
---
90119

main.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import uvicorn
55
from dotenv import load_dotenv
66
from fastapi import FastAPI
7+
from starlette.middleware.cors import CORSMiddleware
78

89
from src.a2a.a2a_utils import A2AUtils
910
from src.agent.analyzer_agent import get_analyzer_agent, get_analyzer_agent_card
@@ -33,6 +34,13 @@
3334
root_path="/a2a",
3435
)
3536

37+
app.add_middleware(
38+
CORSMiddleware,
39+
allow_origins=['*'],
40+
allow_credentials=True,
41+
allow_methods=["*"],
42+
allow_headers=["*"],
43+
)
3644

3745
@app.get("/health")
3846
async def health_check() -> dict[str, str]:

start.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
uv run uvicorn main:app --host 0.0.0.0 --port "${PORT:-8000}"

0 commit comments

Comments
 (0)