Skip to content

Judge agent request outcome (completed/failed) via LLM instead of tool-failure counting#19185

Merged
jvcalderon merged 5 commits into
operations/actions-timeline-7from
operations/actions-timeline-8
Jul 14, 2026
Merged

Judge agent request outcome (completed/failed) via LLM instead of tool-failure counting#19185
jvcalderon merged 5 commits into
operations/actions-timeline-7from
operations/actions-timeline-8

Conversation

@jvcalderon

@jvcalderon jvcalderon commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Description

Until now, whether a tracked agent request ended up completed or failed was decided mechanically, purely by counting tool call failures (resolveFinalRequestStatus). That criterion is wrong in both directions: a tool call can fail and still have the user's actual goal met some other way (false failed), and every tool call can technically succeed without ever delivering what the user asked for (false completed).

The core change in this PR is a new function, generateRequestOutcome (agentRequests/helpers.ts), that asks the LLM to judge - once per request finalization, not per tool call - whether the user's underlying goal was actually achieved, based on the request's full action timeline (user messages, tool calls and their outcomes) plus the agent's final reply. resolveFinalRequestOutcome (agentRequests/crud.ts) wires this judgment into the three places a request can finish (chat stream, webhook chat, escalation resume), falling back to the old mechanical criteria only if the LLM call itself fails.

On top of that core change, this PR also fixes issues found while wiring the judge into the escalation resume path:

  • Bug fix: the judge's needs_input short-circuit also fired during escalation resume, where the request is always in needs_input at that point - so an approved escalation never actually resolved the request, leaving it stuck. Fixed with an isHumanResponse flag (mirroring the one already on updateRequestStatus).
  • Semantics: a human rejecting an escalation is no longer mechanically forced to completed - it now goes through the same LLM judgment as any other finalization, since a rejection is a legitimate outcome but not automatically a success or a failure.
  • Semantics: a request can have several escalations raised over its lifetime. Resolving one of them no longer finalizes the request while others are still pending a human response.
  • Hardened the judge's system prompt against prompt injection from tool outputs/final response text, and made the chat-stream conversation save run in parallel with the (LLM-backed) judgment instead of behind it.

Screen recording

Judge as completed

Screen.Recording.2026-07-09.at.17.48.47.mov

Judge as failed

Screen.Recording.2026-07-09.at.17.51.04.mov

Launchcontrol

Agent requests are now marked completed or failed based on whether the user's actual goal was achieved, judged by the AI itself from the full record of what happened - not just by whether every tool call technically succeeded.

resolveFinalRequestOutcome's needs_input short-circuit also fired in the
escalation resume path, where the request is always in needs_input at
that point - so an approved escalation never actually resolved the
request. Add isHumanResponse so a resume can judge through needs_input,
mirroring updateRequestStatus.

Also fixes two semantics: a human rejecting an escalation is no longer
forced to completed mechanically, it now goes through the same LLM
judgment; and resolving one escalation no longer finalizes a request
that still has other escalations pending a human response.
@github-actions github-actions Bot added the size/l label Jul 9, 2026
@jvcalderon jvcalderon changed the title Fix request outcome judgment for escalation resolutions Judge agent request outcome (completed/failed) via LLM instead of tool-failure counting Jul 9, 2026
@jvcalderon jvcalderon self-assigned this Jul 9, 2026
@jvcalderon
jvcalderon marked this pull request as ready for review July 9, 2026 15:56

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread packages/server/src/sdk/workspace/ai/agentRequests/helpers.ts
Comment thread packages/server/src/sdk/workspace/ai/agentRequests/crud.ts
…RequestOutcome

The try/catch also wrapped the initial tryGet and pending-escalation
lookup, so a failure in either fell back to a mechanical
completed/failed status without knowing whether the request was still
waiting on a human. Narrow the fallback to generateRequestOutcome
failures only, and let guard-query failures propagate.
Comment thread packages/server/src/sdk/workspace/ai/agentRequests/crud.ts
Comment thread packages/server/src/sdk/workspace/ai/agentRequests/crud.ts
@jvcalderon
jvcalderon merged commit 4296cf7 into operations/actions-timeline-7 Jul 14, 2026
33 checks passed
@jvcalderon
jvcalderon deleted the operations/actions-timeline-8 branch July 14, 2026 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants