Inspiration

I'm a junior recruiting for both PM and SWE roles, and I watched a friend accept an offer from a company that announced mass layoffs three weeks later. She had no idea. I started wondering, how many people sign offers without knowing the company is about to restructure, freeze hiring, or go bankrupt? The information exists. It's just scattered across Glassdoor, news articles, SEC filings, and LinkedIn, and nobody has time to piece it together before a deadline.

Canary is what I wished existed when I was evaluating my own offers.

What it does

Canary is a job offer intelligence platform that analyzes any company for job seekers, surfacing hiring signals, layoff history, funding status, and leadership stability so you can negotiate smarter and protect yourself before signing.

You enter a company name and your stage (applying, interviewing, or got the offer). Canary returns:

  • A risk score from 1 to 5 across three classifications: Stable, Caution, or Volatile
  • Four prioritized signals (layoff history, funding status, leadership stability, and hiring velocity) with a critical/watch/secondary hierarchy
  • A stage-aware playbook with specific negotiation tactics based on what Canary found
  • An Offer Risk verdict (Accept, Negotiate, or Walk Away) for every active offer
  • Compensation benchmarks for any role, with AI analysis of whether your specific offer is above, at, or below market

The pipeline tracks your entire job search: every company you're evaluating, at every stage, with auto-refresh every 30 minutes so signals stay current.

How I built it

Layer Technology
AI analysis Gemini 2.5 Flash via Vertex AI
Signal storage and retrieval Elastic Cloud Serverless (Elasticsearch)
MCP integration Elastic Agent Builder MCP server via Google ADK McpToolset
Backend Python + Flask
Frontend Vanilla HTML/CSS/JS
Deployment Google Cloud Run

The core flow: when a user submits a company, Flask calls Elasticsearch via the Elastic MCP server to retrieve any previously stored signals. Those signals are injected as context into a Gemini 2.5 Flash prompt alongside stage-specific instructions. Gemini returns a structured JSON risk assessment, which gets rendered in the dashboard and stored back to Elasticsearch, so every subsequent analysis of the same company is enriched by prior intelligence. This RAG pattern means Canary's signal memory compounds over time.

Challenges I ran into

Reliable structured output from an LLM. Getting Gemini to return consistent, parseable JSON across hundreds of different companies required significant prompt engineering: strict rules, worked examples, field-level constraints, and validation logic with fallbacks.

MCP integration. Connecting Google ADK's McpToolset to the Elastic Agent Builder MCP server required navigating sparse documentation and debugging authentication. The Google Cloud Agent Registry UI doesn't support custom MCP servers properly, so I connected programmatically via the ADK instead.

Signal hierarchy. Not all signals are equal. A layoff affecting 30% of headcount is more urgent than a leadership change. Building a visual priority system (Critical / Watch / Secondary) that's dynamically computed from signal types took several design iterations.

Deployment. Moving from Cloud Shell preview to a persistent Cloud Run URL surfaced file naming issues, IAM permission gaps, and service account configuration that needed debugging through build logs.

Accomplishments that I'm proud of

  • A fully working end-to-end product with real companies, real analysis, and real risk scores deployed at a stable public URL
  • Signal memory that compounds: the second time you analyze a company, Canary already knows its history
  • A visual hierarchy that makes the intelligence feel asymmetric and prioritized, the way real risk dashboards do
  • Role-agnostic compensation analysis: any job seeker, any role, any level
  • Shipping the full stack solo in under two weeks

What I learned

  • How to engineer prompts for structured, reliable JSON output from frontier models at scale
  • How Elastic's MCP server exposes Elasticsearch tools to AI agents, and how to connect it via Google ADK
  • How the RAG pattern applies beyond documents, using a live Elasticsearch index as a persistent agent memory layer
  • How to deploy a containerized Python app to Cloud Run with environment-variable-managed secrets
  • That the hardest part of AI products isn't the AI. It's making the output feel trustworthy and actionable to a real user

What's next for Canary

  • Real-time signal ingestion connecting to live news feeds, SEC EDGAR filings, and LinkedIn hiring data via Elastic connectors so signals reflect what happened this week, not just Gemini's training data
  • Offer comparison with side-by-side analysis when you have multiple offers and a recommendation on which to take
  • Recruiter cadence tracking to log interview rounds and response times to detect ghosting patterns early
  • Mobile app because job searching happens on the go and Canary should too
  • Team plan to share a pipeline with a friend or career coach so you're not navigating offers alone
Share this project:

Updates