ScamSentry / scripts /smoke_test_day3.py
SooryaKiranKakkarayil
Day 3 complete: fix url_reputation_agent output_schema+tools bug, fix eval harness suffix bug, switch to gemini-3.1-flash-lite, all 9 EDD cases + full smoke test pass
e2329f0
Raw History Blame Contribute Delete
3.27 kB
"""
Day 3 smoke test — ScamSentry
Runs the full Intake -> [URL Reputation, Linguistic] parallel pipeline
against 5 mixed sample inputs and prints intermediate + final state for
each. This is the "small Python driver script that prints intermediate
state at each node" from the Day 3 plan.
Run this ON SCREEN in Antigravity while capturing the ~20s clip of the
agent manager/artifacts panel for the Day 7 video — this is the easiest,
most natural moment all week to get that footage authentically. Do it now
rather than trying to recreate it later.
Run from the repo root:
python scripts/smoke_test_day3.py
"""
import asyncio
import json
import sys
from pathlib import Path
# When this file is run directly (python scripts/smoke_test_day3.py),
# Python puts scripts/ on sys.path, not the repo root — so `agents` isn't
# importable without this. Same root cause as the Day 2 mcp_server/server.py
# ModuleNotFoundError fix.
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
# .venv activation loads nothing from .env by itself — that only happens
# via load_dotenv(). Same bug class as the Day 2 MCP Inspector fix, just a
# different entry point. This must run before any agent touches the
# Gemini client.
from dotenv import load_dotenv
load_dotenv()
from agents.orchestrator import run_pipeline
SAMPLES = [
(
"obvious_scam_urgency_gift_card",
"URGENT: Your account will be suspended in 24 hours! Click "
"http://secure-paypa1-verify.com/login now and verify your "
"identity or send a $50 gift card to avoid suspension.",
),
(
"obvious_scam_prize",
"Dear Customer, CONGRATULATIONS! You've won a $5,000 Amazon gift "
"card. Claim now at http://claim-prize-now.example.net before it "
"expires in 1 hour!",
),
(
"obviously_legit",
"Hey, it's Sam from the office. Are we still meeting at 3pm "
"tomorrow to go over the Q3 numbers? Let me know.",
),
(
"legit_with_real_link",
"Your package from Amazon has shipped. Track it here: "
"https://www.amazon.com/gp/your-account/order-history",
),
(
"ambiguous_borderline",
"Hi, this is a reminder that your subscription renews tomorrow. "
"If you'd like to cancel, visit http://billing-update.example.org "
"and update your payment method.",
),
]
async def main():
for i, (name, text) in enumerate(SAMPLES):
if i > 0:
# Space samples out so a healthy run mostly avoids the 429
# retry path in orchestrator.run_pipeline rather than relying
# on it every time. 20s is a starting point for a 5 RPM
# project quota with ~3-4 calls/sample — shrink it if your
# project's actual RPM (shown in the 429 error message) is
# higher.
print("\n[pausing 20s before next sample to respect Gemini RPM]")
await asyncio.sleep(20)
print("\n" + "=" * 70)
print(f"SAMPLE: {name}")
print("=" * 70)
result = await run_pipeline(text=text, verbose=True)
print("\n--- FINAL STATE ---")
print(json.dumps(result, indent=2))
if __name__ == "__main__":
asyncio.run(main())