Inspiration
Anyone who's worked on a film or TV set knows the scene: an assistant director juggling five group texts, a weather app, a permit PDF, and a walkie, trying to make a go/no-go call before the crew stands around burning daylight (and budget). Production delays routinely cost tens of thousands of dollars a day, and the "system" for catching risk early is usually just one very stressed person's short-term memory.
We wanted to see how far an agentic AI loop could go toward automating that triage — not replacing the AD's judgment, but giving them a live, always-on second set of eyes that never gets distracted mid-shoot.
What it does
Green Light is a real-time production risk dashboard. It simulates a stream of shoot-day events — weather risk, crew delays, permit expirations, equipment faults, and all-clear checks — and feeds each one to an AI agent that classifies it as green, yellow, or red with a one-sentence, plain-English reason an AD can act on immediately.
The dashboard polls for new verdicts every few seconds and prepends color-coded cards to a live feed, so a viewer can watch the whole loop — event in, verdict out, dashboard updated — play out with no manual refresh.
How we built it Event producer (producer/): publishes five-plus rotating mock scenarios to a Kafka topic (shoot-day-events) every 10–15 seconds, using confluent-kafka against a local KRaft-mode Kafka broker (no Zookeeper). AI agent (agent/): built on Google's Agent Development Kit (ADK), running on Gemini. It consumes each event and returns a structured verdict — risk level plus reasoning — as strict JSON. API layer (api/): a FastAPI service exposing GET /latest-risk, with the agent runner running as a background asyncio task in the same process — no separate services, no IPC. Frontend (frontend/): a single dependency-free HTML file that polls the API and renders the live, color-coded event feed. Dual-mode runtime: since Cloud Run can't host a persistent Kafka sidecar, we built a second GREENLIGHT_MODE=demo path that drives the same agent loop from an in-process scenario list instead of Kafka — so the exact same Docker image runs locally against real Kafka for development, and standalone on Cloud Run for the public demo, with one env var flipping the mode. IBM Bob drove the development process end-to-end, working from written specs for each component (producer, agent, API, frontend, deployment) before any code was generated. Challenges we ran into
The dual-mode architecture looked simple on paper but surfaced two real bugs only visible once we actually ran the thing end-to-end:
The dashboard never rendered anything. The agent's JSON reply only ever contained event_type, risk_level, and reasoning — but the frontend deduplicates and keys every card off verdict.timestamp. Since that field was never attached to the stored verdict, every single update was silently dropped by the frontend's dedup guard, forever. We fixed it by merging the source event's timestamp, detail, and severity_hint back into the verdict before it's stored — closing the loop the API spec had actually promised all along. Demo mode broke on environments with a broken confluent-kafka install (we hit this ourselves on Python 3.14, which doesn't yet have prebuilt wheels for that package). Demo mode is explicitly designed to never touch Kafka — but it reused scenario data from the producer module, which imported confluent_kafka at the top of the file. That single import statement meant demo mode could crash even though it never actually used Kafka. Moving the import inside the function that actually needs it fixed the coupling.
We also had to catch a subtler deployment bug: the frontend was hardcoded to http://127.0.0.1:8000, which works great locally but silently breaks the moment the app is deployed to a real public URL on Cloud Run (different host, different port, HTTPS). Switching to a same-origin relative fetch (/latest-risk) fixed it for both environments with one line.
Accomplishments that we're proud of A genuinely complete agentic loop — event, reasoning, verdict, live UI — running end-to-end with no manual steps. One Docker image, one codebase, two runtime modes: real Kafka locally, zero-dependency demo mode in production, selected by a single environment variable. A frontend with zero external dependencies and zero build step, yet with real production concerns handled: XSS-safe rendering, in-flight request guarding, DOM growth caps, and graceful 503/network-error states. Catching and fixing cross-component bugs (the missing-timestamp bug spanned the agent, the API contract, and the frontend) that only showed up once the whole system was run together, not in any single file's spec. What we learned
Specs that look complete in isolation can still disagree with each other once wired together — the agent's spec defined a 3-field verdict, while the API spec (written slightly later) promised 6 fields to the frontend, and nothing forced the two to reconcile until we actually ran the app. Running the full loop early, and treating "does the dashboard actually render a card" as the real acceptance test rather than "does each file compile," is what surfaced the bugs that mattered.
We also relearned a classic Python lesson: a module-level import can silently couple two features that have no real reason to depend on each other. Demo mode's only sin was importing a file that happened to also import Kafka — moving that import inside the function that needs it was a one-line fix with an outsized effect on reliability.
What's next for GreenLight A "Scheduling" agent that goes beyond flagging risk and proposes concrete contingency actions (reschedule this block, notify these departments). A "Reporting" agent for on-demand end-of-day summaries an AD could send straight to production. Multi-production support so a studio running several shoots at once gets one dashboard instead of one deployment per production. Historical trend view — was today's risk pattern normal for this location/season, or a genuine outlier worth escalating? A manual "inject event" button for live demos and for ADs who want to log a real-world signal the automated stream hasn't picked up yet.
Log in or sign up for Devpost to join the conversation.