Every public company's story is hiding in plain sight β in 10-Ks and 10-Qs that
almost nobody reads end-to-end. The good stuff is specific: a gross margin
inflecting, risk-factor language that wasn't there last quarter, a going-concern
sentence buried on page 60. I wanted that surfaced to me every morning without
me doing the reading.
So for the All Things Agentic Hackathon I built EDGAR Sentinel: an
autonomous agent on Google Cloud that wakes up at 6:30 every morning, scans SEC
EDGAR for new filings across a 30-company watchlist, reads them with a
two-model pipeline, remembers every prior filing, and emails me what changed β
with a public dashboard for everything it knows.
Cloud Scheduler β Cloud Run Job β an ADK orchestrator agent (Gemini 3.5)
whose tools are the pipeline stages β SEC EDGAR (politely: declared User-Agent,
throttled) β raw filings archived to Cloud Storage β a section parser β
Gemma (on its own Cloud Run service, via Ollama) writes triage notes β
Gemini 3.5 on Vertex AI scores the filing against a five-pillar "Filing
Health Score" with schema-enforced JSON β Firestore stores it β a delta engine compares against the company's prior filing and fires deterministic
One design rule shaped everything: agentic control flow, deterministic execution. The LLM decides
Gemini 3.5 Flash does the deep reading: five pillar scores with cited
rationale, extracted metrics, three decision-relevant highlights. Temperature
zero, pydantic schema enforced, composite recomputed in code so config β not
the model's arithmetic β is authoritative.
Gemma's job is deliberately smaller: read the risk-factors section and produce
a dozen terse triage bullets β red flags, notable changes, tone β that ride
along to Gemini as a second opinion. It runs scale-to-zero on CPU. My first
design had Gemma rewriting filing text; that was wrong in an instructive way
(below).
done_reason: length
β the model spent its whole output budget on
hidden reasoning and never wrote the answer. One think: false
later,
33-second useful triage notes.RIS K FACTORS
, and repeats "Item 1A" as a page header through the whole section β my "take the last heading match" heuristic found nothing. Fix: match headings with optional intra-word whitespace and take
the match with the make_client().models.generate_content(...)
) let the client get
garbage-collected mid-request; its finalizer closed the HTTP pool:
Cannot send a request, as the client has been closed.
Cached singleton.constraints/vertexai.allowedModels
) and strips default service-account grants β both showed up as cryptic 400s/403s. Both fixed with scoped, least-privilege IAM rather than hammer-sized grants.Every one of these would have detonated during a live demo. Finding them on day
one and day four instead is most of what "production-minded" means.
The delta engine is the feature I'd defend in a knife fight. Because every
analysis persists in Firestore, each new filing is compared with the company's
prior one β pillar by pillar β and a deterministic rule (β₯10-point move, band
change, or risk-pillar collapse) decides whether to alert. On the full
backfill it flagged, among others: Plug Power sliding Caution β Distress
(cash down to $161.9M), Salesforce and Meta dropping out of Strong, and
Coinbase and AMC genuinely recovering. It also caught Apple's management going
cautious on component costs a quarter before it showed up anywhere else in the
filing β a 10-point management-signal drop while the composite barely moved.
30 companies Β· 58 filings analyzed Β· 8 live alerts Β· running unattended every
morning since August 14 Β· ~1 minute per filing Β· 20 unit tests Β· roughly a
dollar a day in cloud costs while idle-scaling to zero.
One last production note: even the demo video is Google AI β narration by
Cloud Text-to-Speech (Chirp3-HD), soundtrack generated with Lyria 2 on Vertex AI, and the screen captured while the real daily job ran live on
Cloud Run.
I created this piece of content for the purposes of entering the All Things Agentic Hackathon. EDGAR Sentinel produces automated research summaries