Skip to content

Agent Evaluations

Evals are the regression tests for agent behavior. A unit test checks that a tool returns the right value; an eval checks that the agent calls the right tool, with the right arguments, for a given question — the part a normal test can't see because it depends on the model.

They run a real LLM (the same one the agent uses) against a fixed set of prompts, with all external systems (Kafka, Kubernetes, Elasticsearch, HTTP) mocked. Because they cost tokens and need credentials, they're gated behind a pytest marker and skipped by default.


Running them

make eval                                            # all scenarios, every agent
uv run pytest agents/kafka-health/tests/ -m eval     # one agent

make eval needs LLM credentials — the same ones the agents use. With Vertex AI that's GOOGLE_GENAI_USE_VERTEXAI=TRUE + GOOGLE_CLOUD_PROJECT and working ADC; with the Gemini API it's GOOGLE_API_KEY. Without any, the eval skips (it does not fail), so make test stays credential-free.


What's scored

Each scenario asserts one metric:

Metric Threshold Meaning
tool_trajectory_avg_score 1.0 The tools the agent called (name and arguments, in order) must match the expected trajectory exactly.

The reference text answer in each scenario is documentation only — it is not scored, so it doesn't have to match word-for-word. Only the tool trajectory counts.


How a scenario is built

Each agent has an tests/evals/ folder with one or more *.test.json datasets and a test_config.json holding the criteria above. A scenario is a prompt plus the tool calls it should produce:

{
  "eval_id": "get_consumer_lag",
  "conversation": [
    {
      "user_content": { "parts": [{ "text": "What is the consumer lag for the order-processor group on the orders topic?" }] },
      "intermediate_data": {
        "tool_uses": [
          { "name": "get_consumer_lag", "args": { "group_id": "order-processor", "topic_name": "orders" } }
        ]
      }
    }
  ]
}

The runner (tests/test_<agent>_eval.py) points ADK's AgentEvaluator at that folder and mocks every external client the agent can touch before the model runs:

with (
    patch("kafka_health_agent.tools._get_admin_client", return_value=fake_broker),
    patch.object(strimzi_mod, "_custom_objects_api", return_value=MagicMock()),
):
    await AgentEvaluator.evaluate(
        agent_module="kafka_health_agent.agent", eval_dataset_file_path_or_dir=EVAL_DIR, num_runs=1
    )

The one rule that keeps evals green

Exact-trajectory matching is strict, so a scenario only passes if the agent behaves deterministically. Two things make that true:

  1. Mock every client the agent exposes — not just the obvious one. Most agents carry a second tool family (Strimzi, ECK, Kubernetes operators) beside their primary one. If those clients aren't mocked, the model can reach for an operator tool, hit live infrastructure, and add an unexpected call to the trajectory — failing the match non-deterministically. Mock the operator client too, even if the scenario "shouldn't" use it.

  2. Keep the agent's tool choice unambiguous. If a prompt legitimately admits two tool sets ("is the cluster healthy?" → protocol check or operator status), the model will pick differently across runs. The fix lives in the agent instruction, not the test: tell it which tool family owns which question (e.g. "use protocol tools for health; only use operator tools when the user asks about the operator") and to be surgical (call only what the question needs). A sharper instruction is a better product and a stable eval.

If a scenario flakes, run the prompt a few times and look at the actual trajectory before touching the dataset — decide whether the model's new behavior is genuinely correct (update the expected tool_uses) or ambiguous (tighten the instruction).


Adding a scenario

  1. Add a case to the agent's *.test.json (prompt + expected tool_uses).
  2. Make sure the runner mocks any client that case will exercise.
  3. uv run pytest agents/<agent>/tests/ -m eval and confirm it passes a couple of times — not just once.

See AEP-002: Agent Evaluation Framework for the original design.