Skip to content

Fix cross-app agent delegation misreporting resolution failures as outages - #5024

Open
builder-io-integration[bot] wants to merge 1 commit into
mainfrom
ai_main_5f0c011f4d2144fabc43
Open

builder-io-integration[bot] wants to merge 1 commit into
mainfrom
ai_main_5f0c011f4d2144fabc43

Conversation

@builder-io-integration

@builder-io-integration builder-io-integration Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes findAgent to resolve singular/plural handle variants (e.g. plansplan) and makes unresolvable delegation targets throw a typed, logged, telemetry-tracked error instead of returning a plain Error: ... string.

Problem

Factory item 4ea92872812afebae7b3c90322155307cd37b64d8a34cb67c6c15f458c803a56 (Slack thread) reported that when the Brain app tried to delegate to agent:plans, it failed and the model told the user "The Plans app is temporarily unavailable," then silently fell back to writing a knowledge doc.

Root cause: findAgent only matched handles exactly, so agent="plans" missed the Plan app, which is registered with id plan even though its own sidebar, nav state, and skills all label it "Plans." When resolution failed, call-agent returned a plain Error: ... string rather than throwing. Because the agent loop scores a returned string as a successful tool call (no isError), this failure was invisible in both logs and telemetry, and the model was free to invent a plausible-sounding excuse ("temporarily unavailable") for what was actually a naming/registration mismatch. This is a systemic issue: twelve of thirteen first-party apps had the same latent singular/plural mismatch.

Solution

  • Resolve the singular/plural variant of a requested handle when the exact match fails, but refuse to guess if two distinct agents differ only by a trailing "s".
  • Replace the silent Error: ... string return with a thrown, typed agent_not_found error that is logged and reported via $a2a_invocation telemetry, and whose message explicitly tells the model this is a target-resolution failure, not an outage.

Key Changes

  • Added agentHandleNumberVariant in agent-discovery.ts to compute the singular/plural counterpart of a handle, returning null when the swap would be meaningless (empty string or already ending in "ss").
  • Updated findAgent to fall back to the number-variant match when no exact match is found, only returning a result if exactly one agent matches the variant.
  • Added unresolvableAgentTargetError in call-agent.ts to build an A2AInvocationError (agent_not_found) that logs the unresolved target and connected agents, emits $a2a_invocation telemetry with status: "error", and instructs the model not to describe the target as unavailable/down.
  • call-agent's run now throws this error instead of returning a string when the delegation target can't be found.
  • Added regression tests covering: resolving plansplan, resolving every built-in agent from its other grammatical number, leaving genuinely unknown handles unresolved, refusing to guess between ambiguous report/reports-style agents, and asserting the new thrown error is logged and tracked correctly instead of being scored as a successful call.
  • Added a changeset documenting the fix.

Edit in Builder  Preview


To clone this PR locally use the Github CLI with command gh pr checkout 5024

You can tag me at @BuilderIO for anything you want me to fix or change

…udly when unresolvable

findAgent matched an agent handle exactly, so agent="plans" missed the plan
app even though the Plan app labels itself "Plans" in its own sidebar, nav
state, and skills. Twelve of thirteen first-party apps had the same latent miss
in one grammatical number or the other.

call-agent then returned the miss as a plain "Error: ..." string. The agent
loop scores a returned string as a successful tool call, and the early return
happened before the tracked call began, so the failure produced no isError, no
loop-breaker entry, and no $a2a_invocation row. Handed a successful result
containing prose, the model retold it as "The Plans app is temporarily
unavailable" and fell back to writing a knowledge doc.
@builder-io-integration builder-io-integration Bot changed the title fix: resolve cross-app delegation targets by name variant and surface unresolvable targets as real errors Fix cross-app agent delegation misreporting resolution failures as outages Sep 15, 2026

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Builder reviewed your changes and has a few items to flag 🟡

Review Details

Code Review Summary

PR #5024 updates shared cross-app delegation in @agent-native/core: findAgent now resolves a singular/plural handle variant after exact matching, while refusing ambiguous trailing-s candidates, and unresolved call-agent targets now throw a typed agent_not_found error with logging and $a2a_invocation telemetry. The approach is sound and addresses the reported false-outage behavior; the added discovery and delegation regressions cover the primary paths, and both review agents found no blocking correctness or compatibility issue.

Risk assessment: Standard, because this changes shared business logic and telemetry used across first-party apps. One telemetry accuracy issue remains: the unresolved-target helper hardcodes mode: "message", even though the same branch can be reached for direct actions and task polling. This is non-blocking but will misclassify those failures in analytics and omit task correlation.

✅ Exact-match precedence and ambiguity refusal are preserved.
✅ Errors now propagate as tool failures instead of successful-looking prose.
✅ Focused regression suites passed according to the review agents.

🧪 Browser testing: Attempted full verification; 0/16 cases could be verified because Chrome automation tools were unavailable, although the dev server and affected routes returned HTTP 200.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants