These are ADK-based evaluations even when your team builds agents with LangGraph. Keep your agent in its current framework. Use the same eval JSON, Python scorer, and Harnest command in either project; Harnest adapts LangGraph responses into the ADK objects the scorer receives.
Decide what needs to be custom
Start from a working Harnest agent with its dependencies installed. Live evaluation uses the agent’s normal model and service configuration. The scorer below is deterministic and makes no additional model or service calls.
1. Add the scorer
Use the root agent’slib/ directory for scoring code. Keep only eval set JSON and the shared configuration under evals/.
lib/eval_metrics.py
1.0 when both terms are present and 0.0 otherwise. The conversation score is the mean of its turn scores. With a threshold of 1.0, every turn must satisfy the rule. A lower threshold permits some turns to fail.
This is a text-presence check, not a factuality check: an incorrect answer that mentions both terms still passes. Replace the scoring rule with your actual product contract, or combine it with a reference or judge metric. See the custom metric API for the full input and result contract.
2. Describe the test cases
evals/location-answers.evalset.json
userContent to your real agent. The authored finalResponse is a golden reference, not the actual output and not an answer injected into the agent. This scorer checks the actual output; reference-based metrics can also use the golden answer.
The filename stem must match eval_set_id. Add further cases to cover the behavior you care about. Put sequential turns inside one case for multi-turn evaluation; separate cases do not stand in for a shared conversation.
3. Register the metric and threshold
evals/test_config.json
criteria and customMetrics. Harnest compiles root lib/ modules under harnest.lib, so the registered path differs from the local unit-test import below.
If test_config.json already exists, merge this criterion and registration into it. Do not create a second config or replace existing quality checks. You can use built-in and custom metrics in the same criteria object.
4. Unit-test the scorer
Test passing, failing, missing-response, and multi-turn inputs before running the live agent. These tests evaluate only your scorer and require no model credentials.tests/unit/test_eval_metrics.py
5. Run the eval and inspect evidence
--no-output for quiet terminal output while retaining the file.
Find required_location_terms in each case’s overallEvalMetricResults. Inspect evalMetricResultPerInvocation for the turn scores, actual answers, and available reference answers supplied by the scorer. The command fails when the quality gate fails. See Run and inspect results for result fields and CI handling.
Extend the rule safely
- Inspect
intermediate_datawhen your rule needs captured tool calls or results; do not infer tool execution from answer text alone. - Use the full
actuallist to inspect a conversation-level rule. Keep overall and per-turn scores consistent; ADK’s command gate averages the scored turn results. See score aggregation before implementing a final-turn-only metric. - Handle
expected=Nonefor simulated conversations. Add a conversation scenario when you need generated user turns. - For LLM judgment, prefer a built-in rubric metric where it fits. Arbitrary network or model calls inside your Python scorer do not automatically inherit Harnest’s judge transport adapter; configure and clean up those clients explicitly.