Inspiration
Security teams get flooded with alerts every day — most are noise, but a few are genuine threats, and sorting them manually burns hours that could go toward real incident response. I wanted to build an agent that doesn't just chat about security alerts, but actually makes a judgment call and takes action on them autonomously, the way a junior analyst on triage duty would.
What it does
The agent ingests a stream of security alerts (SSH brute-force attempts, anomalous logins, port scans, privilege escalation attempts, and suspected data exfiltration) and for each one:
- Classifies it as low-risk or high-risk using Gemini
- Auto-remediates clearly benign activity (e.g. blocklists an IP, closes the alert) without waiting for a human
- Escalates ambiguous or dangerous activity with a drafted incident summary and severity level, ready for a human analyst to act on immediately
- Persists every decision to an audit trail, so the reasoning behind each action is fully traceable afterward
It calls exactly one tool per alert — no double-handling, no skipped alerts — and it runs the same core logic whether triggered from a local loop or (in the cloud-deployed version) an asynchronous Pub/Sub push subscription.
How I built it
- Gemini (via the Gemini API) does the actual classification and reasoning for each alert
- Google ADK orchestrates the agent: the model, its instructions, and
two tools (
remediate_alert,escalate_alert) that it can call - The audit trail is written through a small storage layer that transparently switches between a local JSON file (for development) and Firestore (for the cloud-deployed version) via a single environment variable — the agent logic itself never changes between the two
- A separate FastAPI + Cloud Run entry point (
cloud_main.py) is built to receive alerts pushed from Pub/Sub, so the agent can run asynchronously in the background rather than on a fixed schedule
Challenges I ran into
- Iterating through Google Cloud billing/quota setup (free-tier request limits, prepay balances) while developing under a tight deadline
- The Gemini API occasionally returned transient
503 UNAVAILABLEerrors under high demand — I added an application-level retry-with-backoff layer around each alert so a temporary outage doesn't crash the whole run, which the agent demonstrated handling live during testing (visible in the included sample run output) - Balancing local development speed against the eventual cloud deployment path, which led to the store/entry-point split described above
Note on deployment
Due to a billing constraint outside the scope of the hackathon, this
project was fully built, tested, and validated locally (see
sample_run_output.txt and audit_trail.json in the repo for a complete
run across all 6 synthetic alerts), but was not deployed live to Cloud
Run/Pub/Sub/Firestore for this submission. The full cloud deployment code
(cloud_main.py, Dockerfile, deploy.sh) is complete and ready to run —
see the README's "Deploying to Google Cloud" section for exact,
reproducible steps.
What I learned
- How to structure an ADK agent so its core reasoning logic is fully decoupled from both its trigger source (local loop vs. Pub/Sub) and its storage backend (local file vs. Firestore) — a pattern that made the eventual cloud migration a near-zero-code-change process
- How to build resilience against upstream model availability issues rather than assuming every API call succeeds
What's next
- Complete the live Cloud Run deployment once billing is resolved
- Add a lightweight dashboard reading directly from the audit trail collection for a more visual, judge-friendly view of agent decisions
- Expand the synthetic alert set and tune the escalation instructions against a wider range of real-world alert types

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