$ uv run tools/flow.py push reference/lab03-example2-slo.json ! unpublished '77 Log report + repeat topics (answer)' (wf3d06e3d30eeee6): it used the same webhook path ✔ pushed '77 Log report + SLO (reference)' (id wfed832ca6c81732) POST http://localhost:5678/webhook/my-log-report $ uv run tools/flow.py test cases/lab03-slo.json -v POST http://localhost:5678/webhook/my-log-report · 4 case(s) × 1 ✔ 둘째 주 · SLO 못 지킴 · 0.9s · 304 calls · $0.039810 → request POST /webhook/my-log-report { "from": "2026-10-26", "to": "2026-10-30" } ← response HTTP 200 { "total": 357, "errors": 21, "error_rate": 0.0588, "p50_ms": 1171, "p95_ms": 2598, "by_route": { "오류": 21, "자동 답변": 299, "담당자 연결": 17, "잠시 후": 20 }, "by_day": { "2026-10-26": { "total": 70, "errors": 16, "error_rate": 0.2286 }, "2026-10-27": { "total": 62, "errors": 0, "error_rate": 0 }, "2026-10-28": { "total": 64, "errors": 0, "error_rate": 0 }, "2026-10-29": { "total": 97, "errors": 5, "error_rate": 0.0515 }, "2026-10-30": { "total": 64, "errors": 0, "error_rate": 0 } }, "by_release": { "1.0.0": { "answers": 110, "repeats": 3, "repeat_rate": 0.0273 }, "1.1.0": { "answers": 181, "repeats": 14, "repeat_rate": 0.0773 }, "1.2.0": { "answers": 8, "repeats": 5, "repeat_rate": 0.625 } }, "steps": { "faq_ms": { "runs": 337, "p50": 28, "p95": 40 }, "answer_ms": { "runs": 304, "p50": 1162, "p95": 2532 } }, "cost_usd": 0.03981, "cost_per_run": 0.000112, "llm_calls": 304, "failures": [ { "node": "Search FAQ", "message": "timeout of 1000ms exceeded", "count": 16 }, { "node": "Answer", "message": "429 Rate limit reached for requests", "count": 5 } ], "unanswered_topics": [ { "topic": "와이파이", "count": 17 } ], "anomalies": [ { "hour": "2026-10-26T09", "total": 16, "errors": 16, "error_rate": 1 }, { "hour": "2026-10-29T15", "total": 7, "errors": 5, "error_rate": 0.7143 } ], "repeat_topics": [ { "topic": "프린터", "answers": 36, "repeats": 4, "repeat_rate": 0.1111 }, { "topic": "설치", "answers": 24, "repeats": 2, "repeat_rate": 0.0833 }, { "topic": "비밀번호", "answers": 70, "repeats": 5, "repeat_rate": 0.0714 }, { "topic": "접수 현황", "answers": 56, "repeats": 4, "repeat_rate": 0.0714 }, { "topic": "메일", "answers": 48, "repeats": 3, "repeat_rate": 0.0625 }, { "topic": "VPN", "answers": 65, "repeats": 4, "repeat_rate": 0.0615 } ], "unanswered_rate": 0.0476, "slo": { "ok": false, "breaches": [ "error_rate", "unanswered_rate" ], "limits": { "error_rate": 0.01, "p95_ms": 3000, "unanswered_rate": 0.02 } } } ✔ 첫 주 · 답 못 함만 · 0.1s · 292 calls · $0.038550 → request POST /webhook/my-log-report { "from": "2026-10-19", "to": "2026-10-23" } ← response HTTP 200 { "total": 309, "errors": 0, "error_rate": 0, "p50_ms": 1252, "p95_ms": 2525, "by_route": { "자동 답변": 292, "담당자 연결": 17 }, "by_day": { "2026-10-19": { "total": 73, "errors": 0, "error_rate": 0 }, "2026-10-20": { "total": 57, "errors": 0, "error_rate": 0 }, "2026-10-21": { "total": 60, "errors": 0, "error_rate": 0 }, "2026-10-22": { "total": 55, "errors": 0, "error_rate": 0 }, "2026-10-23": { "total": 64, "errors": 0, "error_rate": 0 } }, "by_release": { "1.0.0": { "answers": 292, "repeats": 16, "repeat_rate": 0.0548 } }, "steps": { "faq_ms": { "runs": 309, "p50": 27, "p95": 39 }, "answer_ms": { "runs": 292, "p50": 1200, "p95": 2470 } }, "cost_usd": 0.03855, "cost_per_run": 0.000125, "llm_calls": 292, "failures": [], "unanswered_topics": [ { "topic": "와이파이", "count": 17 } ], "anomalies": [], "repeat_topics": [ { "topic": "프린터", "answers": 45, "repeats": 4, "repeat_rate": 0.0889 }, { "topic": "VPN", "answers": 59, "repeats": 4, "repeat_rate": 0.0678 }, { "topic": "비밀번호", "answers": 69, "repeats": 4, "repeat_rate": 0.058 }, { "topic": "접수 현황", "answers": 40, "repeats": 2, "repeat_rate": 0.05 }, { "topic": "메일", "answers": 42, "repeats": 2, "repeat_rate": 0.0476 } ], "unanswered_rate": 0.055, "slo": { "ok": false, "breaches": [ "unanswered_rate" ], "limits": { "error_rate": 0.01, "p95_ms": 3000, "unanswered_rate": 0.02 } } } ✔ 기준을 바꾸면 · 첫 주 · 0.1s · 292 calls · $0.038550 → request POST /webhook/my-log-report { "from": "2026-10-19", "to": "2026-10-23", "slo": { "unanswered_rate": 0.06 } } ← response HTTP 200 { "total": 309, "errors": 0, "error_rate": 0, "p50_ms": 1252, "p95_ms": 2525, "by_route": { "자동 답변": 292, "담당자 연결": 17 }, "by_day": { "2026-10-19": { "total": 73, "errors": 0, "error_rate": 0 }, "2026-10-20": { "total": 57, "errors": 0, "error_rate": 0 }, "2026-10-21": { "total": 60, "errors": 0, "error_rate": 0 }, "2026-10-22": { "total": 55, "errors": 0, "error_rate": 0 }, "2026-10-23": { "total": 64, "errors": 0, "error_rate": 0 } }, "by_release": { "1.0.0": { "answers": 292, "repeats": 16, "repeat_rate": 0.0548 } }, "steps": { "faq_ms": { "runs": 309, "p50": 27, "p95": 39 }, "answer_ms": { "runs": 292, "p50": 1200, "p95": 2470 } }, "cost_usd": 0.03855, "cost_per_run": 0.000125, "llm_calls": 292, "failures": [], "unanswered_topics": [ { "topic": "와이파이", "count": 17 } ], "anomalies": [], "repeat_topics": [ { "topic": "프린터", "answers": 45, "repeats": 4, "repeat_rate": 0.0889 }, { "topic": "VPN", "answers": 59, "repeats": 4, "repeat_rate": 0.0678 }, { "topic": "비밀번호", "answers": 69, "repeats": 4, "repeat_rate": 0.058 }, { "topic": "접수 현황", "answers": 40, "repeats": 2, "repeat_rate": 0.05 }, { "topic": "메일", "answers": 42, "repeats": 2, "repeat_rate": 0.0476 } ], "unanswered_rate": 0.055, "slo": { "ok": true, "breaches": [], "limits": { "error_rate": 0.01, "p95_ms": 3000, "unanswered_rate": 0.06 } } } ✔ 고친 뒤 · 오류 · 답 못 함 기준은 지킴 · 0.2s · 10 calls · $0.000000 → request POST /webhook/my-log-report { "tag": "after", "source": "live" } ← response HTTP 200 { "total": 10, "errors": 0, "error_rate": 0, "p50_ms": 2342, "p95_ms": 3560, "by_route": { "자동 답변": 10 }, "by_day": { "2026-10-31": { "total": 10, "errors": 0, "error_rate": 0 } }, "by_release": { "1.1.0": { "answers": 10, "repeats": 0, "repeat_rate": 0 } }, "steps": { "faq_ms": { "runs": 10, "p50": 1238, "p95": 1278 }, "answer_ms": { "runs": 10, "p50": 1103, "p95": 2282 } }, "cost_usd": 0, "cost_per_run": 0, "llm_calls": 10, "failures": [], "unanswered_topics": [], "anomalies": [], "repeat_topics": [], "unanswered_rate": 0, "slo": { "ok": false, "breaches": [ "p95_ms" ], "limits": { "error_rate": 0.01, "p95_ms": 3000, "unanswered_rate": 0.02 } } } Passed 4/4 report: runs/lab03-slo-20261031-075213.json $ uv run tools/flow.py call my-log-report '{"tag": "after", "source": "live"}' HTTP 200 · 0.0s { "total": 10, "errors": 0, "error_rate": 0, "p50_ms": 2342, "p95_ms": 3560, "by_route": { "자동 답변": 10 }, "by_day": { "2026-10-31": { "total": 10, "errors": 0, "error_rate": 0 } }, "by_release": { "1.1.0": { "answers": 10, "repeats": 0, "repeat_rate": 0 } }, "steps": { "faq_ms": { "runs": 10, "p50": 1238, "p95": 1278 }, "answer_ms": { "runs": 10, "p50": 1103, "p95": 2282 } }, "cost_usd": 0, "cost_per_run": 0, "llm_calls": 10, "failures": [], "unanswered_topics": [], "anomalies": [], "repeat_topics": [], "unanswered_rate": 0, "slo": { "ok": false, "breaches": [ "p95_ms" ], "limits": { "error_rate": 0.01, "p95_ms": 3000, "unanswered_rate": 0.02 } } } $ uv run tools/flow.py test cases/lab02-challenge.json POST http://localhost:5678/webhook/my-log-report · 5 case(s) × 1 ✔ 두 주 · 다시 묻는 비율이 가장 높은 주제 · 0.1s · 596 calls · $0.078360 ✔ 두 주 · 수로는 비밀번호가 가장 많지만 비율은 2위 · 0.1s · 596 calls · $0.078360 ✔ 두 주 · 다시 물은 주제는 6개 · 0.1s · 596 calls · $0.078360 ✔ 첫 주 · 설치는 다시 묻지 않음 · 0.1s · 292 calls · $0.038550 ✔ 앞의 지표는 그대로 · 0.1s · 596 calls · $0.078360 Passed 5/5 report: runs/lab02-challenge-20261031-075213.json