Repository navigation
QA Lab · Test TravelMind end to end and gate the release #38
akash-coded
started this conversation in
Hands-on Labs
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Hands-on QA Lab: test TravelMind end to end
You are the QA engineer on TravelMind, an airline booking-exception agent. A
teammate wants to ship a prompt change. Your job is to prove the build is safe
before it reaches customers, using the four QA disciplines, and to produce a
sign-off you would stand behind.
You will write the QA yourself. By the end you will have run the full loop:
tests, evaluation, observability, and a gate that blocks a bad build.
travelmind_agent.pyandconfig.py, AWS credentials for the model stagesThe agent under test
TravelMind has three tools, all plain functions that the agent wraps with
tool(...)at wiring time:lookup_booking(pnr){pnr, status, flight, date};statusis one of CONFIRMED, CANCELLED, DELAYED, NOT_FOUNDget_disruption_reason(pnr){pnr, reason, detail};reasonis None for a healthy bookingget_rebooking_options(pnr){flight, dep}; empty list means noneFixed test data:
JX48Q2is CANCELLED (weather),AB12CDis CONFIRMED,DL99XYis DELAYED (crew), anything else is NOT_FOUND.Run it (Local track):
Run it (AgentCore track): wrap the same agent as a Runtime entrypoint and
invoke it. The agent logic does not change; only how it is hosted does.
AgentCore entrypoint and deploy (click to expand)
agentcore configure -e travelmind_runtime.py agentcore launch agentcore invoke '{"prompt": "Status of PNR JX48Q2?"}'No kit? Minimal stand-in agent (click to expand)
Save this as
travelmind_agent.pyand you can do every lab.Key concepts you will use
Four ideas show up in every lab. Learn the vocabulary once.
Golden set. A fixed list of test inputs, each with acceptance criteria
instead of an exact expected answer. An agent has no single right reply, so you
cannot diff against a fixed string. You check properties: the reply must mention
"cancelled", must not mention a flight number for a bad PNR, and so on. The
golden set is your regression baseline; you re-run it on every change.
Facts. The ground truth you hand an LLM judge so it is not guessing. If you
ask a model to grade whether a reply is correct, the model needs to know what
correct is. The facts are the real tool outputs ("JX48Q2 is CANCELLED due to
weather; options AI-318, 6E-552"). A judge without facts grades vibes.
LLM-as-judge. A stronger model scores a reply against a short rubric, for the
things a substring cannot check: completeness, tone, no invention. It is triage,
not an oracle. You keep it honest by grounding it with facts, constraining it to
JSON output, and calibrating it against human labels.
The stages of QA. QA is not one step at the end. It threads the lifecycle:
Lab 1 - Tool-contract tests (deterministic, no AWS)
Goal. Catch a broken tool before the agent ever runs.
Concept. A contract is a tool's promised shape (which keys) and range
(which values). The agent is built on that promise. These tests run with no model
and no cloud, so they go on every commit.
Your task. Create
test_contracts.pywith assertions that:lookup_booking("JX48Q2")returns the keys pnr, status, flight, date.get_rebooking_optionsreturns a list whose items have flight and dep.Hint
Run with
pytest test_contracts.py -q.Done when.
pytest test_contracts.pyis green, with no AWS configured.Reveal a fuller solution
Lab 2 - Behaviour and trajectory tests (real model)
Goal. Check what the agent decides, not what it says word for word.
Concept. The model is non-deterministic, so the wording changes run to run.
Never assert an exact string. Assert observable, stable properties: which tools
were called (the trajectory) and the end state. To see the tools, wrap each one
in a spy that records its name. These are integration tests; they need a real
model and run on a prompt or model change, not on every commit.
Your task. Spy the tools, run the agent on a rebooking request, and assert:
lookup_bookingwas called (it checked before acting), andRun it on three seeds and require the invariant to hold every time.
Hint
Done when. The test passes on all three seeds. If it flakes, you are probably
asserting wording somewhere; assert a property instead.
Reveal
Multi-agent note: if a supervisor routes to specialist sub-agents, spy the
specialists the same way and assert reachability and end state, not order.
A Graph has fixed edges so you can assert a node completed; a Swarm decides
hand-offs at runtime so order is not guaranteed.
Lab 3 - Golden set and deterministic evaluation
Goal. Turn "seems fine" into a number you can compare.
Concept. Write a golden set: inputs with criteria, not answers. Three
rule types cover most cases:
must: every phrase must appear.any_of: at least one phrase must appear (for several acceptable phrasings).must_not: no phrase may appear (this catches an invented flight).Your task.
golden_set.jsonl: a disruptionquestion, a rebooking question, and a bad-PNR safety case.
substring_check(reply, case)that applies the rules.Pure means it takes a string and a case and returns a boolean; it does not call
the agent. The agent call is the part that needs AWS; keep it separate.
Hint
{"id": "g1", "input": "Is PNR JX48Q2 affected?", "must": ["cancelled", "weather"], "must_not": ["confirmed"]} {"id": "g2", "input": "Rebooking options for JX48Q2?", "any_of": ["ai-318", "6e-552"]} {"id": "g3", "input": "Rebook PNR ZZZZZZ.", "any_of": ["not found", "could not find"], "must_not": ["ai-3"]}Done when. You can print something like
pass rate 100% (3/3). Then break acase on purpose (change a
mustto a word the agent will not say) and watch therate drop. That drop is the regression signal.
Reveal the run loop
Lab 4 - LLM-as-judge with facts
Goal. Grade what a substring cannot: did the reply explain the cause and
offer an option, without inventing anything.
Concept. Ask a stronger model to score the reply 1 to 5 against a rubric.
Ground it with facts so it is not guessing. Constrain it to JSON so you can
parse a number. Watch three biases:
Your task. Write
judge(question, reply, facts, focus)that returns{"score": int, "reason": str}, then grade this case:Hint
Done when. A good reply scores 4 or 5; a reply you deliberately cripple (force
the agent to skip the options) scores lower. The judge moved with quality.
Reveal: grade a case, plus the third grader (RAGAS)
For answers grounded in a knowledge base (a refund policy, say), use RAGAS
faithfulness: the fraction of claims in the reply the retrieved context
supports. It needs the retrieved chunks, so it does not apply to the pure
booking flow.
Lab 5 - Observability and cost
Goal. Localise a failing run to one span, and read cost as a quality signal.
This is the lab where the two tracks differ.
Concept. You cannot step-debug a non-deterministic agent. You read traces.
The hierarchy is Session -> Trace -> Span: a session holds traces, a trace
holds spans, and each span is one model call or one tool call with its input,
output, latency, and tokens. Spans land in the CloudWatch Logs group
aws/spans.A cost spike is usually retries or a loop, which is a quality bug, so you alarm on
cost the way you alarm on errors.
Setup differs by track
aws-opentelemetry-distroto requirements, launch withopentelemetry-instrument python -m travelmind_agentaws/spansaws/spansYour task.
aws/spansfor failed tool spans.Hint: the query and the cost helper
Logs Insights query (run against the
aws/spanslog group):Run a broad
fields @message | limit 5first to confirm your real field names;paths follow the OpenTelemetry GenAI conventions and can vary by setup.
Cost from tokens (prices are USD per 1M tokens):
Token counts are on the span, and locally on
result.metricsfrom a Strands run.Done when. You can point at a specific tool span and say "this is where it
failed", and you can state the cost of a typical resolution in dollars.
Reveal: query from Python and find the failing span
The classic finding: a tool span with status ERROR sitting next to a normal final
model span. The tool failed, the model answered anyway. Fix by returning tool
errors to the model and adding a post-condition check before claiming success.
Lab 6 - Quality gate and sign-off (the capstone)
Goal. Compose Labs 1 to 5 into one decision: promote or block. Then run the
real scenario that started this lab.
Concept. A gate reads the numbers the earlier stages produced, checks each
against an agreed threshold, and exits non-zero to block a deploy if any bar
is missed. A gate that only warns is not a gate. It also writes a sign-off: the
artifact proving a specific build cleared every bar.
The bars to start with (agree them with the client):
Your task.
quality_gate.pythat loadstest_report.json,eval_report.json, andcost_latency.json, checks the thresholds, writessignoff_report.md, andexits 1 on any failure.
88%. Run the gate. It must block. Restore the line that offers options (back to
94%). Run again. It must pass and sign off.
Hint: the gate skeleton
Done when. Two runs, two outcomes from the same gate: v7 blocked (exit 1), the
fix passed (exit 0), and
signoff_report.mdwritten for the passing build.Reveal: writing the sign-off and the regression scenario
The regression scenario, in the eval harness:
Put it together: the end-to-end run
The stages connect through small JSON reports. Each writes one; the gate reads
all three. That file contract is why a stage can run on a different machine or at
a different time and the gate still works.
A pipeline runs them in order: tests, eval, observability, gate. Run the cheap
deterministic layers on every commit, the model and judge layers on change and on
a schedule, and the gate before every promotion.
Self-check
You have completed end-to-end QA when you can answer yes to all of these.
aws/spans.A simple scoring guide for the workshop: one point per box, plus one bonus point
for any stretch goal below. Six or more out of seven is a pass.
Stretch goals
(B, A) and average to cancel position bias.
Lab 5, write a case that would have caught it, and add it to the set.
CloudWatch alarm you would set on it.
the right specialist was reached for a rebooking request.
Common errors and fixes
us.prefix on the model idaws/spansare emptysys.exit(1)when any check failsAll reactions