You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: Gate call-actor mentions when the tool is absent from the session
Several places named call-actor unconditionally regardless of whether a
session's ?tools=/?actors= selection actually included it \u2014 inviting a
hallucinated call to a tool the client never received in tools/list.
- actor_tools_factory.ts: gate the call-actor line in dedicated Actor
tool descriptions via the existing hasTool pattern.
- server-instructions/index.ts: getServerInstructions now takes a
ToolDescriptionContext instead of a bare reportProblemAvailable
boolean, gating every call-actor, rag-web-browser, web-fetch and
report-problem mention through one mechanism.
- mcp/server.ts: legacy path passes the real per-session tool set;
stateless path resolves call-actor presence from the request URL
(?tools=/?actors=) with zero network calls, since that presence
never depends on mode, client identity, or the Actor-metadata
fetch \u2014 falls back to today's behavior when no URL is given.
- stateless_server.ts / dev_server.ts: thread requestUrl through,
additive and backward compatible.
Adds a regression test pinning the Claude-connector tool surface
(19 tools, no call-actor) and asserting the resolved instructions
never mention it.
letdescription=`This tool calls the Actor "${definition.actorFullName}" and retrieves its output results.
133
+
${hasTool(HELPER_TOOLS.ACTOR_CALL) ? `Use this tool instead of the "${HELPER_TOOLS.ACTOR_CALL}" if user requests this specific Actor.\n` : ''}Actor description: ${definition.description}`;
// Derive the API base from config so examples match the gate/templates under an
26
30
// APIFY_API_BASE_URL / staging override, instead of a hardcoded api.apify.com.
@@ -70,13 +74,20 @@ ${
70
74
## Widget workflow (applies when tool responses include widget metadata)
71
75
Some clients render widget-backed Actor tools: the response includes a live UI that automatically polls run status. When a widget is rendered, follow-up status polling by the model is a forbidden duplicate.
72
76
73
-
- **After \`${HELPER_TOOLS.ACTOR_CALL_WIDGET}\` or \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\`, never call \`${HELPER_TOOLS.ACTOR_RUNS_GET}\` or \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` for the same run.** Both widgets render live progress and poll themselves — stop after the widget response and defer to it for run status. Re-rendering the same run via \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` is a duplicate.
77
+
${
78
+
hasTool(HELPER_TOOLS.ACTOR_CALL)
79
+
? `- **After \`${HELPER_TOOLS.ACTOR_CALL_WIDGET}\` or \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\`, never call \`${HELPER_TOOLS.ACTOR_RUNS_GET}\` or \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` for the same run.** Both widgets render live progress and poll themselves — stop after the widget response and defer to it for run status. Re-rendering the same run via \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` is a duplicate.
74
80
- Polling \`${HELPER_TOOLS.ACTOR_RUNS_GET}\` after \`${HELPER_TOOLS.ACTOR_CALL}\` is fine — that tool renders no UI, so polling is expected when the run is non-terminal and you need the latest status.
75
81
`
82
+
: `- **After \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\`, never call \`${HELPER_TOOLS.ACTOR_RUNS_GET}\` or \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` for the same run.** It renders live progress and polls itself — stop after the widget response and defer to it for run status. Re-rendering the same run via \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` is a duplicate.
83
+
`
84
+
}`
76
85
: ''
77
86
}
78
87
## Tool dependencies and disambiguation
79
-
88
+
${
89
+
hasTool(HELPER_TOOLS.ACTOR_CALL)
90
+
? `
80
91
### Tool dependencies
81
92
- \`${HELPER_TOOLS.ACTOR_CALL}\`:
82
93
- Use \`${HELPER_TOOLS.ACTOR_GET_DETAILS}\` first to obtain the Actor's input schema.
@@ -85,7 +96,9 @@ Some clients render widget-backed Actor tools: the response includes a live UI t
85
96
- Supports a \`waitSecs\` parameter (default 30, max 45):
86
97
- \`waitSecs: 0\`: fire-and-forget — starts the run and returns immediately with a runId.
87
98
- \`waitSecs > 0\`: waits up to that many seconds for the run to complete, then returns its current status and storage IDs (never the output rows — fetch those with \`${HELPER_TOOLS.DATASET_GET_ITEMS}\`).
88
-
99
+
`
100
+
: ''
101
+
}
89
102
### Tool disambiguation
90
103
- **\`${HELPER_TOOLS.STORE_SEARCH}\` vs \`${HELPER_TOOLS.ACTOR_GET_DETAILS}\`:**
91
104
\`${HELPER_TOOLS.STORE_SEARCH}\` finds Actors; \`${HELPER_TOOLS.ACTOR_GET_DETAILS}\` retrieves detailed info, README, and schema for a specific Actor.
@@ -94,22 +107,33 @@ ${
94
107
? `- **Data vs widget Actor tools (when the client supports widgets):**
95
108
- \`${HELPER_TOOLS.STORE_SEARCH}\` is a silent data lookup (Actor list for name resolution) with no UI; \`${HELPER_TOOLS.STORE_SEARCH_WIDGET}\` renders an interactive UI element (widget) with Actor search results for the user to browse — use it only when the user explicitly asks to search or discover Actors.
96
109
- \`${HELPER_TOOLS.ACTOR_GET_DETAILS}\` is a silent data lookup (input schema, README, metadata) with no UI; \`${HELPER_TOOLS.ACTOR_GET_DETAILS_WIDGET}\` renders an interactive UI element (widget) with Actor details — use it only when the user explicitly asks to see or browse the Actor.
97
-
- \`${HELPER_TOOLS.ACTOR_CALL}\` runs the Actor and returns its run status and storage IDs (no UI); \`${HELPER_TOOLS.ACTOR_CALL_WIDGET}\` renders an interactive UI element (widget) that tracks live Actor run progress — use it only when the user explicitly asks to see progress.
98
-
- \`${HELPER_TOOLS.ACTOR_RUNS_GET}\` is a silent data lookup (run status, dataset IDs, stats) with no UI; \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` renders an interactive UI element (widget) showing live run progress for the user — use it only when the user explicitly asks to see run progress.
110
+
${hasTool(HELPER_TOOLS.ACTOR_CALL) ? ` - \`${HELPER_TOOLS.ACTOR_CALL}\` runs the Actor and returns its run status and storage IDs (no UI); \`${HELPER_TOOLS.ACTOR_CALL_WIDGET}\` renders an interactive UI element (widget) that tracks live Actor run progress — use it only when the user explicitly asks to see progress.\n` : ''} - \`${HELPER_TOOLS.ACTOR_RUNS_GET}\` is a silent data lookup (run status, dataset IDs, stats) with no UI; \`${HELPER_TOOLS.ACTOR_RUNS_GET_WIDGET}\` renders an interactive UI element (widget) showing live run progress for the user — use it only when the user explicitly asks to see run progress.
99
111
- When the next step is running an Actor, prefer silent lookups (\`${HELPER_TOOLS.STORE_SEARCH}\`, \`${HELPER_TOOLS.ACTOR_GET_DETAILS}\`) over widget-backed variants.
100
112
`
101
113
: ''
102
-
}- **\`${HELPER_TOOLS.STORE_SEARCH}\` vs ${RAG_WEB_BROWSER}:**
114
+
}${
115
+
hasTool(RAG_WEB_BROWSER_TOOL)
116
+
? `- **\`${HELPER_TOOLS.STORE_SEARCH}\` vs ${RAG_WEB_BROWSER}:**
103
117
\`${HELPER_TOOLS.STORE_SEARCH}\` finds robust and reliable Actors for specific websites; ${RAG_WEB_BROWSER} is a general and versatile web scraping tool.
${WEB_FETCH} fetches one specific URL and returns its full content verbatim; ${RAG_WEB_BROWSER} searches the web by query and returns content from the top results.
106
-
- **Dedicated Actor tools (e.g. ${RAG_WEB_BROWSER}) vs \`${HELPER_TOOLS.ACTOR_CALL}\`:**
124
+
`
125
+
: ''
126
+
}${
127
+
hasTool(HELPER_TOOLS.ACTOR_CALL)
128
+
? `- **Dedicated Actor tools${hasTool(RAG_WEB_BROWSER_TOOL) ? ` (e.g. ${RAG_WEB_BROWSER})` : ''} vs \`${HELPER_TOOLS.ACTOR_CALL}\`:**
107
129
Prefer dedicated tools when available; use \`${HELPER_TOOLS.ACTOR_CALL}\` only when no specialized tool exists in the Apify store.
108
-
${
109
-
reportProblemAvailable
110
-
? `
130
+
`
131
+
: ''
132
+
}${
133
+
hasTool(HELPER_TOOLS.PROBLEM_REPORT)
134
+
? `
111
135
If a tool or Actor fails and you cannot resolve it, you can report it with \`${HELPER_TOOLS.PROBLEM_REPORT}\`.
0 commit comments