fix(evals): include agent output in AgentRunHistory [AE-2147] - #1894
Open
rakesh-uipath wants to merge 3 commits into
Open
fix(evals): include agent output in AgentRunHistory [AE-2147]#1894rakesh-uipath wants to merge 3 commits into
rakesh-uipath wants to merge 3 commits into
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The legacy evaluator still omits supplied output for runs with no trace spans.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Fixes {{AgentRunHistory}} so trajectory evaluators include the agent’s final output.
Changes:
- Appends workload output to serialized traces.
- Updates modern and legacy trajectory evaluators.
- Adds regression tests.
- Bumps version to 2.14.15.
File summaries
| File | Summary |
|---|---|
packages/uipath/uv.lock |
Updates locked package metadata. |
packages/uipath/tests/evaluators/test_trajectory_agent_output.py |
Adds evaluator regression coverage. |
packages/uipath/tests/evaluators/test_evaluator_helpers.py |
Tests trace output serialization. |
packages/uipath/src/uipath/eval/evaluators/llm_judge_trajectory_evaluator.py |
Passes agent output into judge history. |
packages/uipath/src/uipath/eval/evaluators/legacy_trajectory_evaluator.py |
Passes output into legacy history, but empty-trace runs still need correction. |
packages/uipath/src/uipath/eval/_helpers/evaluators_helpers.py |
Serializes and appends agent output. |
packages/uipath/pyproject.toml |
Bumps the package version. |
Review details
- Files reviewed: 6/7 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+140
to
+144
| @@ -139,7 +141,7 @@ def _create_evaluation_prompt( | |||
| and agent_run_history | |||
| and isinstance(agent_run_history[0], ReadableSpan) | |||
| ): | |||
| agent_run_history = trace_to_str(agent_run_history) | |||
| agent_run_history = trace_to_str(agent_run_history, workload_output) | |||
🚨 Heads up:
|
rakesh-uipath
added a commit
that referenced
this pull request
Sep 10, 2026
The span-list guard in LegacyTrajectoryEvaluator required a first
element, so a run that answered without calling a tool fell through to
str([]) and lost {{AgentRunHistory}} all over again -- the same omission
AE-2147 is about, just on the no-tool path. Route an empty span list
through trace_to_str whenever there is an output to append, and keep the
old '[]' rendering when there is none.
Found by Copilot review on #1894.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
trace_to_str() rendered only spans carrying a `tool.name` attribute, so
`{{AgentRunHistory}}` reached the trajectory judge as a tool-call
transcript with the agent's own answer missing. The trajectory judges
have no second channel for it — `actual_output_placeholder` IS
`{{AgentRunHistory}}` — so the judge graded every run as if the agent
had produced nothing, and marked correct runs down for "never produced
an answer".
Pass the workload output through to trace_to_str and append it as a
final "Agent Output" block, from both the LLM-judge and the legacy
trajectory evaluator. LLM spans stay unrendered on purpose: they carry
the full system prompt and would swamp the judge's context
(test_legacy_trajectory_prompt_uses_compact_tool_history pins that).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sonar's quality gate wanted 90% on new code and got 85.7%. The two uncovered lines were the non-JSON-serialisable fallback in _format_workload_output and the new argument inside LegacyTrajectoryEvaluator.evaluate, which no test reached. The second one is worth having regardless: it asserts the agent output lands in the prompt the LLM is actually sent, not just in the string _create_evaluation_prompt returns. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The span-list guard in LegacyTrajectoryEvaluator required a first
element, so a run that answered without calling a tool fell through to
str([]) and lost {{AgentRunHistory}} all over again -- the same omission
AE-2147 is about, just on the no-tool path. Route an empty span list
through trace_to_str whenever there is an output to append, and keep the
old '[]' rendering when there is none.
Found by Copilot review on #1894.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rakesh-uipath
force-pushed
the
fix/ae-2147-trajectory-agent-output
branch
from
September 10, 2026 17:34
6f87333 to
a6a24fe
Compare
|
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.



Fixes AE-2147 — reported by James Dickson in #help-agent-builder, filed by Maria Vimer.
The bug
{{AgentRunHistory}}reaches the trajectory judge as a tool-call transcript with the agent's own output missing, so the judge grades an incomplete trace.It is real, and it is one predicate:
https://github.com/UiPath/uipath-python/blob/30f6bec2/packages/uipath/src/uipath/eval/_helpers/evaluators_helpers.py#L653
A span without
tool.nameis skipped, and the docstring said so out loud: "Only processes tool spans". The workload's own answer lives onWorkloadExecution.workload_output(populated inruntime.py:1143) and never entered the string.There is no second channel for it. On
BaseLLMTrajectoryEvaluatorthe actual-output placeholder is the history:So the judge never saw the output at all — while its own system prompt promises it "a trace/history of the agent's actions and outputs".
Reproduced against James's run (one
Web_Searchtool span, agent answered correctly). Before:Byte-for-byte what his screenshot shows. The judge scored it 10% with the justification "It never produced a user-facing answer identifying Argentina as the most recent World Cup winner" — while the Actual Output panel on the same screen read
{"search_results_answer": "Argentina won the most recent FIFA World Cup (Qatar 2022)..."}. The agent was right and got marked down for the serialiser's omission.The fix
trace_to_strtakes the workload output and appends it as a final block; both trajectory evaluators pass it.Fixed in
LLMJudgeTrajectoryEvaluator/LLMJudgeTrajectorySimulationEvaluatorand inLegacyTrajectoryEvaluator, which had the same defect through the same helper.Deliberately not changed
Intermediate assistant messages are still not rendered. LLM spans carry the full system prompt, and
test_legacy_trajectory_prompt_uses_compact_tool_historyexists precisely to keep a 10k-char prompt out of the judge's context. Surfacing intermediate reasoning needs a bounded projection of the LLM spans, not a filter removal — worth doing, separate change. James's other asks in that thread (documenting what each{{...}}binds to in the evaluator UI, eval-driven judge authoring) are product work, not this.workload_output=Nonekeeps the old behaviour, so no existing caller changes shape.Tests
packages/uipath/tests/evaluators/test_trajectory_agent_output.py— reproduces the AE-2147 run through both evaluators and asserts the answer reaches the prompt. Both fail onmain:Plus five cases on
trace_to_stritself intest_evaluator_helpers.py(ordering, str vs dict output, omitted output, empty output).Verification
Ran locally, all from
packages/uipath:uv run pytest— green, exit 0uv run ruff check .— All checks passeduv run ruff format --check .— 335 files already formatteduv run mypy --config-file pyproject.toml .— no issues in 335 source filesuv run python scripts/lint_httpx_client.py— cleanVersion bumped 2.14.14 → 2.14.15; 2.14.14 is already on PyPI so
check-version-availabilitywould have failed otherwise.🤖 Generated with Claude Code