Skip to content

feat(agent): name the dropped tool when _init_prompt_tools swallows a conversion exception#344

Open
camerono wants to merge 1 commit into
langgenius:mainfrom
camerono:agent-name-dropped-tool-in-log
Open

feat(agent): name the dropped tool when _init_prompt_tools swallows a conversion exception#344
camerono wants to merge 1 commit into
langgenius:mainfrom
camerono:agent-name-dropped-tool-in-log

Conversation

@camerono
Copy link
Copy Markdown

What

When _convert_tool_to_prompt_message_tool raises inside _init_prompt_tools, the tool gets silently dropped from the LLM payload and the only trace is Failed to convert tool to prompt message tool — which doesn't name the tool. Operators trying to diagnose "why isn't my agent calling X anymore" have no log to grep for.

This PR adds the tool name to the log message and bumps the level from exception (ERROR) to warning, since plugin_daemon routes ERROR through a debug stream by default. No behaviour change beyond observability.

Why this matters

Burned a couple hours this week on the symptom. A custom API tool provider was recreated at some point — same name, new UUID in tool_api_providers. Every existing app's agent_mode.tools[*].provider_id still pointed at the prior UUID. App.deleted_tools (in langgenius/dify at models/model.py) joined on the stale IDs, marked the tools deleted, and _init_prompt_tools here dropped them. The LLM saw a partial tools list and either shortcut-synthesized or returned its own "unknown tool" rejection in-stream. Reading the wire-level capture made it obvious; the existing log alone wouldn't have.

The longer-term fix is probably either (a) a Dify-side migration that rewires stored provider_id references when a provider is recreated under the same name, or (b) refusing the recreate when dependent apps exist. Both are larger changes that belong in langgenius/dify. This PR is the small observability fix that would have shortened my session today.

Diff

-            except Exception:
-                # api tool may be deleted
-                logger.exception("Failed to convert tool to prompt message tool")
+            except Exception:
+                # api tool may be deleted (e.g. its provider was recreated and
+                # the app's stored provider_id no longer matches any row in
+                # tool_api_providers). Naming the tool lets operators grep for
+                # the drop in plugin_daemon logs instead of guessing why the
+                # model can't see it.
+                tool_name = getattr(
+                    getattr(tool, "identity", None), "name", "<unknown>"
+                )
+                logger.warning(
+                    "Dropping tool %r from prompt: conversion failed "
+                    "(provider may be deleted or its schema is stale)",
+                    tool_name,
+                    exc_info=True,
+                )
                 continue

Compatibility Check

  • Backward compatible — log line change only, no API change
  • Forward compatible
  • No breaking change
  • No version bump needed — observability-only fix

Available Checks

  • just build — haven't run it locally; happy to iterate if CI flags anything

I'm grateful for this project's efforts and appreciate the chance to help evolve/improve it.

… conversion exception

When `_convert_tool_to_prompt_message_tool` raises, the tool is silently omitted from the
LLM payload. The current `Failed to convert tool to prompt message tool` log line doesn't
say which tool, so operators have no way to tell which one disappeared from the agent's view.

Most common trigger: a custom API tool provider gets recreated under the same name, its row
in `tool_api_providers` gets a new UUID, and existing apps still reference the prior UUID
in `agent_mode.tools[*].provider_id`. The agent then sees a partial tools list and either
shortcuts or surfaces a model-side "unknown tool" rejection — easy to misread as a model
defect.

Adds the tool name to the log line and bumps the level to warning, since `logger.exception`
defaults to ERROR but routes through a debug stream in plugin_daemon by default.
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves error logging in strategy.py when converting a tool to a prompt message tool fails. It safely extracts the tool's name and logs a detailed warning instead of a generic exception, making it easier to identify which tool failed to convert. There are no review comments to address.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant