A source-grounded legislative intelligence platform for US federal legislation.
PoliScope is a full-stack transparency explorer powered by a LangGraph-based Retrieval-Augmented Generation (RAG) orchestrator. The frontend (Vite + React + shadcn/ui) streams orchestrated answers, ranked bill cards, and influence overlays. The backend (Express + LangGraph) executes a multi-tool workflow that calls the Congress.gov, GovInfo, Senate LDA, and OpenFEC APIs to ground every response in primary-source data.
Every answer traces back to a primary government source. The orchestrator is explicitly constrained to descriptive output: a guardrail node blocks advisory or persuasive language, so the system reports what legislation says and who influenced it, rather than arguing a position.
Origin: Built as a hackathon project at HackHarvard 2025 (October 2025). The
hackathon-demotag marks the state submitted for judging; later commits are post-hackathon cleanup. See contributors for the full commit record.
Implemented and functional (given API keys):
- Bill search and retrieval over Congress.gov, with pagination and calibrated confidence scoring.
- "Policy DNA" version tracking — downloads GovInfo XML/HTML across bill versions and
computes textual deltas via
diff-match-patch. - Influence lookup — Senate LDA lobbying disclosures and OpenFEC campaign-finance totals, mapped to bill sponsors.
- Grounded answer composition through Vertex AI Gemini, with inline citations.
- Guardrail enforcement combining regex detection with model-based validation.
- Graceful degradation — missing credentials produce deterministic summaries and explanatory notes in the UI rather than failures.
Not implemented — these are architectural proposals, described under Extending the RAG System: a vector + BM25 hybrid store, Vertex embedding/reranking, Cloud Logging observability, a Firestore session store, and a Neo4j graph backend.
- Retrieval currently queries the Congress.gov API directly; there is no vector index, so recall depends on that API's own search behaviour.
- Test coverage is limited to lint, build verification, and manual API smoke tests. There is no automated test suite against fixture data.
- Data coverage follows the upstream APIs — lobbying and finance records are only as complete and current as Senate LDA and OpenFEC publish them.
Web Client (Vite/React)
↓ HTTPS
API Gateway / Express (server/index.ts)
↓ LangGraph StateGraph (server/orchestrator.ts)
├─ policy-search → Congress.gov bill search + summaries
├─ policy-dna → GovInfo text downloads + diff-match-patch
├─ influence-lookup → Senate LDA + OpenFEC lookups
├─ answer-grounder → Gemini-backed response composer
└─ guardrail → Moderation + style enforcement
- LangGraph StateGraph: normalizes the query, performs hybrid policy search, builds a version timeline (“DNA”), aggregates lobbying & finance data, and grounds the final answer with citations before running style guardrails.
- Express service: exposes
/api/chatfor conversational answers and/api/policy/:billIdfor direct transparency views. A health probe lives at/healthfor Cloud Run readiness. - React experience:
src/pages/Chat.tsxconsumes the orchestrator, renders citations inline, and surfaces orchestrator logs.src/pages/TransparencyGraph.tsxhydrates the timeline, blame view, influence overlay, and action history from live API responses.
-
Install dependencies
npm install
-
Provide environment variables (use
.envlocally, or Cloud Run secrets):Variable Required Description CONGRESS_API_KEY✅ API key for Congress.gov. Needed for policy search and bill metadata. CONGRESS_API_BASE_URLoptional Override the default https://api.congress.gov/v3endpoint if using a proxy.CONGRESS_PAGE_SIZEoptional Page size used when crawling Congress.gov search (defaults to 50). CONGRESS_MAX_RESULTSoptional Maximum number of Congress.gov hits to aggregate per query (defaults to 200). CONGRESS_MAX_PAGESoptional Upper bound on paginated requests for a single query (defaults to 6). FEC_API_KEY✅ Key for OpenFEC. Enables sponsor finance totals. FEC_API_BASE_URLoptional Override FEC base URL (defaults to https://api.open.fec.gov/v1).LDA_API_BASE_URLoptional Override Senate LDA base URL (defaults to https://lda.senate.gov/api/v1).GOOGLE_APPLICATION_CREDENTIALS✅ Path to the service-account JSON that can access Vertex AI. VERTEX_PROJECT_ID✅ Google Cloud project hosting Vertex AI resources. VERTEX_LOCATIONoptional Vertex AI region (defaults to us-central1).VERTEX_GEMINI_MODELoptional Gemini model name for answer/guardrail calls (defaults to gemini-1.5-flash).PORToptional Port for the orchestrator service ( 8787by default).GovInfo text downloads do not require an additional key for enrolled USLM XML.
-
Check your credentials
- Create a
.envfile with the variables above and ensure your Google service-account JSON path is accessible. - Run
npm run dev:orchestratoronce—the server will log which required keys are missing before it boots so you can correct them.
- Create a
-
Run the orchestrator service
npm run dev:orchestrator
-
Start the client (in a new terminal)
npm run dev
-
Navigate to
http://localhost:5173and chat. The client targetshttp://localhost:8787unlessVITE_API_BASE_URLis set.
Follow this quick smoke test after the services start:
- Verify the orchestrator health endpoint:
curl http://localhost:8787/health
- Issue a sample chat request (replace the message with your query):
curl -X POST http://localhost:8787/api/chat \ -H 'Content-Type: application/json' \ -d '{"message":"What is H.R. 5376?"}'
- Open the web client at
http://localhost:5173and send the same prompt. You should see bill cards, an answer with citations, and the environment log panel at the bottom of the chat.
- Build two services: one Cloud Run instance for the orchestrator (
npm run dev:orchestratorbuild) and one for the static client (npm run build→ deploy via Cloud Run or Cloud Storage + CDN). - Configure required secrets via
CONGRESS_API_KEY,FEC_API_KEY, etc. Cloud Run automatically injectsPORT. - Attach API Gateway or Cloud Endpoints in front of the Express service if you need unified auth.
- LangGraph workflow (
server/orchestrator.ts): usesAnnotation.Rootto define shared state (policies,dna,influence,answer,guardrailResult,logs). Nodes run sequentially with clear log breadcrumbs. - Tooling:
policy-search(server/tools/policySearch.ts) normalizes bill identifiers, paginates through Congress.gov (up to 200 hits by default), and returns top sections/snippets with calibrated confidence scores.policy-dna(server/tools/policyDna.ts) fetches version metadata, downloads GovInfo XML/HTML, calculates change deltas viadiff-match-patch, and synthesizes clause attributions from amendments, section-by-section notes, or timeline changes when explicit data is missing.influence-lookup(server/tools/influenceLookup.ts) fans out across multiple Senate LDA search terms, maps sponsors to FEC committees for finance totals, and surfaces the search terms/notes used for transparency.answer-grounder(server/tools/answerGrounder.ts) composes strictly descriptive responses with citation tuples through Vertex AI Gemini, with deterministic fallbacks when credentials are unavailable.guardrail(server/tools/guardrail.ts) combines regex detection with Gemini-powered validations to block advisory language or unsafe content.
- React integration:
Chat.tsxuses React Query to mutate conversations, streams results, shows citations with inline hyperlinks, and surfaces guardrail warnings + orchestrator logs.TransparencyGraph.tsxlazily fetches DNA/influence data, wiresVersionTimeline,BlameView,InfluenceOverlay,HistoryPanel, and the in-contextPolicyChatPanelso users can interrogate the focused bill without leaving the transparency view.
To reach production parity with the GCP-first reference architecture, add the following:
- Vector + BM25 store: provision Cloud SQL (Postgres) with
pgvector+tsvectorindexes. Replace the direct Congress.gov search with ingestion jobs that hydrate these tables, then updatepolicy-searchto query your hybrid index (optionally re-rank with Vertex AI). Export connection strings viaDATABASE_URL. - Embeddings & reranking: integrate Vertex AI (
text-embedding-005and Gemini Flash) by injectingGOOGLE_APPLICATION_CREDENTIALS,VERTEX_PROJECT_ID,VERTEX_LOCATION. Replace heuristic scoring with true hybrid retrieval + Vertex rerank. - Observability: forward orchestrator logs to Cloud Logging (use
@google-cloud/logging) and add Cloud Trace spans around each tool call. - Firestore session store: persist chat history/filters so
/api/chatcan resume multi-turn context. - Neo4j Aura graph: extend
policy-dnato upsert nodes/edges and expose a/api/graphendpoint to power richer network views.
npm run lint– static analysis of the frontend code.npm run build– verifies the client builds successfully.- API smoke tests –
curl http://localhost:8787/healthandcurl -X POST http://localhost:8787/api/chat -d '{"message":"ACA"}'(with keys configured).
- The orchestrator intentionally degrades gracefully: missing keys or empty lookups surface explanatory notes in the UI. If Vertex credentials are absent the answer-grounder reverts to deterministic summaries and the guardrail relies on regex heuristics.
- All APIs are invoked with strict JSON contracts so the system can scale to Cloud Run Jobs or Workflows for scheduled ingestion.
- Guardrails enforce descriptive, non-advisory tone; extend the regex patterns or integrate a hosted moderation endpoint as needed.