Unified Engineering Intelligence Platform
A production-ready system that transforms scattered engineering data—pull requests, incident logs, architecture documents—into a structured knowledge graph, enabling engineers to query institutional knowledge conversationally while automatically enforcing architectural decisions on new code.
Engineering teams face two critical knowledge gaps:
- Architectural Amnesia: Design decisions live in old PRs, Slack threads, and senior engineers' heads. New developers repeat mistakes or interrupt seniors for answers.
- Operational Fragmentation: Runbooks, alerts, and incident playbooks spread across five tools. On-call engineers context-switch under pressure and miss architectural constraints.
DevContextIQ solves both with a unified system deployable on any GitHub-based engineering team.
| Feature | Benefit |
|---|---|
| Conversational Context Agent | Query architectural decisions and decisions in natural language—get sources, confidence scores, and related context in seconds |
| Governance Bot | Automatically catch architectural violations in PRs before merge—no human review needed |
| Incident Response Agent | Structured incident answers: issue summary, root cause hypothesis, numbered fix steps, and architectural warnings |
| Knowledge Graph | Nodes (decisions, files, people, incidents) + edges (supports, conflicts, supersedes) enable semantic reasoning |
| Vector Search | pgvector semantic search finds relevant decisions even when exact keywords don't match |
Five-layer stack built entirely on free and open-source tools:
Layer 5: Frontend (React + Vite on Vercel)
↓
Layer 4: Agent Backend (FastAPI on Render)
↓
Layer 3: LLM Orchestration (Gemini API)
↓
Layer 2: Vector + Graph DB (Supabase + pgvector)
↓
Layer 1: Data Ingestion (GitHub Actions)
- Database: Supabase (PostgreSQL) + pgvector (semantic search)
- Backend: FastAPI (Python) on Render
- Frontend: React with Vite on Vercel
- LLM: Google Gemini (text-embedding-004 for vectors, Gemini 2.0 Flash for agents)
- Ingestion: GitHub Actions + Python scripts
- Auth: Supabase + Google OAuth 2.0
Zero paid services required. All tiers are free for development and demo use.
- GitHub repository
- Google account (for AI Studio)
- 30 minutes
# Navigate to Supabase dashboard → SQL Editor → New Query
# Paste contents of schema.sql and executeThe schema creates:
nodes: knowledge graph entities (decisions, files, people, incidents, ADRs)edges: relationships (supports, conflicts, caused_by, supersedes)node_embeddings: 768-dim vectors from Gemini text-embedding-004 with pgvector HNSW index
Create .env in the agents/ directory:
GEMINI_API_KEY=your_key_here
SUPABASE_URL=your_project.supabase.co
SUPABASE_ANON_KEY=your_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_service_key
RENDER_DEPLOYMENT_URL=https://your-app.onrender.compip install -r agents/requirements.txt
uvicorn agents.main:app --reload --port 8000API available at http://localhost:8000
cd frontend/
npm install
npm run devVisit http://localhost:5173 to access the chat interface.
All responses include sources array with links to original PRs, ADRs, and incidents.
Context Agent — Answer architectural questions
curl -X POST http://localhost:8000/api/v1/ask \
-H "Content-Type: application/json" \
-d '{
"question": "Why is rate limiting at the API gateway?",
"repo_id": "org/repo-name"
}'Response:
{
"answer": "Rate limiting is at the API gateway to prevent DB connection saturation — decision made after INC-0089 in August 2025.",
"sources": [
{ "type": "pr", "label": "PR #245", "url": "github.com/.../pull/245" },
{ "type": "adr", "label": "ADR-003", "url": "..." },
{ "type": "incident", "label": "INC-0089", "url": "..." }
],
"confidence": 0.91
}Governance Bot — Detect architectural conflicts in PRs
Integrated into GitHub Actions. Automatically runs on new PRs. Returns:
- Conflicting decisions with links
- Suggested comment for PR
- Safe-to-merge boolean
Incident Agent — Structured incident response
curl -X POST http://localhost:8000/api/v1/incident \
-H "Content-Type: application/json" \
-d '{
"alert_title": "Payment service error rate spike",
"service_name": "payments",
"error_snippet": "Too many connections to DB pool — max 100 exceeded"
}'Response:
{
"issue": "DB connection pool exhausted on payment service",
"likely_cause": "Rate limiting missing on /payments/process endpoint",
"fix_steps": [
"1. Enable gateway rate limiting for /payments route",
"2. Restart payment service pods",
"3. Monitor DB connection count"
],
"warnings": ["Do NOT move rate limiting into the service — see ADR-003"],
"runbook_url": "confluence.../runbook-payments"
}Health check endpoint.
Triggered on PR merge. Workflow file: .github/workflows/ingest.yml
# Extracts PR diff, title, author, date
# Calls Gemini Flash to extract decisions
# Writes nodes + edges to Supabase
# Generates embeddings via text-embedding-004For non-GitHub sources (runbooks, ADRs, incident reports):
from ingestion.embed import ingest_document
ingest_document(
content="Rate limiting prevents DB saturation...",
doc_type="adr",
metadata={
"adr_id": "ADR-003",
"date": "2025-08-14",
"author": "rahul@company.com"
}
)id UUID -- primary key
type TEXT -- 'decision' | 'file' | 'person' | 'incident' | 'adr'
label TEXT -- human-readable label
metadata JSONB -- flexible attributes
source_url TEXT -- GitHub PR, Confluence link, etc.
created_at TIMESTAMPTZ -- auto-populatedfrom_node_id UUID -- source node
to_node_id UUID -- target node
relation TEXT -- 'supports' | 'conflicts' | 'caused_by' | 'supersedes'
created_at TIMESTAMPTZnode_id UUID
chunk TEXT -- text passage that was embedded
embedding vector(768) -- 768-dim vector from GeminiVector Search Example:
SELECT n.id, n.label, (1 - (ne.embedding <=> $1::vector)) AS similarity
FROM node_embeddings ne
JOIN nodes n ON n.id = ne.node_id
ORDER BY ne.embedding <=> $1::vector
LIMIT 5;devcontextiq/
├── ingestion/
│ ├── ingest_pr.py # GitHub PR → Gemini extraction → Supabase
│ ├── embed.py # Text → Gemini embeddings → pgvector
│ └── requirements.txt
│
├── agents/
│ ├── main.py # FastAPI entry point
│ ├── context_agent.py # POST /ask handler
│ ├── governance_agent.py # POST /governance/check handler
│ ├── incident_agent.py # POST /incident handler
│ ├── tools.py # Gemini function-calling tools
│ ├── db.py # Supabase queries
│ └── requirements.txt
│
├── frontend/
│ ├── src/
│ │ ├── App.tsx
│ │ ├── Chat.tsx # Chat UI component
│ │ └── api.ts # API client
│ ├── vite.config.ts
│ └── package.json
│
├── .github/workflows/
│ ├── ingest.yml # Triggered on PR merge
│ └── governance.yml # Runs on new PRs
│
├── schema.sql # PostgreSQL schema + pgvector setup
├── seed_data.sql # Demo data
└── README.md
- Push
agents/folder to GitHub - Create new Web Service on Render
- Connect GitHub repo
- Set runtime to Python 3.11
- Build:
pip install -r requirements.txt - Start:
uvicorn main:app --host 0.0.0.0 --port $PORT - Add env vars:
GEMINI_API_KEY,SUPABASE_URL,SUPABASE_ANON_KEY
Note: Free tier spins down after 15 minutes. Use UptimeRobot (free) to keep alive during presentation.
- Push
frontend/folder to GitHub - Create new Vercel project from GitHub repo
- Framework preset: Vite
- Add env vars:
VITE_SUPABASE_URL,VITE_SUPABASE_ANON_KEY,VITE_API_BASE - Deploy
Auto-deploys on push to main.
Query: "Why is rate limiting at the gateway?" Result: Answer + links to PR #245, ADR-003, and the incident that triggered the decision.
PR opens with rate limiting changes. GitHub bot comment: "This conflicts with ADR-003. See PR #245 for the original decision."
Alert: Payment service error spike. Query: "DB connections exhausted—what do I do?" Result: Issue summary, likely cause, numbered steps, architectural warnings.
- Semantic search: <200ms (pgvector HNSW index)
- Agent response: 1–3s (Gemini function calling)
- PR ingestion: 30–60s (Gemini extraction + embedding)
- Concurrent users: 750 hrs/month free Render tier sufficient for 5–10 daily users
| Feature | Status | Reason |
|---|---|---|
| Temporal reasoning | Not implemented | Scope |
| Multi-repo graphs | Partial | Requires repo_id parameter per query |
| Role-based access control | Not implemented | Supabase RLS can be added |
| Batch PR ingestion | Not implemented | Use GitHub Actions cron job for weekly backfill |
| PII redaction | Not implemented | Add filtering in embed.py if needed |
- Fork repository
- Create feature branch
- Test locally with
.envfile - Push to GitHub
- Open PR with description of change
MIT
Built for Google Build for AI Hackathon, April 2026.
API returns 401 Unauthorized
- Check Supabase JWT in Authorization header
- Verify SUPABASE_ANON_KEY matches
.env
Vector search returns no results
- Confirm pgvector extension is enabled:
SELECT extname FROM pg_extension; - Check node_embeddings table is populated:
SELECT count(*) FROM node_embeddings; - Verify HNSW index exists:
SELECT indexname FROM pg_indexes WHERE tablename = 'node_embeddings';
Frontend can't reach backend
- Confirm frontend env uses
VITE_API_BASE_URL - For local UI development, point to the agents API service (
agents.main) - Keep webhook ingestion service separate (
ingestion.github_webhook) - Confirm CORS allows:
http://localhost:5173http://127.0.0.1:5173
Render service spins down
- Free tier auto-hibernates after 15 min of inactivity
- Use UptimeRobot (free) to ping
/healthendpoint every 10 min
Gemini API returns rate limit error
- Free tier: 60 requests per minute
- Add exponential backoff retry logic in agents
- For fallback we've used OpenRouter
Use backend for UI routes (/api/v1/health, /api/v1/ask, /api/v1/governance/check, /api/v1/incident):
uvicorn agents.main:app --reload --port 8000Use webhook service separately (GitHub ingestion only):
uvicorn ingestion.github_webhook:app --reload --port 8001If port 8000 is already occupied, run agents on 8001 (or another free port) and update:
VITE_API_BASE_URL=http://127.0.0.1:8001