Skip to main content
Turn a business rule into a repeatable evaluation. This walkthrough checks that each answer contains two required location terms and saves the scored result.
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 with a working agent and installed dependencies. Evaluation calls the agent’s configured model and services; this deterministic scorer makes no additional calls.

1. Add the scorer

Use the root agent’s lib/ directory for scoring code. Keep only eval set JSON and the shared configuration under evals/.
lib/eval_metrics.py
Each answer scores 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 checks text presence, not accuracy: an incorrect answer mentioning both terms passes. Adapt the rule or combine it with a reference or judge metric. See the custom metric API.

2. Describe the test cases

evals/location-answers.evalset.json
Harnest sends userContent to the agent and scores its response. finalResponse is a golden reference for reference-based metrics; it is never injected into the agent. 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
Use the same metric key in criteria and customMetrics. Harnest compiles root lib/ modules under harnest.lib, so the registered path differs from the local unit-test import below. Merge the criterion and registration into an existing test_config.json without replacing other checks.

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
See Testing and compilation for the authored unit-test lane and imports.

5. Run the eval and inspect evidence

Use this command for either an ADK or a LangGraph project; Harnest uses the configured agent framework. Unit tests run first. The live eval then runs the agent, calls your registered scorer, and writes the result. Add --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_data when your rule needs captured tool calls or results; do not infer tool execution from answer text alone.
  • Use the full actual list 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=None for 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.
A custom scorer is trusted Python code executed during evaluation. It can access the process environment and call external systems. Review implementations before running them, and do not put credentials into eval files or return them as diagnostic evidence.