René's URL Explorer Experiment


Title: Duplicate tool calls during conversation - Need better approach than manual caching · Issue #6 · VapiAI/example-server-javascript-node · GitHub

Open Graph Title: Duplicate tool calls during conversation - Need better approach than manual caching · Issue #6 · VapiAI/example-server-javascript-node

X Title: Duplicate tool calls during conversation - Need better approach than manual caching · Issue #6 · VapiAI/example-server-javascript-node

Description: Current Issue: I'm experiencing multiple identical tool calls being sent to my backend API during a single conversation. My backend receives repeated calls with the same parameters throughout a conversation, leading to duplicate processi...

Open Graph Description: Current Issue: I'm experiencing multiple identical tool calls being sent to my backend API during a single conversation. My backend receives repeated calls with the same parameters throughout a con...

X Description: Current Issue: I'm experiencing multiple identical tool calls being sent to my backend API during a single conversation. My backend receives repeated calls with the same parameters throughout a...

Opengraph URL: https://github.com/VapiAI/example-server-javascript-node/issues/6

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Duplicate tool calls during conversation - Need better approach than manual caching","articleBody":"Current Issue: I'm experiencing multiple identical tool calls being sent to my backend API during a single conversation. My backend receives repeated calls with the same parameters throughout a conversation, leading to duplicate processing.\n\nThe issue here is on each message it sends call to my backend that causes tools calls duplication if we have something in configuration the agent only send req to api call when a tool the functions  we provide to that agent configuration  is called or how can i manage this \n\n`app.post('/api/tools', async (req, res) =\u003e {\n  try {\n    logger.info('POST /api/tools endpoint called');\n    \n    // Enhanced logging with request identification\n    const requestId = `req-${Date.now()}-${Math.random().toString(36).substring(2, 7)}`;\n    logger.debug(`Processing request ${requestId}`, { body: req.body });\n    \n    // Check if this is a handshake or health check request (empty or minimal payload)\n    if (!req.body || (Object.keys(req.body).length === 0)) {\n      logger.info('Received handshake/health check request');\n      return res.json({\n        status: 'ok',\n        message: 'Server is operational'\n      });\n    }\n\n    // Check if this is a status update message\n    if (req.body.message \u0026\u0026 req.body.message.type) {\n      if (req.body.message.type === 'status-update') {\n        logger.info(`Status update received: ${req.body.message.status}`);\n        logger.info(`Reason: ${req.body.message.endedReason || 'N/A'}`);\n        return res.json({\n          results: [{\n            result: `Received status update: ${req.body.message.status}`\n          }]\n        });\n      } else if (req.body.message.type === 'end-of-call-report') {\n        logger.info(`End of call report received`);\n        \n        // Log details of the call report for analysis\n        if (req.body.message.analysis) {\n          logger.info('Call analysis', {\n            summary: req.body.message.analysis.summary,\n            success: req.body.message.analysis.successEvaluation\n          });\n        }\n        \n        return res.json({\n          results: [{\n            result: `Received end of call report`\n          }]\n        });\n      }\n    }\n\n    // Extract tool calls from the request body - handling different formats\n    const { toolCalls, format } = extractToolCallsWithFormat(req.body);\n    \n    if (!toolCalls || !Array.isArray(toolCalls) || toolCalls.length === 0) {\n      logger.warn(`No valid tool calls found in request ${requestId}`, { body: req.body });\n      return res.status(400).json({ \n        error: 'No valid tool calls found in request',\n        requestId: requestId \n      });\n    }\n\n    logger.info(`Found ${toolCalls.length} tool calls in ${format} format`, { requestId });\n\n    // Handle regular tool calls\n    const results = await Promise.all(toolCalls.map(async (toolCall) =\u003e {\n      // Check for duplicate tool calls before processing\n      if (isDuplicateToolCall(toolCall)) {\n        // Return cached response for duplicate call\n        return {\n          toolCallId: toolCall.id,\n          result: JSON.stringify({\n            status: 'duplicate',\n            message: 'This tool call was already processed recently.'\n          })\n        };\n      }\n      \n      const result = await handleToolCall(toolCall);\n      return {\n        toolCallId: toolCall.id,\n        result: result\n      };\n    }));\n\n    logger.info(`Response sent for request ${requestId}`, { results });\n    res.json({ results });\n  } catch (error) {\n    logger.error('Error processing tool call', { error: error.message, stack: error.stack });\n    // Send a properly formatted response even on error\n    res.json({\n      results: [{\n        toolCallId: req.body.toolCallId || \"unknown\",\n        result: JSON.stringify({\n          status: 'error',\n          message: error.message\n        })\n      }]\n    });\n  }\n});`\n\n\n`import { CreateAssistantDTO } from \"@vapi-ai/web/dist/api\";\nexport const characterAssistant: CreateAssistantDTO = {\n  name: \"Mohammad\",\n  model: {\n    provider: \"openai\",\n    model: \"gpt-3.5-turbo\",\n    temperature: 0.7,\n    messages: [\n      {\n        role: \"system\",\n        content: \"You are a helpful, polite restaurant assistant named Mohammad for a premium Middle Eastern dining restaurant called Khayal. Handle guest interactions professionally in both English (EN) and Arabic (AR), including table reservations, order placement, and menu navigation. If the user speaks Arabic, respond in Arabic. If the user speaks English, respond in English. Always provide clear options and summarize selections. If unsure, ask clarifying questions. You should use the makeReservation function when a customer wants to book a table, the addToOrder function when they want to order food, and the checkAvailability function to verify if tables are available for specific dates and times.\"\n      }\n    ],\n    tools: [\n      {\n        type: \"function\",\n        function: {\n          name: \"makeReservation\",\n          description: \"Books a table reservation for customers at the restaurant\",\n          parameters: {\n            type: \"object\",\n            properties: {\n              guestCount: {\n                type: \"number\",\n                description: \"Number of guests for the reservation\",\n              },\n              date: {\n                type: \"string\",\n                description: \"Date of the reservation (YYYY-MM-DD format)\",\n              },\n              time: {\n                type: \"string\",\n                description: \"Time of the reservation (HH:MM format)\",\n              },\n              name: {\n                type: \"string\",\n                description: \"Name under which the reservation is made\",\n              },\n              phoneNumber: {\n                type: \"string\",\n                description: \"Contact phone number for the reservation\",\n              },\n              specialRequests: {\n                type: \"string\",\n                description: \"Any special requests for the reservation\",\n              },\n            },\n            required: [\"guestCount\", \"date\", \"time\", \"name\", \"phoneNumber\"],\n          },\n        },\n        async: false\n      },\n      {\n        type: \"function\",\n        function: {\n          name: \"addToOrder\",\n          description: \"Adds items to a customer's order\",\n          parameters: {\n            type: \"object\",\n            properties: {\n              items: {\n                type: \"array\",\n                items: {\n                  type: \"object\",\n                  properties: {\n                    name: {\n                      type: \"string\",\n                      description: \"Name of the menu item\",\n                    },\n                    quantity: {\n                      type: \"number\",\n                      description: \"Quantity of the item\",\n                    },\n                    specialInstructions: {\n                      type: \"string\",\n                      description: \"Special instructions for preparing the item\",\n                    },\n                  },\n                  required: [\"name\", \"quantity\"],\n                },\n                description: \"List of items to add to the order\",\n              },\n            },\n            required: [\"items\"],\n          },\n        },\n        async: false\n      },\n      {\n        type: \"function\",\n        function: {\n          name: \"checkAvailability\",\n          description: \"Checks if tables are available for a specific date and time\",\n          parameters: {\n            type: \"object\",\n            properties: {\n              guestCount: {\n                type: \"number\",\n                description: \"Number of guests\",\n              },\n              date: {\n                type: \"string\",\n                description: \"Date to check availability (YYYY-MM-DD format)\",\n              },\n              time: {\n                type: \"string\",\n                description: \"Time to check availability (HH:MM format)\",\n              },\n            },\n            required: [\"guestCount\", \"date\", \"time\"],\n          },\n        },\n        async: false\n      }\n    ],\n  },\n  \n  // Add server configuration for function handling\n  server: {\n    url: \"https://1dd0-2a09-bac1-5b20-28-00-19b-fe.ngrok-free.app/api/tools\",\n    timeoutSeconds: 20,\n    secret: \"mock-secret-key\"\n  },\n  serverUrl: \"https://1dd0-2a09-bac1-5b20-28-00-19b-fe.ngrok-free.app/api/tools\",\n  serverUrlSecret:\"mock\",\n  \n  // Move idle messages to messagePlan instead of the root-level messages property\n  messagePlan: {\n    idleMessages: [\n      \"Please wait while I process your request...\",\n      \"I'm checking our system for that information...\",\n      \"Just a moment while I update our records...\"\n    ],\n    idleMessageMaxSpokenCount: 1,\n    idleTimeoutSeconds: 5\n  },\n  \n  voice: {\n    provider: \"11labs\",\n    voiceId: \"paula\",\n  },\n  \n  firstMessage: \"Thank you for calling Khayal Restaurant. This is Mohammad, your Arabic and English scheduling assistant. How may I help you today?\",\n};\n`\n\nThe Problem: While this manual caching works somewhat, I have several concerns:\n\nThis feels like a workaround rather than the right solution\nI'm not sure if 6 seconds is the right deduplication window\nThe manual cache management is not ideal and could lead to memory issues\nI shouldn't need to handle this level of deduplication on my backend\nMy Configuration: I've configured my agent to call my backend tools at http://localhost:3000/api/tools and implemented handlers for various tool functions (makeReservation, addToOrder, checkAvailability). The agent correctly formats and sends tool calls, but I'm receiving duplicate requests.\n\nQuestions:\n\nHow can i configure in some way so my backend is only called when a tool is called?\nYou can ignore these caching things i  have mentioned if those are unrelated.\nIs there a configuration setting to prevent the agent from sending duplicate tool calls?\nIs there a recommended backend approach for handling this situation that doesn't require manual caching?\nIs this expected behavior, and if so, what's the recommended pattern for backend implementation?\nCould this be related to how I'm responding to tool calls?\ncan we have a sample configuration of a sample node js server and agent config as well","author":{"url":"https://github.com/umerfarok","@type":"Person","name":"umerfarok"},"datePublished":"2025-04-10T08:34:33.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/6/example-server-javascript-node/issues/6"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:0d0f77e6-b355-ebd1-47c1-afd19180dff6
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idB3DC:2582C9:99C9CD:CC16BF:697BF63E
html-safe-nonce8ec80463b8c945de53c4d7c319fee09656aea88a845e7a4e7d6a5c8db8aa7ff7
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCM0RDOjI1ODJDOTo5OUM5Q0Q6Q0MxNkJGOjY5N0JGNjNFIiwidmlzaXRvcl9pZCI6IjUxMzU2NzE0MDMyNDM4OTQzMzQiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmac2321afe2496608aaa4fa21dccc418b6fb0e44ec8f5a1239810313b0e22c647dd
hovercard-subject-tagissue:2984910367
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/VapiAI/example-server-javascript-node/6/issue_layout
twitter:imagehttps://opengraph.githubassets.com/3692d7c216b3501aa422032ce419016eaf8c71c659f0396547dfbcc679006b70/VapiAI/example-server-javascript-node/issues/6
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/3692d7c216b3501aa422032ce419016eaf8c71c659f0396547dfbcc679006b70/VapiAI/example-server-javascript-node/issues/6
og:image:altCurrent Issue: I'm experiencing multiple identical tool calls being sent to my backend API during a single conversation. My backend receives repeated calls with the same parameters throughout a con...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernameumerfarok
hostnamegithub.com
expected-hostnamegithub.com
Noneda4f0ee56809799586f8ee546b27f94fe9b5893edfbf87732e82be45be013b52
turbo-cache-controlno-preview
go-importgithub.com/VapiAI/example-server-javascript-node git https://github.com/VapiAI/example-server-javascript-node.git
octolytics-dimension-user_id144965430
octolytics-dimension-user_loginVapiAI
octolytics-dimension-repository_id753175131
octolytics-dimension-repository_nwoVapiAI/example-server-javascript-node
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id753175131
octolytics-dimension-repository_network_root_nwoVapiAI/example-server-javascript-node
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release847cd6771d7fb3caaa9384a1fe1215457fe1e4f4
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/VapiAI/example-server-javascript-node/issues/6#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FVapiAI%2Fexample-server-javascript-node%2Fissues%2F6
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub SparkBuild and deploy intelligent appshttps://github.com/features/spark
GitHub ModelsManage and compare promptshttps://github.com/features/models
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
GitHub SponsorsFund open source developershttps://github.com/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/accelerator
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FVapiAI%2Fexample-server-javascript-node%2Fissues%2F6
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=VapiAI%2Fexample-server-javascript-node
Reloadhttps://github.com/VapiAI/example-server-javascript-node/issues/6
Reloadhttps://github.com/VapiAI/example-server-javascript-node/issues/6
Reloadhttps://github.com/VapiAI/example-server-javascript-node/issues/6
VapiAI https://github.com/VapiAI
example-server-javascript-nodehttps://github.com/VapiAI/example-server-javascript-node
Notifications https://github.com/login?return_to=%2FVapiAI%2Fexample-server-javascript-node
Fork 16 https://github.com/login?return_to=%2FVapiAI%2Fexample-server-javascript-node
Star 17 https://github.com/login?return_to=%2FVapiAI%2Fexample-server-javascript-node
Code https://github.com/VapiAI/example-server-javascript-node
Issues 1 https://github.com/VapiAI/example-server-javascript-node/issues
Pull requests 1 https://github.com/VapiAI/example-server-javascript-node/pulls
Actions https://github.com/VapiAI/example-server-javascript-node/actions
Projects 0 https://github.com/VapiAI/example-server-javascript-node/projects
Security 0 https://github.com/VapiAI/example-server-javascript-node/security
Insights https://github.com/VapiAI/example-server-javascript-node/pulse
Code https://github.com/VapiAI/example-server-javascript-node
Issues https://github.com/VapiAI/example-server-javascript-node/issues
Pull requests https://github.com/VapiAI/example-server-javascript-node/pulls
Actions https://github.com/VapiAI/example-server-javascript-node/actions
Projects https://github.com/VapiAI/example-server-javascript-node/projects
Security https://github.com/VapiAI/example-server-javascript-node/security
Insights https://github.com/VapiAI/example-server-javascript-node/pulse
New issuehttps://github.com/login?return_to=https://github.com/VapiAI/example-server-javascript-node/issues/6
New issuehttps://github.com/login?return_to=https://github.com/VapiAI/example-server-javascript-node/issues/6
Duplicate tool calls during conversation - Need better approach than manual cachinghttps://github.com/VapiAI/example-server-javascript-node/issues/6#top
https://github.com/umerfarok
https://github.com/umerfarok
umerfarokhttps://github.com/umerfarok
on Apr 10, 2025https://github.com/VapiAI/example-server-javascript-node/issues/6#issue-2984910367
https://1dd0-2a09-bac1-5b20-28-00-19b-fe.ngrok-free.app/api/toolshttps://1dd0-2a09-bac1-5b20-28-00-19b-fe.ngrok-free.app/api/tools
https://1dd0-2a09-bac1-5b20-28-00-19b-fe.ngrok-free.app/api/toolshttps://1dd0-2a09-bac1-5b20-28-00-19b-fe.ngrok-free.app/api/tools
http://localhost:3000/api/toolshttp://localhost:3000/api/tools
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.