feat(evals): name a fabricated answer as a fault, and stop crediting a wrong tool - #445
Merged
Merged
Conversation
…a wrong tool Diagnosis raises ungrounded_answer when an agent that had tools called none, did not say it could not answer, and still stated specifics — a count, a record id, a date — that no tool supplied. Where the scenario names an expected tool, expected_tool_not_called now says the same in its summary and carries ungrounded: true, so an invented answer no longer reads like an honest gap. Both faults reach the judge, which is where a suggested tool comes from. An agent with no tools at all is not flagged: it answers from its instructions by design, and whether that is acceptable is the judge's grade. tools_succeeded is awarded only for a tool the scenario expected (or any tool when it expects none): a wrong tool that ran without erroring scored higher than calling nothing. The judge reads 1,500 characters of a scenario's notes rather than 300, because a suite's rubric tends to put its "must not" clause last. Closes #433. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMSRnSxYS9mRx1hSjytB9Z
…-answer # Conflicts: # CHANGELOG.md
…-answer # Conflicts: # CHANGELOG.md
…-answer # Conflicts: # CHANGELOG.md
hayat01sh1da
pushed a commit
to hayat01sh1da/activeagent
that referenced
this pull request
Sep 14, 2026
Three changelog merges resolved with a script that dropped the entries sitting under a heading it took as common context, so main's Unreleased section carried an empty "### Added". Restores the five entries — the caller seam (activeagents#443), runtime schema tools (activeagents#447) and the fabrication fault (activeagents#445) — from the commits that introduced them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMSRnSxYS9mRx1hSjytB9Z
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #433.
Diagnosiscould not tell a grounded answer from an invented one. Measured on the issue's reproduction: an agent that refused honestly was flaggedmissing_capability, while one that answered "You have 3 open tickets: #412 Login bug (due Friday)…" with no tool call passed — and because no fault fired, the judge was never asked for the tool that would have grounded it.Re-checked against current
mainbefore changing anything: where a scenario declarestools:,expected_tool_not_calledalready fires and already reaches the judge, so that half of the issue is stale. What remained open: a scenario with no tool expectation (the common case for a pasted question list), the fact that the fault text could not distinguish an honest gap from a fabrication, and the scoring quirk where a wrong tool call outscored none.Change
ungrounded_answer— a new fault, raised when the agent had tools, called none, did not say it could not answer, and still stated specifics: a record id (#412), a date (2026-09-01), or a count of things (you have 3 open tickets,4 overdue invoices). The patterns are deliberately narrow — a number in prose (here are three options,within 30 days) is not a data claim, and a false positive here fails a scenario. It sits afterexpected_tool_not_called, before the content faults, and is inDEFAULT_REFINE_FAULTSso the judge is asked for a tool.expected_tool_not_callednames the fabrication when the answer stated specifics no tool supplied: the summary says so, the evidence carriesungrounded: trueand theclaim, and the recommendation says to treat the answer as invented rather than as a prompt-preference problem.task_completiongrade, not a mechanical rule. The PR description of Diagnosis cannot detect a fabricated answer, so no fault fires and the judge is never asked for a tool #433 wanted this row flagged too; the false-positive cost on instruction-answerable tasks is why it is not.tools_succeededis awarded only for an expected tool (or any tool when the scenario expects none). Previously a wrong tool that ran without erroring scored 0.80 against 0.75 for calling nothing.Not done: the judge-limit accounting (
DEFAULT_JUDGE_LIMIT = 25with nothing logging what was skipped). Worth its own change; it is a report-shape question.Testing
test/evals/diagnosis_test.rb(+6),scorer_test.rb(+2),runner_test.rb(+1, end to end through the judge to a suggested tool),judge_test.rb(+1, the rubric's last clause reaches the judge).bin/test test/evals/*_test.rb actionagent/test/scenario_evaluation_runner_test.rb actionagent/test/evaluation_evidence_test.rb— 156 runs, 926 assertions, 0 failures.bin/rubocopclean on the changed files. Docs: the fault tables indocs/framework/dashboard.mdanddocs/framework/evaluations.md.🤖 Generated with Claude Code
https://claude.ai/code/session_01XMSRnSxYS9mRx1hSjytB9Z