Practice Repo β runnable, offline¶
A tiny fake agent platform so the concepts in the notes become physical. No API keys, no network β it runs with only pytest.
Run it¶
You should see 50 tests pass across five test files (agent graph, trace/non-determinism, audit/eval, safety/red-team, and the action harness).
What each file demonstrates¶
| File | Maps to notes | Shows |
|---|---|---|
agent.py |
08, 09, 12 | Fake agent graph (classifyβpolicyβapprovalβexecuteβaudit), mockable tools, a Langfuse-shaped Trace, and a hash-chained AuditLog. |
evals.py |
04, 07, 10, 11 | cosine, safe_json, semantic assertion, Ragas-style faithfulness/answer_relevancy/context_recall, and a regression harness with baseline comparison. |
conftest.py |
01 | Fixtures: scoped audit, a factory make_payment with cleanup. |
tests/test_agent_graph.py |
08 | Assert path/order, mock tools to force branches, the approval gate, exact tool args, boundary parametrize. |
tests/test_trace_and_nondeterminism.py |
07, 09 | Trace path/score/cost assertions, structural invariants, semantic (not exact) matching, messy-JSON parsing. |
tests/test_audit_and_eval.py |
10, 11, 12 | Audit chain intact / append-only / tamper detected, Ragas metrics catch hallucination, regression gate passes and trips. |
safety.py |
16 | A guarded fake chatbot (secure vs vulnerable=True) + graders: refusal check, PII/secret regex, canary-token leak, identity denylist, Attack Success Rate. |
tests/test_safety_redteam.py |
16 | Red-team: harms refusal + ASR gate + over-refusal, system-prompt/secret leakage (canary), jailbreak incl. indirect injection via poisoned tool output, identity ("I'm ChatGPT") checks β plus tests proving the detectors catch a real leak. |
action_harness.py |
17 | The action containment harness for real-world actions: least-privilege allowlist, human gate for irreversible actions, dry-run, spend cap, idempotency, kill switch. |
tests/test_action_harness.py |
17 | One test per control (OWASP LLM06): disallowed tool blocked, irreversibleβapproval, retryβno double-execute, over-budgetβblocked, dry-runβno side effect, kill switchβhalts. |
Learn by breaking things (do this before the interview)¶
- In
agent.py, move thecheck_policyspan to afterrelease_paymentβtest_policy_checked_before_releasefails. That's why order matters (file 08). - Change
HIGH_VALUE_THRESHOLDto100000β the approval-gate test fails. That's a missing human gate (file 08/12). - In
tests/test_audit_and_eval.py::test_tampering_breaks_the_chain, comment out the tamper line βverify_chain()stays True, showing the hash chain only catches actual edits (file 12). - Make
degradedreturn the correct answer intest_regression_is_detectedβ the regression gate no longer trips (file 10). - Raise the semantic
thresholdto0.99β paraphrase test fails, showing threshold tuning (file 07). - In
safety.py, make the secure bot echo the system prompt (or say "I'm ChatGPT") β the red-team tests intest_safety_redteam.pygo red, proving the guardrail + detector work (file 16).
Then extend it (interview talking points)¶
- Add a
tool_errorpath: makerelease_paymentraise and assert the agent degrades gracefully (file 08). - Add
pytest-asyncioand anasync def run_agentvariant (file 04). - Add an HTTPX + Pydantic contract test against a stub endpoint (file 03).
- Add a
--min-scoreCLI aroundrun_evaland wire the exit code as an Azure DevOps gate (file 06/10).