You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c9a9100
Browse filesBrowse the repository at this point in the historyBrowse files
feat(gooddata-eval): record why an agentic simulated-user loop stopped
Every agentic evaluator drives a loop that can exit several ways, but the result
only ever recorded *whether* the agent produced its output. A run that ran out of
turns while doing the right thing was reported identically to one that refused,
and identically to one that answered wrongly.
It is worse than a missing field, because the downstream checks are all of the
form `produced_output and <check>`. An exhausted alert run reports
operator_correct, threshold_correct, metric_correct and recipients_correct as
False -- four specific-sounding content failures for work the agent was never
given the chance to attempt.
Adds `LoopExit` (core/models.py) and threads it through all five loops, plus
`turns_used`/`max_iterations` in `detail`:
success the agent produced its output
agent_silent neither text nor a tool call -- genuinely stuck
budget_exhausted hit max_iterations; says nothing about being on track
simulated_user_failed OUR simulated-user model failed, not the agent
chat_error the chat call raised mid-conversation (kda partial path)
not_run the loop never started (conversation $ref skip)
The default is BUDGET_EXHAUSTED and every other exit assigns explicitly, so a loop
that simply runs out of range() is labelled correctly with no trailing else.
Two exits were previously invisible and are the reason this is worth doing:
- metric_skill catches SimulatedResponseError and breaks. A harness-side outage
was scored against the product as metric_created=False/maql_correct=False.
- kda_skill breaks on a chat error with a partial result.
Deliberately NOT included:
- No verdict changes. An exhausted run still fails. The point is that the cases
become countable, not that any of them start passing.
- No change to any max_iterations default (4-7, already tuned per kind). Whether
a budget is too tight becomes answerable from data instead of argued -- which is
the actual ask behind GDAI-2200, where ~13% of alert runs are estimated to need
7 turns against a ceiling of 6. Raising the ceiling first would have hidden the
interaction with GDAI-2199's MANDATORY STOPs, which make prescribed
end-turn-without-a-tool-call behaviour consume budget.
- No try/except added to alert_skill's simulated-user call: there a failure
already propagates as a hard error rather than being swallowed, which is the
behaviour we want. Only metric_skill needed the label.
Tests: existing detail assertions extended across all five kinds, plus dedicated
coverage for budget_exhausted vs agent_silent vs success (including the turn the
tool landed on), simulated_user_failed, and a regression guard asserting that two
runs with identical scored booleans differ only in exit_reason -- the exact
ambiguity this removes.
739 passed; ruff check clean.
0 commit comments