Warn instead of silently falling back on unknown agent#547
Open
wkramme wants to merge 1 commit into
Open
Conversation
wkramme
force-pushed
the
fix/warn-on-unknown-agent-fallback
branch
from
July 10, 2026 16:21
bb309be to
6cda225
Compare
invoke_agent silently substituted the default code-puppy agent when an unknown agent name was requested, so the call appeared to succeed and the result was mislabeled as the requested agent — the calling agent and the user had no way to know a substitution happened. Surface the fallback at every layer: - load_agent() emits a clear warning (no longer tells the end user to run list_agents()). - AgentInvokeOutput gains requested_agent_name and fell_back so the calling agent receives a structured signal (backward-compatible defaults). - _invoke_agent_impl detects fallback deterministically (requested name absent AND code-puppy present, mirroring load_agent), attributes the run to the actual agent across events/history/messages, prepends an [invoke_agent notice] to the response instructing the calling agent to tell the user the agent doesn't exist and offer to install-or-switch, and prefixes the error on the failure path. When no fallback exists, load_agent still raises. Adds get_registered_agent_names() helper; extends agent-manager and agent-tools tests (150 passing).
wkramme
force-pushed
the
fix/warn-on-unknown-agent-fallback
branch
from
July 10, 2026 16:56
6cda225 to
f347b31
Compare
wkramme
marked this pull request as ready for review
July 10, 2026 17:01
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.
TL;DR
Invoking an agent that doesn't exist currently looks like it works — you silently get
code-puppywearing the missing agent's name tag, and nobody is told. This PR keeps the graceful fallback but makes it honest: it warns, it re-labels the run truthfully, and — most importantly — it hands a structured "that agent doesn't exist, I used code-puppy instead" signal back to the calling agent so it can explain the situation to the user and offer to install-or-switch.The bug
load_agent()maps any unrecognized agent name tocode-puppywithout a peep, andinvoke_agentthen echoes the requested name back as if it ran:Repro
Why it hurts
list_agents()" warning talked past the user — that's a tool only the LLM can call; it's useless advice to a human.The fix — surface the fallback at every layer
code-puppy) is used in the invocation event, response message, session history, and success line — no more crediting a non-existent agent.AgentInvokeOutputgains two backward-compatible fields:requested_agent_name: str | None = Nonefell_back: bool = False[invoke_agent notice]telling the calling LLM to inform the user that the requested agent doesn't exist and offer to (a) install/create it or (b) switch to a different existing agent — and not to attribute the output to the missing agent.(requested agent '<name>' not found; ran 'code-puppy' instead) ….Deterministic detection (no guessing)
Fallback is computed to mirror
load_agent()exactly:A new lightweight
get_registered_agent_names()helper returns registry names without instantiating agents. When the requested agent is missing and there's nocode-puppyfallback,load_agent()still raises"not found and no fallback available"and nothing falsely claims code-puppy ran.Backward compatibility
None/False.AgentInvokeOutput.agent_namenow reflects the actual runner; the originally requested name is preserved inrequested_agent_namewheneverfell_backisTrue. Callers that need the requested value should read that field.Scope & safety
load_agent.session_idvalidation, so bad-session early-returns don't pay discovery cost.Tests
Extended the three
load_agentfallback tests plustests/test_agent_tools_coverage.py:list_agents;get_registered_agent_names()discovery/behavior;fell_back=True,requested_agent_name=<bogus>,agent_name="code-puppy", response starts with[invoke_agent notice], and events/history/success use the actual runner;fell_back=Truewith the(requested agent … ran 'code-puppy' instead)prefix;fell_back=False,requested_agent_name=None, real "no fallback available" error, no false code-puppy claim;fell_back=False, response untouched.Out of scope (noted for later)
Repeated invalid requests for the same name will each warn; a small dedupe/rate-limit by agent name would be a clean follow-up, intentionally left out to keep this focused.