A2A Security Scanner Pipeline (Google Cloud A2A/ADK Challenge)
TL;DR: A parallel, fault-tolerant, multi-agent CI/CD security scanner.
Agents: Dependencies (A2), Secrets (A3), IaC (A4), Exposure (A6), Risk (A7), Reporter (A8).
Core: Orchestrator (A0) fans out tasks in parallel, fans in results, scores risk, and publishes a report.
UX: Live dashboard (dashboard.html) with health, loop status, latency charts, and recent runs.
Table of Contents
- Project Goals
- High-Level Architecture
- A2A Protocol
- Repository Layout
- Agent Responsibilities
- Orchestrator (A0) Mechanics
- Continuous Monitoring Loop
- Frontend Dashboard
- Local Development & Quickstart
- Manual API Testing
- Troubleshooting
- Config & Environment
- Extending: Adding a New Agent
- Performance Notes
- Security Notes
- FAQ
Project Goals
- Parallelism: Execute multiple security scans concurrently (4× faster vs sequential).
- Fault tolerance: One failing agent doesn't block the others; partials still aggregate.
- A2A compliance: Agents self-describe via discovery and exchange structured envelopes.
- Autonomy: Background monitoring loop that periodically scans on a schedule.
- Observability: Human-friendly dashboard with health, latency, loop progress, and recent runs.
---
## A2A Protocol
### Discovery
Each agent exposes a discovery card at:
GET /.well-known/agent.json
Example:
```json
{
"name": "A4_iac",
"version": "1.0.0",
"capabilities": ["lint_iac"],
"endpoint": "http://localhost:8014/a2a/task"
}
Envelopes
TASK envelope (A0 → agent):
{
"spec_version": "a2a.v1",
"type": "TASK",
"capability": "lint_iac",
"from": "A0_orchestrator",
"to": "A4_iac",
"reply_to": "A0_orchestrator",
"build_id": "build-123",
"payload": {
"repo": "org/app",
"commit": "latest"
}
}
RESULT envelope (agent → A0):
{
"spec_version": "a2a.v1",
"type": "RESULT",
"capability": "lint_iac",
"from": "A4_iac",
"to": "A0_orchestrator",
"reply_to": "msg-id-of-task",
"build_id": "build-123",
"payload": {
"misconfigs": []
}
}
Repository Layout
.
├─ agents/
│ ├─ A0_orchestrator/
│ │ ├─ orchestrator.py # Orchestrator service (FastAPI)
│ │ ├─ agent_card.json # A2A discovery
│ │ └─ dashboard.html # Frontend UI
│ ├─ A2_deps/ # Dependency audit agent
│ ├─ A3_secrets/ # Secret scanner agent
│ ├─ A4_iac/ # IaC linter agent
│ ├─ A6_exposure/ # Exposure checker agent
│ ├─ A7_risk/ # Risk scoring agent
│ └─ A8_reporter/ # Report publisher agent
├─ lib/
│ └─ validate.py # new_card() & helpers
├─ scripts/
│ ├─ start_all.ps1 # Launch all agents
│ ├─ health.ps1 # Health checks
│ └─ smoke.ps1 # Trigger & readout test
└─ tests/
└─ smoke.py # Python smoke test (optional)
Agent Responsibilities
- A2_deps –
audit_dependencies→ Simulates dependency audit. - A3_secrets –
scan_secrets→ Simulates secret scanning. - A4_iac –
lint_iac→ Lints IaC configs (capability key = lint_iac). - A6_exposure –
check_exposure→ Simulates surface exposure checks. - A7_risk –
score_risk→ Aggregates partials into a risk score. - A8_reporter –
publish_report→ Produces final highlights + summary.
Orchestrator (A0) Mechanics
- Ports: Orchestrator = 8010, Agents = 8012–8018.
- Endpoints:
/trigger,/monitor/start,/monitor/status,/monitor/stop. - Pipeline: Fan-out → fan-in → risk scoring → report.
- Benefits: 4× faster, tolerant of failures, scalable.
Continuous Monitoring Loop
- Background asyncio task started by
/monitor/start. - Runs pipeline every
interval_seconds. - Tracks runs in
monitoring_state.runs. - Resilient: survives errors, cancels cleanly.
Frontend Dashboard
Built with: Tailwind + Chart.js.
Panels:
- Challenge Requirements
- Control Panel (manual scan + loop control)
- Agent Status (green/gray)
- Activity Log
Features:
- Polls
/monitor/statusevery 5s - Real-time feedback for loop + scans
Local Development & Quickstart
# Install deps
pip install fastapi uvicorn httpx
# Start all agents
.\scripts\start_all.ps1
# Verify health
.\scripts\health.ps1
# Open dashboard
http://127.0.0.1:8010
Trigger manually:
$body = @{ build_id="demo"; repo="org/app"; commit="latest"} | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri http://127.0.0.1:8010/trigger -ContentType 'application/json' -Body $body
Manual API Testing
Health:
Invoke-RestMethod http://127.0.0.1:8014/health
Discovery:
Invoke-RestMethod http://127.0.0.1:8014/.well-known/agent.json
Troubleshooting
- "Some agents failed" → Check
/healthor logs. - A4_iac errors → Ensure capability is
lint_iac. - Loop not ticking → Confirm updated orchestrator with
monitor_task. - PowerShell curl issues → Use
Invoke-RestMethod.
Config & Environment
- Ports: fixed 8010–8018.
- Risk policy threshold: default = 70.
- Orchestrator CORS: open (for demo).
Extending: Adding a New Agent
- Create folder
agents/A9_foo/withmain.py+agent_card.json. - Implement
/health,/.well-known/agent.json,/a2a/task. - Add to
AGENTS+CAPSin orchestrator. - Example capability:
"foo_scan".
Performance Notes
- 4× faster vs sequential due to parallel fan-out.
- Partial results even if some agents fail.
- Timeout: 30s per agent (configurable).
Security Notes
- Demo-only simulated scanners.
- Replace with real scanners carefully.
- Sandbox inputs for production.
FAQ
Q: Why do I see "Some agents had issues"?
A: One agent returned 500. Check directly via /health.
Q: Why already_running?
A: Loop is already active. Stop first, then restart.
Built With
- a2a/adk
- async
- cloud
- fastapi
- http
- javascript
- jsonschema
- loop
- monitoring
- powershell
- pydantic
- uvicorn
- vanilla
- windows


Log in or sign up for Devpost to join the conversation.