Imported from rohan-chand-m-01/OpenComply (
AGENTS.md). Install upstream withnpx skills add rohan-chand-m-01/OpenComply. Copyright stays with the author.
AGENTS.md — OpenComply Commons
OpenComply Commons is the Apache-2.0, local-first, open-source compliance intelligence layer for Indian GST, TDS, payroll (PF, ESIC, PT) and labour-law rules.
Mission & Core Principles
| Principle | Detail |
|---|---|
| Evidence-first | The LLM proposes; the deterministic validator decides. Rates, thresholds, section numbers, and due dates must come from official sources with explicit citations — never hallucinated by the model. |
| Local-first privacy | Business documents and payroll data stay on the user's machine by default. Nothing is sent to an external API unless the operator explicitly enables the cloud fallback. |
| Immutable Rule Packs | Every versioned set of compliance rules is a content-addressed artifact stored under rulepacks/. Rule Packs are append-only; old packs are never deleted. |
| Offline-first | Core compliance evaluation (Rail B deterministic engine) runs fully offline. LLM assistance (Rail A) degrades gracefully when no model is reachable. |
| Local Gemma 4 is primary | Gemma 4 via Ollama / llama.cpp is the default LLM provider. Gemini API (gemini_client.py) and OpenRouter are opt-in fallbacks only. Business documents are never sent to a remote API by default. |
| No secrets in repo | All keys and URLs live in .env (git-ignored). Defaults in .env.example must be non-functional placeholders. |
| Human in the loop by default | Every autonomous decision starts as a draft and requires HITL approval before taking effect. The UI always shows: "Not tax advice. Verify with a Chartered Accountant." |
The 4 Real-World Accuracy Rules
-
Model never supplies legal values. Threshold amounts, tax rates, due dates, and section references must be fetched from official sources (Rule Packs, regulation corpus) with citations. The LLM may summarise, but must never invent numeric values.
-
Everything starts as a draft. All AI-generated compliance assessments enter the HITL queue (
services/agents/hitl/) with statuspending_review. The UI persists the disclaimer: "Not tax advice. Verify with a Chartered Accountant." -
Legal-reference aliases. The rule engine and RAG corpus maintain a mapping between old and new section numbering (e.g., Income-tax Act 1961 § 194C ↔ Income-tax Act 2025 § 194C, effective 1 April 2026). Alias tables live in
services/knowledge/rule_engine/section_aliases.py(create if absent). -
Never hard-code model tags. LLM model identifiers (
OLLAMA_MODEL,GEMINI_MODEL,GROQ_MODEL,OPENROUTER_MODEL) are configuration-only — set inservices/api/config.pyand.env.example. Code must read fromsettings.*exclusively.
Directory Mapping: Existing Repo → OpenComply Modules
OpenComply/ (repo root)
├── services/api/ → FastAPI backend (apps/api equivalent)
│ ├── main.py → App entry-point; health endpoints /health + /v1/health
│ ├── config.py → Central settings (ALL model IDs here, never in code)
│ ├── database.py → Async SQLAlchemy + ORM models
│ ├── routers/ → REST endpoints
│ │ ├── admin.py → Portal management, demo trigger, DPDP breach sim
│ │ ├── assistant.py → AI chat (DRCA-backed)
│ │ ├── audit.py → CAAL ledger read API
│ │ ├── compliance.py → Business compliance status
│ │ ├── demo.py → Demo scenario execution
│ │ ├── gst.py → GST filing + readiness
│ │ ├── hitl.py → HITL queue management
│ │ ├── knowledge.py → Graph + RAG stats
│ │ ├── obligations.py → Obligation CRUD
│ │ └── payroll.py → PF / ESI / PT / TDS compute
│ ├── middleware/
│ │ └── clerk_auth.py → JWT verification middleware
│ └── websocket/
│ └── retrigger_ws.py → WebSocket broadcast manager
│
├── apps/web/ → Next.js 14 App Router frontend
│ ├── app/(dashboard)/ → All dashboard pages
│ ├── components/ → Shared UI (DualRailBadge, ConfidenceScore, etc.)
│ ├── hooks/ → Custom React hooks (WebSocket, alerts, audit)
│ └── middleware.ts → Clerk auth route protection
│
├── apps/mock-portals/ → Local mock regulatory portals (offline demo)
│ ├── gstn/ → GSTN mock (also deployed: gstn-xi.vercel.app)
│ ├── epfo/ → EPFO mock (also deployed: epfo-coral.vercel.app)
│ ├── fssai/ → FSSAI mock (also deployed: fssai-nine.vercel.app)
│ └── pt-states/ → PT-States mock (also deployed: state-pt.vercel.app)
│
├── services/knowledge/ → Core Schema + Deterministic Engine (packages/core equivalent)
│ ├── obligation_graph/ → Obligation Knowledge Graph
│ │ ├── node_schema.py → ObligationNode + CrossDomainEdge dataclasses
│ │ ├── graph_builder.py → NetworkX DiGraph; build/query/cascade/delta
│ │ ├── versioner.py → Graph version history + delta tracking
│ │ └── cross_domain_edges.py → Cross-domain edge constants + propagation
│ └── rule_engine/ → Deterministic Rail-B engine (packages/core/validator)
│ ├── gst_rules.py → GST rate + due-date computation
│ ├── pf_rules.py → Provident Fund rules (wage ceiling, contribution %)
│ ├── esi_rules.py → ESI contribution rules
│ ├── pt_rules.py → Professional Tax state-wise slabs
│ ├── tds_rules.py → TDS section rates
│ └── __init__.py → RuleEngine.evaluate(query_type, params, portal_data)
│
├── services/knowledge/rag/ → Gemma 4 Provider Layer + Ingest (packages/llm + ingest)
│ ├── gemini_client.py → Gemini API client (FALLBACK ONLY — never default)
│ ├── groq_client.py → Groq client (legacy; replaced by local Gemma 4)
│ ├── embedder.py → Embedding pipeline (local-first; remote fallback)
│ ├── vector_store.py → ChromaDB persistent vector store
│ ├── retriever.py → Profile-aware domain filtering + context construction
│ └── regulation_corpus/
│ └── regulations.json → 60-chunk regulation corpus (GST/PF/ESI/FSSAI/PT/DPDP)
│
├── services/agents/ → Reasoning Agents (packages/llm/agents equivalent)
│ ├── orchestrator.py → LangGraph StateGraph pipeline (IRDA→COCE→DRCA→HITL→CAAL)
│ ├── irda/ → Intelligent Regulation Delta Analyzer
│ │ ├── watcher.py → Portal HTTP polling + hash-change detection
│ │ ├── delta_extractor.py → Field-level delta extraction + KG update hooks
│ │ ├── notifier.py → Affected-business detection + WS broadcast
│ │ └── orchestrator.py → Full IRDA cycle runner + CAAL logging
│ ├── coce/ → Cascade Obligation Computation Engine
│ │ ├── dependency_map.py → BUSINESS_EVENTS mapping
│ │ ├── cascade_engine.py → Event/regulation-change cascade evaluation
│ │ └── plain_language.py → Human-friendly change cards
│ ├── drca/ → Dual-Rail Compliance Assessor
│ │ ├── rail_a.py → LLM + RAG + KG reasoning (Rail A)
│ │ ├── rail_b.py → Deterministic rule engine (Rail B)
│ │ └── comparator.py → Rail diff, HITL escalation, CAAL write
│ ├── hitl/ → Human-in-the-Loop Resolver
│ │ ├── escalation.py → Escalation creation + context retrieval
│ │ └── resolution.py → Resolution update + CAAL write + WS notify
│ ├── caal/ → Cryptographic Agent Action Ledger
│ │ ├── agent_identity.py → Deterministic DID registry + action signing
│ │ ├── ledger_writer.py → Append-only CAAL writes + paginated retrieval
│ │ └── audit_packet.py → 90-day self-certifying audit packet generation
│ ├── gst_agent/
│ │ └── readiness_checker.py → GST filing readiness + checklist
│ ├── payroll_agent/
│ │ └── calculator.py → PF / ESI / PT / TDS payroll computation
│ └── dpdp/ → Data Privacy vault (DPDP Act 2023)
│ ├── vault_manager.py → Fernet tokenization / profile scrubbing
│ ├── consent_manager.py → Consent record + check
│ └── breach_detector.py → Breach simulation + DPB notification draft
│
├── services/scheduler/
│ └── polling_jobs.py → APScheduler jobs (portal poll, due dates, HITL reminder)
│
├── rulepacks/ → Immutable content-addressed Rule Pack store (create dir)
│ └── active.json → Pointer to currently active Rule Pack SHA
│
├── data/
│ ├── migrations/ → PostgreSQL DDL migrations
│ │ └── 001_initial_schema.sql
│ └── seed/ → Demo data seeders
│ ├── seed_db.py
│ ├── users.json
│ ├── obligations.json
│ └── audit_history.json
│
├── .env.example → All env var documentation (no real secrets)
├── docker-compose.yml → postgres + redis + api + scheduler
├── Makefile → dev / test / lint / seed / demo / doctor targets
├── AGENTS.md → This file
└── .cursor/rules/opencomply.mdc → Cursor/Kiro editor rules (copy of AGENTS.md)
LLM Provider Strategy
Primary: Gemma 4 (local, via Ollama / llama.cpp)
env: OLLAMA_BASE_URL, OLLAMA_MODEL
Fallback: Gemini API (opt-in, operator must set GEMINI_API_KEY)
code: services/knowledge/rag/gemini_client.py
Never sends business documents by default.
Legacy: Groq (retained in groq_client.py for backward compat)
env: GROQ_API_KEY, GROQ_MODEL
Alt: OpenRouter (opt-in)
env: OPENROUTER_API_KEY, OPENROUTER_MODEL
Routing logic (implement in services/knowledge/rag/llm_router.py):
- If Ollama is reachable → use local Gemma 4.
- Else if
GEMINI_API_KEYis set → use Gemini (no business docs). - Else if
GROQ_API_KEYis set → use Groq. - Else → return deterministic Rail-B result only with a warning.
Agent Pipeline (LangGraph)
UserQuery / PortalEvent
│
▼
[IRDA Watcher] ── poll portals every 30s ──► detect hash change
│
▼
[COCE Cascade] ── traverse KG ──► identify affected businesses + obligations
│
▼
┌─────┴──────┐
│ Rail A │ Gemma 4 (local LLM) + RAG retrieval
│ Rail B │ Deterministic Rule Engine (offline)
└─────┬──────┘
│ compare confidence delta
▼
[DRCA Comparator]
│
divergent?
yes ──► [HITL Queue] ──► human reviewer
no ──► auto-approve (draft)
│
▼
[CAAL Ledger] ── SHA-256 sign + append-only PostgreSQL write
│
▼
WebSocket broadcast ──► Next.js frontend
API Surface
| Method | Path | Description |
|---|---|---|
| GET | /health |
Health check — must return 200 {"status":"ok"} |
| GET | /v1/health |
Versioned health alias |
| GET | /compliance/businesses |
All businesses + health scores |
| GET | /obligations |
Obligation list (filterable) |
| POST | /assistant/chat |
DRCA-backed AI chat |
| GET | /audit |
CAAL ledger (paginated) |
| GET/POST | /hitl |
HITL queue management |
| GET | /gst/filing-status |
GST readiness + checklist |
| POST | /payroll/compute |
PF/ESI/PT/TDS compute |
| GET | /knowledge/graph |
Obligation graph JSON |
| POST | /admin/demo/trigger-change |
Demo change trigger |
| GET | /admin/scraping-health |
Live scraping status |
| WS | /ws/retrigger |
Real-time event stream |
Rule Pack Format
Rule Packs are immutable, content-addressed JSON bundles stored in rulepacks/:
{
"schema_version": "1.0",
"pack_id": "<sha256-of-content>",
"domain": "gst|pf|esi|pt|tds|labour",
"effective_date": "YYYY-MM-DD",
"source_url": "https://...",
"source_citation": "Notification No. ...",
"rules": [
{
"rule_id": "gst.late_fee.gstr3b",
"description": "...",
"formula": "...",
"parameters": {}
}
],
"section_aliases": {
"old": "...",
"new": "..."
}
}
Active Rule Pack pointer: rulepacks/active.json → { "active_pack_id": "<sha256>" }.
Development Workflow
make dev # Start PostgreSQL + Redis (Docker) + FastAPI backend
make seed # Run data/seed/seed_db.py to populate demo data
make demo # Run seed + trigger 3 demo scenarios
make test # Run Python + JS test suites
make lint # Ruff (Python) + ESLint (TypeScript)
make doctor # Environment pre-flight checks (Docker, Ollama, deps)
Security Notes
VAULT_ENCRYPTION_KEYmust be a 32-byte Fernet key. Generate with:python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"- Never commit
.env. The.gitignoremust include.env. - Clerk JWT verification happens in
middleware/clerk_auth.py. Do not bypass for any production route. - CAAL entries are append-only; do not add DELETE endpoints to the audit router.
Disclaimer
This system is not a substitute for professional tax or legal advice. All outputs are AI-assisted drafts pending human review. Always verify compliance assessments with a qualified Chartered Accountant or Company Secretary.
OpenComply Commons — Apache License 2.0
