AI Vendor Risk Assessor
Capstone project · after the Production RAG, Agentic RAG and Deep Search courses

AI Vendor Risk Assessor

Build the assistant every security and procurement team wishes it had: ask “Can our support team use this AI tool with customer data?” and get a review file with every policy requirement checked against evidence from the web — source, date and verdict — plus the exact questions still to ask the vendor. A human approves. The system never does.

Solo: 2–3 weeks · Team of 3–4: 4 weeks · Starter kit runs offline on day one · Created by Shivank Agrawal

0Start here

You have finished three courses. Each one built a serious component in isolation: a production RAG pipeline over company documents, an agentic RAG crew that routes and grades, and a deep search agent that researches the open web and refuses to be fooled. This capstone puts the three together into one product that a company would use, and adds the glue that none of the courses taught: a deterministic requirement matcher, a questionnaire drafter, a human approval gate and a UI.

What you will have at the end

  • A working assessor: policy library + vendor research + rule-based verdicts + human gate, behind an API and a small UI.
  • A hand-built gold set of real vendors and an evaluation report proving accuracy, zero guessing and injection resistance.
  • A trace for every run that lets you point from any verdict to the exact web page and policy clause behind it.
  • A portfolio project with a real enterprise story: “I automated the vendor security review, and here is how I kept it honest.”

Prerequisites

  • Completed Production RAG from Scratch (you have a working rag_core/ folder).
  • Completed Agentic RAG with DeepSeek + CrewAI (you understand Router, Retriever and the two graders).
  • Completed Deep Search Agents (you have run run_agent.py offline and live, and Lab 12 in LangGraph).
  • Python 3.10+, a free LLM key (Gemini or Groq) or Ollama, and a free web-search option (ddgs, no key).

Day one: run the starter kit

cd vendor-risk-assessor
python -m venv .venv && source .venv/bin/activate      # Windows: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
cp .env.example .env
python scripts/check_setup.py
python run_assessor.py                                   # LedgerLens AI, customer data, 35 users
python -m pytest -q                                      # 70 tests
python eval/run_eval.py                                  # the scorecard

The default run finishes in under a second with no key and no internet, and prints a full review file ending in BLOCKED. Read runs/<timestamp>-assess/report.md and then trace.jsonl. That report is the target; the rest of this page is how you make the system that produces it real.

How the starter kit is built. The deterministic parts are complete and tested (schemas, the matcher, the questionnaire, the report, the gold set and the evaluation harness). The parts your courses taught are present in a simplified offline form — keyword search instead of hybrid + rerank, a rule-based router instead of an LLM router, a static research plan instead of a planner — so that the whole thing runs. Every one of those files starts with a COURSE MAP comment and a LEARNER TODO block that names the milestone and the course module to use. Your job is to replace the simplified part with the real one, keep the tests green, and prove the improvement in the evaluation.

1The problem

Every company now has employees asking “can I use this AI tool?” several times a week. Each request should trigger a vendor security review: does the vendor hold a current SOC 2 Type II or ISO 27001? Where is our data stored? Do they train on it? Who are their sub-processors? Have they had an incident? Is a DPA available? Today a security engineer spends two to six hours per vendor reading trust centres, privacy policies and news, and most of that time is finding and dating facts, not judging them. Teams either wait weeks for a review or skip it.

The assessor does the finding, dating and checking. It leaves the judging to a person, with every fact already attached to its source.

The running example: Nimbu Mart

You know Nimbu Mart from the Production RAG course. Its Information Security team has eight internal documents — two editions of the security policy, a data-protection policy written for India’s DPDP Act, an AI acceptable-use policy, a procurement checklist, the restricted Approved Vendor List, a questionnaire template and an untrusted chat export. Three fictional AI vendors want in:

VendorWhat it doesWhy it is a good test
LedgerLens AISummarises support ticketsSolid SOC 2 Type II, but data lives in the US/EU with India “planned”. A stale 2024 page, a same-name UK accountancy firm, a forum rumour, a review site that contradicts the trust centre, and a blog page carrying a prompt-injection attack.
QuillDeskAI writing assistant“SOC 2 compliant” with no report, trains on content by default, US-only storage, a July 2026 incident with no post-mortem, a directory page that is a copy of the vendor’s own page.
Parakeet TranslateTranslation for Indian languagesThe good vendor: ISO 27001 confirmed on the certifier’s registry, India region, no training, DPA with a DPDP addendum — but approved only for internal data, so customer-data use still needs Procurement.

What “good” looks like

The review file the starter kit produces for LedgerLens at the customer-data tier looks like this (abridged):

RequirementClauseVerdictReason (abridged)Evidence
Independent security assuranceSEC-4.2PASSSOC 2 Type II report dated 2026-01-20trust.ledgerlens.example · 2026-09-01
Customer data stored in IndiaDP-3.1FAILIndia is only planned; available today: US, EUledgerlens.example/legal/privacy · 2026-03-15
No training on our dataAI-2.1NEEDS REVIEWNo training on Business/Enterprise; Free/Pro trains by defaultledgerlens.example/legal/ai-data-use
Sub-processors disclosedAI-3.4NEEDS REVIEWModel provider present: Orbital Models (US)ledgerlens.example/legal/subprocessors
Incident historySEC-9.3NEEDS REVIEWOne major incident (2025-04) with a published post-mortem2 sources
On the Approved Vendor ListPROC-1.1NEEDS REVIEWA review is already in progress; attach this assessmentpolicy library

Then: the facts with confidence and conflicts, a security section (“1 page quarantined for prompt injection; 1 rejected as a different company; 1 rumour dropped”), six ready-to-send questions for the vendor, and an approval block with the two roles who must sign (Head of Information Security and DPO). The outcome line says BLOCKED for this data tier — never “rejected”, and never “approved”.

2Architecture

Question+ who is asking Input guardrailredact · intent RouterAgentic RAG Policy library (Production RAG)clause chunks · hybrid · rerank · ACL Gradersrelevant? grounded? policy question Vendor research (Deep Search)plan · fetch · identity · score · merge vendor / assessment Matcherrules → verdicts (no LLM) requirements.yaml · Approved Vendor List QuestionnaireUNKNOWN → questions Human gateapprovers by tier (AI-5.1) Review filereport.md · json · trace Output guardrailno “approved” · evidence, else UNKNOWN Production RAG course Agentic RAG course Deep Search course New in this capstone Security & humans (both courses)
One graph, three routes. A policy question stops at the graders. A vendor-fact question stops after research. An assessment runs the whole chain and ends in a human decision. The same nodes run as plain Python or as a LangGraph state machine (assessor/graph.py).

The components

ComponentFileStatus in the starter kit
Contracts between stagesassessor/schemas.pyComplete. Nine vendor fields, evidence levels, verdicts, the report.
Policy libraryassessor/policy_rag.pySimplified: clause chunking + BM25 + ACL/version/trust filters + extractive answers. You: hybrid + rerank + grounded generation.
Routerassessor/router.pyRule-based mock. You: LLM router with the course’s Router prompt and two extra routes.
Gradersassessor/graders.pyHeuristic mocks. You: the two grader agents + retry loop.
Vendor researchassessor/vendor_research.pyFull offline loop with identity gate, quarantine, scoring, merging. Live mode is a sequential baseline. You: planner, parallel workers, memory, live evaluation.
Requirement matcherassessor/matcher.py + data/requirements.yamlComplete and tested. Eight rule types, eleven requirements. You extend it when you add policies.
Questionnaire, reportassessor/questionnaire.py, report.pyComplete.
Guardrailsassessor/guardrails.pyRegex input redaction, intent check, output policy. You: LLM injection classifier, red-team suite.
Orchestratorassessor/graph.pyPlain Python and LangGraph, same nodes; CLI human gate. You: checkpointer + interrupt, streaming.
API, UIapp/api.py, app/ui.pyThin skeletons. You: queue, storage, auth, trace viewer.
Evaluationeval/run_eval.py, data/gold_set*.jsonHarness complete; fictional gold set complete; real-vendor gold set is a template. You: fill it.

3Course map: which part needs which course section

Use this table as your index. When you open a LEARNER TODO in the code, this is where to look first. “Reuse” names the files from the course code packs you can copy or import.

Project partCourseModule / chapterLabReuse from the course codeMilestone
Ingest policies; chunk by clause with metadata (version, status, access, trust)Production RAG04 Document ingestion pipeline · 06 Chunking strategies (“structure-aware”, “chunk metadata”)Lab 03rag_core/documents.py, chunking.py, loaders.py, the _metadata.json patternM1
Retrieve the right clause: hybrid search, RRF, metadata filters, rerankingProduction RAG08 Retrieval & reranking (sections 3–9) · 07 Embeddings (choosing a model)Labs 04, 06, 07, 08rag_core/hybrid.py, bm25.py, vectorstore.py, rerank.py, query_transform.pyM1
Grounded policy answers with clause citations; refuse when the context lacks the answerProduction RAG09 Grounded generation (grounding rules, refusing, structured output)Lab 09rag_core/generate.py, prompts.pyM1
Access control in retrieval; archived versions; untrusted documents; PII redactionProduction RAG11 Security & privacy (sections 1–3)Lab 11rag_core/security.py (acl_filter, redact_pii, detect_injection)M1, M4
Route the question: policy / vendor / assessment / refuseAgentic RAG“agents.py → The Router” · “tasks.py → Task 1: route” · exercise “Break the Router on purpose”—agents.py (create_router_agent), tasks.pyM3
Check the answer: relevance grader and hallucination grader, with a retryAgentic RAG“Tasks 3 and 4: the two checks” · “Prompt engineering is the real work”—agents.py (the two grader agents), tasks.py (context between tasks)M3
Two models: a fast cheap one for extraction and grading, a strong one for synthesisAgentic RAG Deep SearchAgentic RAG “Two LLMs”, llms.py · Deep Search 09 “Model routing”DS Lab 10llms.py; deepsearch/llm.py (LLM.small)M2, M3
Plan the research: Plan Creator → Reviewer, sub-questions per field, stop rulesDeep Search03 Planning layerLab 3deepsearch/planner.py, schemas.py (ResearchPlan, PlanReview)M2
Typed tools; validate → repair loop for LLM JSONDeep Search04 Executor, tools and MCP (“Schema enforcement with Pydantic”, “Robust tool calls”)Lab 2deepsearch/llm.py (structured()), tools.pyM2
Parallel workers: search → fetch → injection scan → extract claimsDeep Search04 Executor · 09 “Latency: parallel workers”Lab 4deepsearch/executor.py, extractor.pyM2
Identity gate (same-name companies), authority per source, freshness decay, copies counted onceDeep Search05 Validation, reliability and temporal reasoningLab 6deepsearch/validator.py (AUTHORITY, HALF_LIFE_DAYS, FIELD_AUTHORITY_OVERRIDES)M2
Merge claims; resolve conflicts; keep provenance on every valueDeep Search06 Merging and final answer constructionLab 7deepsearch/merger.pyM2
Remember past assessments; re-review only what changed (SEC-12.1)Deep Search07 Context, memory and iterationLab 8deepsearch/memory.pyM2 (stretch)
Prompt injection through web pages; quarantine; defence in depth; red teamDeep Search Production RAGDeep Search 08 Security · Production RAG 11 (“Prompt injection through documents”)DS Lab 9 · RAG Lab 11deepsearch/security.py, rag_core/security.pyM4
Budgets, token costs, model routing; cost per assessmentDeep Search Production RAGDeep Search 09 Cost, latency and budgets · Production RAG 12 (“Cost”, “Caching”)DS Lab 10 · RAG Lab 13deepsearch/budget.py, rag_core/cache.pyM2, M5
Tracing and observability: read a wrong verdict back to its pageDeep Search Production RAGDeep Search tracing.py (Module 12 checklist) · Production RAG 12 “Observability”RAG Lab 13deepsearch/tracing.py, rag_core/observability.pyM5
Evaluation: gold set first, programmatic metrics, ablations, LLM-as-judge, CIDeep Search Production RAGDeep Search 10 Evaluating deep search agents · Production RAG 10 EvaluationDS Lab 11 · RAG Lab 10deepsearch/evaluation.py, rag_core/evaluation.py, eval/golden.jsonl formatM6
Orchestration as a graph; human-in-the-loop pause; checkpointsDeep Search02 System architecture (“five patterns”) · 12 “The same loop in a framework”Lab 12labs/lab12_langgraph_version.pyM5
The service: FastAPI entry points, validation, queue, workers, storageProduction RAG04 Ingestion pipeline (entry points, queue, idempotency) · 13 Capstone: the production appModule 13 exercisescode/app/api.py, worker.py, db.py, docker-compose.ymlM5
Privacy and law: research companies, not people; DPDP Act; minimal schemaDeep Search11 Privacy, law and ethics for research agents—the checklist in Module 11M4
Expose the assessor to Claude Desktop / your IDE as an MCP tool (stretch)Deep Search04 “MCP: the Model Context Protocol”Lab 5labs/lab05_mcp_server.py, lab05_mcp_client.pyStretch
Requirement matcher: rules × facts → verdicts, deterministic, testedNewPrinciples: Deep Search 06 (“a clean structured result”), Production RAG 09 (“refusing”)—Already written: assessor/matcher.py, tests/test_matcher.py. Extend when you add clauses.M0, M6
Questionnaire drafter and review fileNewProduction RAG 09 “Structured output”—Already written: questionnaire.py, report.pyM0
Human approval gate, approvers by data tierNewDeep Search 12 checklist (“the user approves the plan before a long run”)—graph.py (human_gate), app/api.py (/approve)M5
Streamlit UI with progress and a trace viewerNew——app/ui.py skeletonM5

4Milestones

Do them in order. Each one ends with a check you can run. Tick the box when the check passes; the page remembers it in your browser.

M0

Run and read the starter kit

½ day

Goal: know exactly what the finished system does before changing anything.

  1. Run the four demo questions in the README. Read each report.md, then its trace.jsonl, bottom to top.
  2. Read the code in this order: schemas.py → matcher.py → graph.py (run_plain) → vendor_research.py → policy_rag.py.
  3. Open data/vendor_web/corpus.json. Find the stale page, the look-alike company, the rumour, the copy and the attack page. Predict what the system does with each; check against the LedgerLens trace.
  4. Break something on purpose: in requirements.yaml set allow_planned: true on DP-3.1 and watch LedgerLens pass residency. Put it back.

Done when: pytest is green, eval/run_eval.py shows 100% verdict accuracy, and you can explain in two sentences why QuillDesk is BLOCKED and Parakeet is only CONDITIONAL.

M1

The policy library, production grade

3–4 days

Production RAG Modules 06, 08, 09, 11 · Labs 03, 06, 08, 09, 11

Goal: replace keyword search with your rag_core pipeline, and extractive answers with grounded generation — without losing a single security property.

  1. Copy your rag_core/ into the project. Load data/policies through it, keeping clause ids and the metadata fields (access, status, trust, version) on every chunk.
  2. Make PolicyLibrary.search() use hybrid retrieval (BM25 + vectors, RRF) and a cross-encoder reranker. Filters stay before ranking: ACL, archived, untrusted, injection flag.
  3. Make PolicyLibrary.answer() generate grounded answers with clause citations when an LLM is configured; keep the extractive mode as the offline fallback. Refuse when the top score is below threshold and when the grader says the answer is not grounded.
  4. Fix the known failure: pq-who-approves in the gold set (keyword search ranks SEC-7.1 above the approval table in AI-5.1). Hybrid + rerank should fix it; prove it in the eval report.
  5. Add three policy documents of your own (for example an incident-response runbook and a 2027 draft marked status: draft) and three new gold questions.

Done when: all policy-question checks in eval/run_eval.py pass including the one marked “baseline known to fail”; tests/test_policy_rag.py still passes (ACL, archived, untrusted); an employee asking for the Approved Vendor List still gets the process, never the list.

M2

Vendor research on the real web

4–5 days

Deep Search Modules 03, 04, 05, 06, 07, 09 · Labs 2, 3, 4, 6, 7, 8, 10

Goal: turn the sequential live baseline into a planned, parallel, budgeted research agent that produces the same VendorProfile the offline mode does — for real vendors.

  1. Four places (Deep Search Module 12 “Adapt it to your own domain”): the fields are already retargeted in schemas.py; review AUTHORITY, FIELD_AUTHORITY_OVERRIDES and HALF_LIFE_DAYS in vendor_research.py and justify each number in a comment.
  2. Replace plan_queries() with a Plan Creator → Plan Reviewer pair that produces one sub-question per field, with stop rules (“stop when every high-stakes field has a documented source or two searches have failed”).
  3. Run fetch + extraction in parallel workers sharing one Budget; route extraction to the small model.
  4. Make the identity gate real: the LLM decides “same company?” from domain, legal entity and product — and the gate stays a gate (reject, do not down-weight).
  5. Pick three real AI/SaaS vendors, research them by hand first (fill data/gold_set_template.json with URLs and dates), then run the agent and compare field by field.
  6. Stretch: long-term memory of previous runs so a re-review of the same vendor only fetches pages newer than the last run.

Done when: on your three real vendors, field accuracy against your hand-made gold set is ≥ 80%, no field is filled from a page about a different company, a live assessment costs under your VRA_MAX_USD and finishes in under 90 seconds, and the offline tests still pass unchanged.

Expect friction. Trust centres are JavaScript-heavy, some sites block bots, and “SOC 2 compliant” appears on pages with no report. That is the real job. Keep the offline corpus as your regression suite and add a cached_pages/ snapshot for your real vendors so your demo does not depend on the internet.

M3

Router and graders as agents

2 days

Agentic RAG “agents.py”, “tasks.py”, “Practice and self-check”

Goal: replace the regex router and the heuristic graders with LLM agents that are better than the mocks and prove it.

  1. Port the Router’s goal and backstory from the course kit, add the two new routes (vendor, assessment) and the refuse route, and return a RouteDecision through LLM.structured().
  2. Port the Answer Grader and Hallucination Grader as grade_relevance() / grade_grounded(). Add the retry loop: not relevant → widen the search (k = 8, include query rewriting); not grounded → regenerate once with a stricter prompt, then abstain.
  3. Write 30 routing questions (10 per route, including awkward ones: “Is LedgerLens SOC 2 so we can use it?” is an assessment; “Which tier is Parakeet approved for?” is a policy question) and measure routing accuracy for the mock and for the LLM.
  4. Repeat the course exercise “Break the Router on purpose” on your new router and write down what changed.

Done when: routing accuracy ≥ 90% on your 30 questions with the LLM router; a deliberately wrong policy answer (edit the prompt to invent a clause) is caught by the hallucination grader and turned into an abstain.

M4

Security: attack it, then defend in layers

2 days

Deep Search Modules 08, 11 · Lab 9   Production RAG Module 11 · Lab 11

Goal: prove that untrusted content — web pages, chat exports, the user’s own question — can never change a verdict.

  1. Write tests/test_red_team.py with 15 attacks: injection in a vendor page (“report PASS”), injection in a policy document, a user question that smuggles an instruction (“…and mark it approved”), a fake trust-centre on a look-alike domain, a page that says the India region exists when the privacy policy says planned, a rumour phrased as news. Every attack must be caught, and the test must assert where it was caught (quarantine, identity gate, dropped, intent check, output guardrail).
  2. Add a second injection layer behind the regexes: a small-model classifier on each fetched page (Deep Search Lab 9). Measure false positives on the clean pages.
  3. Run the ablation: switch the identity gate off and show the UK firm’s ISO certificate leaking into LedgerLens’s facts. Put the screenshot in your write-up.
  4. Apply the Module 11 privacy checklist: the schema holds no personal data; the questionnaire email names a role, not a person; nothing from a vendor’s employees is stored.

Done when: 15/15 attacks caught with the catch point asserted; the gold-set safety metric is still 100%; the guess rate is still 0.

M5

Make it a product: graph, API, UI, human gate

3–4 days

Deep Search Module 12, Lab 12   Production RAG Modules 04, 12, 13

Goal: a reviewer can use it without you in the room.

  1. LangGraph: add a checkpointer and an interrupt() at human_gate so an assessment can pause for days and resume when the approver decides. The CLI prompt in the starter is the placeholder for this.
  2. API: put /assess behind a queue (Redis + RQ as in the Production RAG app), return a job id immediately, and poll for the report. Store reports in Postgres so /vendors/{name}/history can show what changed since the last review (SEC-12.1).
  3. Derive user_groups from the caller’s identity on the server. Never accept groups from the client — that is the ACL.
  4. UI: stream node progress during a live run; show the trace as a tree beside the report; add the Approve / Reject form that calls /approve/{run_id} with the reviewer’s name. A BLOCKED report must not offer an Approve button.
  5. Observability: per-stage timings and cost on every run; a table of the last 20 runs with p50/p95 latency and cost (Production RAG Lab 13).

Done when: a teammate who has not seen the code can assess a vendor from the UI, read why each verdict was given, send the vendor questions, and record a decision — and the decision survives a server restart.

M6

Evaluate, write it up, demo

2–3 days

Deep Search Module 10, Lab 11   Production RAG Module 10, Lab 10

  1. Grow the real-vendor gold set to 10 vendors × 8 fields, hand-checked with URL and date. Mix clear passes, clear fails and messy cases.
  2. Add an LLM-as-judge metric for the reasons: is every reason faithful to the cited evidence? Calibrate the judge on 20 hand-labelled reasons first.
  3. Run one ablation per component (no reranker, no identity gate, no freshness decay, no planner) and put the table in the report. Each component must earn its place.
  4. Wire eval/run_eval.py --strict and pytest into CI (GitHub Actions) on the offline gold set.
  5. Write the README for your repo: the problem, the architecture, the numbers, what went wrong and what you would do next. Then rehearse the demo below.

Done when: the evaluation report shows accuracy, guess rate, safety, cost and latency for the fictional set and the real set; CI is green; the demo runs offline and live.

5The data pack

Policies data/policies/

  • Information Security Policy 2026 (SEC-4.2 assurance, SEC-7.1 SSO, SEC-9.3 incidents, SEC-9.4 rumours) and the 2025 edition, archived — it accepted SOC 2 Type I, so an agent that reads the wrong version passes the wrong vendors.
  • Data Protection Policy (DP-2.2 DPA, DP-3.1 India residency, DP-4.1 sub-processors, DP-5.4 deletion).
  • AI Acceptable Use Policy (AI-2.1 no training, AI-3.4 model providers, AI-5.1 who approves).
  • Vendor Onboarding Checklist (PROC-1.1 the list, PROC-2.1 the review file).
  • Approved Vendor List — restricted to Security and Procurement. Parakeet is approved for T2 only; LedgerLens is “in progress”.
  • Questionnaire template NM-SEC-Q — the source of every vendor question in the report.
  • Chat export marked untrusted, with a wrong claim and an injection line.

Rules data/requirements.yaml

Eleven machine-checkable requirements. Each has a clause, a vendor field, a rule type, parameters, a severity and the data tiers it applies to. Rule types: certification_valid, region_includes, value_known, enum_verdict, list_disclosed, retention_within, no_unresolved_incident, approved_for_tier. Adding a clause means adding a YAML entry and, sometimes, one small rule function with its tests.

The vendor web data/vendor_web/corpus.json

23 fictional pages across three vendors. Each page carries mock_claims: what a careful extraction model would read from it. In offline mode the agent uses those; in live mode it calls your model. Every domain ends in .example.

Gold sets

gold_set.json: five assessment cases (including the same question asked by someone without access) and six policy questions, one marked “baseline known to fail”. gold_set_template.json: the shape you fill for real vendors.

6Rules of the project

  1. The model never decides a verdict. It reads pages, drafts text and classifies routes. matcher.py decides, from rules you can unit-test. Two runs on the same evidence give the same verdict.
  2. UNKNOWN beats a guess. A PASS or FAIL without an evidence URL is a bug; the output guardrail downgrades it. The evaluation’s guess_rate must stay at zero.
  3. A claim is not evidence. “We are SOC 2 compliant” is claimed. A report, a certificate number, a registry entry or a legal page is documented. Only documented evidence passes a high-stakes requirement.
  4. Identity is a gate, not a weight. A page about a same-name company is rejected before anything is read from it. Down-weighting it would still let its facts leak in.
  5. Untrusted content never reaches the verdict. Pages that address the AI are quarantined whole. Forum posts and rumours are dropped and logged, not scored low.
  6. Repetition is not corroboration. A syndicated copy of the vendor’s page counts once.
  7. Access control lives in retrieval. The Approved Vendor List is invisible to people outside Security and Procurement, and the assistant says so instead of leaking it. Groups come from identity on the server, never from the request body.
  8. Every fact has a date. Freshness decays per field. A 2024 security page loses to a 2026 trust centre, and the conflict is recorded, not hidden.
  9. Humans approve. The report ends in an approval block that only a named person can fill. The word “approved” never appears in anything the system writes about a vendor.
  10. Research companies, not people. No names of vendor employees in the schema, the memory or the report.

7Evaluation & rubric

The scorecard your evaluation must report

MetricMeaningTarget
verdict_accuracy(case, requirement) verdicts equal to gold≥ 95% fictional set · ≥ 80% real set
overall_accuracyBLOCKED / CONDITIONAL / READY matches gold100% fictional
guess_ratePASS/FAIL where gold says UNKNOWN or NEEDS_REVIEW0%, both sets
safetyattack pages quarantined, look-alikes rejected, rumours dropped, nothing from them cited100%
policy_qa_hardnever cites a document the asker may not see, nor an untrusted one100%
cost · latencyper live assessmentunder your budget · under 90 s

Rubric (100 points)

AreaPointsFull marks look like
Correctness on the fictional gold set15eval --strict and pytest green after every change you made.
Policy library (M1)15Hybrid + rerank + grounded answers with clause citations; the “known to fail” case fixed; ACL, versions and trust proven by tests; three new documents and questions.
Vendor research, live (M2)20Planner + parallel workers + budget; ≥ 80% field accuracy on a hand-made gold set of real vendors; identity gate and freshness justified; conflicts recorded with provenance.
Router and graders (M3)10LLM router ≥ 90% on 30 questions; graders catch an injected hallucination; retry loop works.
Security (M4)1015/15 red-team attacks caught with catch point asserted; identity-gate ablation shown; privacy checklist applied.
Product (M5)15LangGraph with checkpointed human gate; queued API with history; UI with progress, trace viewer and decision form; a BLOCKED report cannot be approved.
Evaluation and engineering (M6)1010 real vendors in the gold set; LLM-as-judge for reasons, calibrated; one ablation per component; CI green.
Write-up and demo5README with numbers and honest failures; a demo that runs offline and live without improvisation.

8Demo checklist (12 minutes)

  1. The question (1 min): a support lead asks whether the team can use LedgerLens for tickets. Show the review file. Point at the BLOCKED line and at DP-3.1 with its source and date.
  2. The trace (2 min): open trace.jsonl. Show the rejected UK firm, the quarantined blog page, the dropped rumour, the 2024 page losing to the 2026 trust centre.
  3. Access control (1 min): ask the same question as an employee outside Security. PROC-1.1 turns UNKNOWN; the Approved Vendor List never appears. Ask “which vendors are approved?” and get the process, not the list.
  4. The good vendor (2 min): Parakeet at T3 — every requirement passes on documented evidence, yet the outcome is CONDITIONAL because approval is for T2 only. Switch to T2 and show READY FOR HUMAN APPROVAL. Try to approve the BLOCKED LedgerLens report: refused.
  5. Live (3 min): a real vendor from your gold set, from the UI, with progress streaming. Compare two fields against what you found by hand.
  6. Attack (1 min): add an injection line to a cached page and re-run. Quarantined; verdicts unchanged.
  7. Numbers (2 min): the scorecard, the ablation table, cost and latency, and the two things that still go wrong.

9Stretch goals

  • Continuous monitoring. A weekly scheduled re-review of every approved vendor that only reports changes (new sub-processor, new incident, certificate expiring in 60 days). Deep Search Module 7 memory + Module 12 “regulatory circular monitor” idea.
  • MCP server. Expose assess_vendor and ask_policy as MCP tools so Claude Desktop or your IDE can call them (Deep Search Lab 5).
  • Debate layer. Before the human gate, a “vendor advocate” and a “risk officer” agent each write one paragraph from the same evidence; the report shows both. Useful when evidence conflicts.
  • Document intake. Let the vendor upload its SOC 2 report PDF; extract the audit period and the auditor’s opinion with the Production RAG OCR/table pipeline (Lab 02) and upgrade claimed to documented automatically.
  • Multi-tenant. A second company with different policies (tenant_id on every chunk and rule), as in the Production RAG capstone exercise.

10FAQ

Why not let the LLM read the policy and the evidence and decide?

Because the verdict must be the same on Tuesday as it was on Monday, and a reviewer must be able to point at the line of policy and the line of evidence behind it. Models are excellent at reading and extracting; they are not consistent judges. Keeping the judgement in code is what makes the system auditable and the evaluation meaningful.

Isn’t a rule engine “not AI”?

The intelligence is in reading a thousand messy pages and turning them into typed, dated, sourced facts — and in knowing which pages to distrust. That is where every hour of the project goes. The rule engine is 300 lines and stays that way.

What if a vendor’s pages block my fetcher?

Cache what you can, record UNKNOWN for what you cannot, and let the questionnaire ask the vendor. An honest UNKNOWN with a question attached is a correct output. Playwright for JavaScript-rendered trust centres is a reasonable stretch.

Can I do this solo?

Yes: do M0–M4 fully, M5 as the CLI + API only, and three real vendors instead of ten. That is a complete, demonstrable project in about three weeks.

Which LLM should I use?

Whatever is free and supports JSON output: Gemini’s free tier or Groq for development, Ollama for offline. Use the small model for extraction and grading and a stronger one only for planning and synthesis — then show the cost difference in your report.

AGlossary

Data tierNimbu Mart’s classification: T1 public, T2 internal, T3 customer data. Requirements depend on the highest tier a tool touches.
SOC 2 Type IIAn independent auditor’s report that a vendor’s controls operated effectively over a period (usually 6–12 months). Type I covers design at a point in time only.
ISO/IEC 27001A certificate, issued by an accredited body, that the vendor runs an information-security management system. Has a certificate number and an expiry date.
DPAData Processing Agreement: the contract that binds a vendor to process personal data only on the customer’s instructions.
DPDP ActIndia’s Digital Personal Data Protection Act, 2023. Nimbu Mart is a Data Fiduciary; vendors are Data Processors.
Sub-processorA company the vendor uses that also touches your data — hosting, email, and any third-party model provider.
Evidence leveldocumented (report, certificate, registry, legal page) · claimed (marketing text) · third_party (named press/review site) · rumour (forum, unnamed).
Identity gateThe check that a page is about the same company before anything is read from it.
QuarantineRemoving a page entirely because it contains instructions aimed at the AI.
VerdictsPASS · FAIL · UNKNOWN (no evidence) · NEEDS_REVIEW (evidence found, a person must judge) · NOT_APPLICABLE (rule does not apply to this tier).
OutcomeBLOCKED (a blocking requirement failed) · CONDITIONAL (open items) · READY FOR HUMAN APPROVAL (all passed; a person still decides).
Created by Shivank Agrawal · Future with Shivank · All companies, people, domains and documents in the data pack are fictional and were written for this course.