#Multiple invocation of handler function in useFrontendTool
1 messages · Page 1 of 1 (latest)
This solution has been AI generated
It’s usually caused by two things: parallel tool execution and React Strict Mode double‑invoking hooks in development. In v1.10.6, ensure tools aren’t executed in parallel at the adapter level and that each action is registered once per component lifecycle.
Verify adapter config (disable parallel tool calls)
Make sure parallel tool calls are disabled on your LLM adapter (not just the model). For example:
import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/backend";
const runtime = new CopilotRuntime();
const adapter = new OpenAIAdapter({
// ...other config
disableParallelToolCalls: true,
});
Avoid duplicate registrations in useFrontendTool/useCopilotAction
CopilotKit dedupes actions by name, but duplicate registrations can still happen if actions are re‑created on each render.
- Ensure unique action names across your app.
- Memoize your action definitions so they’re created only once:
const actions = useMemo(() => ([
{
name: "exampleAction",
description: "Example",
handler: (args) => { /* ... */ },
},
]), []);
useCopilotAction(actions);
React Strict Mode in development
React Strict Mode intentionally double‑invokes effects/hooks in dev, which can trigger duplicate registrations and handler calls. v1.10.6 includes deduplication that warns: "Found an already registered action with name ${action.name}". Update all relevant packages to exactly v1.10.6 and rely on the built‑in dedupe. Note: This double invocation does not occur in production.
Direct to LLM specifics
Define actions only once per component lifecycle and avoid creating new handler references during re‑renders.
References
- Direct to LLM guides: https://docs.copilotkit.ai/direct-to-llm/guides/backend-actions
- LLM adapters reference (disableParallelToolCalls): https://docs.copilotkit.ai/reference/classes/llm-adapters/OpenAIAdapter
- Troubleshooting: https://docs.copilotkit.ai/direct-to-llm/troubleshooting/
Was this helpful?
If this solution worked for you, please click on the appropriate option below to help us improve:
Hey @slender grove!
Thanks for raising this - could you help me to understand what you're current setup is like?
@hallow folio pretty simple:
<CopilotKit runtimeUrl="/api/copilotkit">
<CRMTools /> {/* custom component with useFrontendTools definitions */}
<CopilotChat />
</CopilotKit>
CRMTools is god component with all 7 tools with similar structure:
- @tanstact/react-query mutation, like the next:
const createLeadMutation = useMutation({
mutationFn: useConvexMutation(api.leads.create),
});
- useFrontendTool wrapper, like the next:
useFrontendTool({
name: "create_or_edit_lead",
description: "Create a new lead or edit an existing lead",
parameters: [
{
name: "id",
type: "string",
description:
"The id of the lead (undefined if creating a new lead, overvise required!)",
},
{
name: "data",
type: "string",
description: dedent`
JSON encoded lead data with following schema:
name: v.string(),
...
`,
},
],
render({ args, status, result }) {
// simple generative UI to show progress of execution and result
},
handler: async ({ id, data }) => {
// calling the mutation here (inside try-catch block and with helpers to structure errors and success in similar way
},
});
Any ideas?