Policy-governed intelligence for decisions that need proof.
Take organizational rules, retrieve the authoritative version, enforce constraints, and only then let AI answer.
Live Demo | Overview | Demo | Architecture | Run Locally | Deployment
Deployed CANON: canon.devayushrout.me
CANON is a governance-gated policy intelligence system for teams that need internal policy answers with traceable evidence. It does not treat the model as the source of truth. Instead, it treats approved policy documents as the canonical authority and uses the model only after routing, retrieval, and governance checks have already narrowed the answer space.
The system is designed for organizational policy workflows where a generic chatbot would be risky: refund rules, access controls, support exceptions, security escalation, compliance-sensitive procedures, and versioned operating policies.
The current production path is a Vite + React 19 + TanStack frontend calling a Python API for policy intelligence. Groq handles classification/generation and Gemini handles embeddings from the Python layer. The repository has been cleaned so only the active frontend, Python API, policy corpus, docs, and evaluation tooling remain.
CANON can currently answer from the included markdown policy corpus, return sources and supporting clauses, refuse invalid or policy-disallowed requests, and escalate sensitive cases. It is still a project/demo system, not a substitute for legal, compliance, or human policy approval.
Live production demo: canon.devayushrout.me
Question
-> intent detection
-> owner routing
-> Gemini embedding
-> policy retrieval
-> governance verdict
-> source-backed answer or refusal
Example query:
Can support override the refund deadline?
Example response shape:
{
"status": "SAFE",
"verdict": "SAFE",
"answer": "The answer is generated only from retrieved policy clauses.",
"sources": ["data/raw_docs/policies/billing_and_refund_policy_v2.md"],
"supporting_clauses": ["Relevant policy text used by the answer."],
"confidence": "high",
"context_used": 5,
"hallucination_detected": false
}| Area | Current State |
|---|---|
| Frontend | React 19, TypeScript, TanStack Start-ready Vite app, TanStack Router, TanStack Query |
| UI | Tailwind CSS v4, Radix UI primitives, shadcn-style components, Lucide icons |
| API | Python FastAPI endpoint at POST /api/query |
| AI Layer | Python calls Groq chat completions and Gemini embeddings |
| Retrieval | Python retrieval over static JSON embeddings, with lexical local fallback |
| Data | Markdown policy documents under data/raw_docs |
| Deployment | Vercel production at canon.devayushrout.me |
| Status | Portfolio-grade MVP with deterministic governance gates |
- Policy-first answers: every answer is grounded in approved internal documents.
- Owner-scoped retrieval: queries are routed to Finance, Operations, Security, or Support before evidence is used.
- Version-aware evidence: latest policy versions win over stale source documents.
- Explicit governance verdicts: responses are classified as
SAFE,REFUSE_POLICY,REFUSE_INVALID, orESCALATE. - Source-backed output: answers include source paths, supporting clauses, confidence, and grounding status.
- No Node AI backend: Node is used only for frontend tooling; the intelligence runtime is Python.
Browser
-> Vite React UI
-> TanStack Query mutation
-> Python POST /api/query
-> Python Groq intent detection
-> deterministic owner routing
-> Python Gemini query embedding
-> cosine retrieval over data/search-index.json
-> owner/latest-version constraints
-> Python Groq governance classification
-> Python Groq answer or refusal generation
-> lexical grounding check
-> JSON response
The architecture is shaped around one rule: the model should not get to answer until the system has decided which policy owner applies, which documents are authoritative, whether the request is allowed, and whether the final answer stays close to the retrieved evidence.
Read the full architecture notes in docs/ARCHITECTURE.md.
| Layer | Tools |
|---|---|
| UI | React 19, TypeScript, Tailwind CSS v4 |
| Routing | TanStack Router |
| Data Fetching | TanStack React Query |
| Components | Radix UI primitives, shadcn-style local components |
| Charts/Icons | Recharts, Lucide React |
| Build | Vite with TanStack Start package alignment |
| API | Python FastAPI |
| Classification | Python calling Groq chat completions |
| Generation | Python calling Groq chat completions |
| Embeddings | Python calling Gemini Embedding API |
| Retrieval | Python static JSON index, cosine similarity, lexical fallback |
| Source Data | Markdown policy documents |
| Deploy | Vercel static frontend plus Python serverless function |
CANON exists because policy Q&A should not behave like an unconstrained chatbot. The system separates the decision path into explicit stages: detect what the user is asking, scope the policy owners, retrieve authoritative documents, apply governance rules, generate only from retrieved evidence, and return an answer with sources.
The current implementation keeps the browser app light and pushes the intelligence runtime into Python. Embeddings are generated through Gemini, model reasoning runs through Groq, and retrieval uses a static JSON index plus deterministic fallbacks so the project remains understandable and deployable.
Clone the repository:
git clone https://github.com/ayushcodes13/canon.git
cd canonInstall dependencies:
pnpm install
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtCreate a local environment file:
cp .env.example .env.localBuild the retrieval index:
pnpm run build:indexStart the Python API:
pnpm run dev:apiStart the frontend in another terminal:
pnpm run devThen open the local Vite URL printed by the dev server.
GROQ_API_KEY=
GEMINI_API_KEY=
GROQ_MODEL=llama-3.3-70b-versatile
GEMINI_EMBEDDING_MODEL=gemini-embedding-001
VITE_API_BASE_URL=Never commit real secrets. Keep .env.local untracked and configure production secrets directly in the hosting provider.
frontend/
index.html
src/
components/ui/
lib/
screens/
sections/
main.tsx
router.tsx
styles.css
api/
index.py
main.py
pipeline.py
build_search_index.py
data/
raw_docs/
search-index.json
docs/
ARCHITECTURE.md
DOMAINS.md
assets/
- Use the requested frontend stack: React 19, TypeScript, TanStack Router, TanStack Query, Vite, Tailwind v4, Radix-style UI, Lucide icons, and Recharts now own the browser app.
- Keep AI in Python: intent detection, retrieval, governance, generation, and grounding are all behind
api/main.py. - Use hosted embeddings: Gemini embeddings keep the production index path lightweight and deployment-friendly.
- Keep retrieval simple: the document set is small, so a static JSON vector index is easy to build, inspect, and deploy.
- Gate before generation: governance classification happens before answer generation, not after.
- Expose uncertainty: confidence, grounding warnings, context count, and sources are part of the response contract.
- Remove inactive surfaces: retired demo code and unused binary indexes are kept out of the production repository so future work starts from the active architecture.
- The best results require valid Groq and Gemini API keys.
- Without keys, the Python API uses deterministic local fallback logic for development only.
- The current index is generated from local markdown files, not a live document management system.
- There is no authentication or role-based access control yet.
- The grounding check is lexical and lightweight, not a formal proof system.
- It is a portfolio-grade MVP and still needs security review before real organizational use.
- Add a persistent document ingestion dashboard.
- Add authentication and role-aware policy access.
- Add policy owner approval workflows.
- Add richer evaluation tests for refusals, escalations, and grounding.
- Add durable production logging for audit trails.
- Keep the public Vercel demo and custom domain current with releases.
- Add a clean free subdomain such as
canon-policy.pages.devorcanon.is-a.dev.
Live production deployment:
https://canon.devayushrout.me
CANON is configured for a single Vercel project. Vercel builds the Vite frontend, generates the Gemini embedding index during deployment, and routes /api/* to the Python FastAPI app through api/index.py.
For local frontend-only verification:
pnpm run buildFor Vercel production builds:
pnpm run build:vercelRun the Python API locally:
python3 -m uvicorn api.main:app --host 0.0.0.0 --port 8000On Vercel, set GROQ_API_KEY and GEMINI_API_KEY before deploying. GEMINI_API_KEY is required to generate the semantic retrieval index; without it, the build skips index generation and the API falls back to lexical retrieval. VITE_API_BASE_URL can stay unset for same-origin Vercel deployment because the frontend calls /api/query.
This project is released under the Apache License 2.0. See LICENSE.




