How to Use Tool Calling to Update CRMs From Calls (2026)

How to Use Tool Calling to Update CRMs from Calls: transcription to JSON, tool schemas, OAuth, retries, plus Salesforce/HubSpot code. Build faster. Try it now.

Connecting voice streams to stateful systems like a CRM is a common engineering challenge. While a phone call is unstructured audio, a CRM requires structured data. Getting that data from the conversation into the correct CRM fields manually is slow and error-prone, with studies showing manual data entry error rates can be as high as 4%. For developers, the goal is to bridge this gap programmatically. This is where voice AI and tool calling provide a robust, automatable solution.

Tool calling enables a voice agent to interact with external APIs during a live conversation. This guide provides a technical breakdown of how to implement tool calling to update CRMs like Salesforce or HubSpot, turning conversational data into structured API calls that create and update records in real-time. We’ll cover tool definitions, API authentication, error handling, and provide concrete code examples.

The Foundation: From Speech to Structured JSON

Before an agent can execute a tool call, it must convert raw audio into a machine-readable format. This involves two key steps that form the basis of any voice AI workflow.

1. Real-Time Transcription

The process begins with streaming the call audio to a speech-to-text (STT) engine for real-time transcription. High-performance STT services like Deepgram are engineered for low latency and high accuracy, handling diverse accents and background noise to produce a clean text stream. This transcript is the source data for the Large Language Model (LLM).

2. Entity Extraction via LLM

With the transcript available, transcript entity extraction is performed by an LLM. You instruct the model—via its system prompt or a specific function call—to identify and structure key pieces of information (“entities”) from the user’s speech.

For example, the phrase, “Hi, I’m Jane Smith and I need to change the delivery address for order number 98765,” is parsed by the LLM into a structured JSON object:

{
  "name": "Jane Smith",
  "orderId": "98765",
  "intent": "update_delivery_address"
}

This structured output is now ready to be used as arguments in an API call.

The Core Mechanism: The Tool Calling Implementation Loop

With structured data available, the agent can now execute external actions. The process of using tool calling to update CRMs follows a well-defined programmatic loop.

The Explicit Tool Call Handling Loop

This is the core logic that orchestrates the interaction between the LLM, your code, and the external CRM API.

  1. LLM Generates a Tool Call: Based on the conversation, the LLM determines an action is needed and generates a JSON object specifying the tool to use and the parameters.
  2. Your Code Executes the Tool: Your application receives this JSON. You parse the tool name and arguments, then execute the corresponding function in your code (e.g., updateHubspotContact()).
  3. API Call to CRM: Your function makes a secure API request to the CRM endpoint, passing the arguments.
  4. CRM Returns a Result: The CRM API responds with a success or failure message (e.g., a 200 OK with the updated record or a 404 Not Found).
  5. Return Result to LLM: You pass this result back to the LLM. This closes the loop and gives the model the context it needs to respond appropriately to the user (e.g., “Okay, I’ve updated your address,” or “I couldn’t find a record with that ID.”).

Here is a simplified Node.js pseudocode representation of the loop:

// Simplified logic for a single turn
async function handleTurn(userInput) {
  // 1. Get LLM response, which may include a tool call
  const modelResponse = await llm.chat(userInput, { tools: [createLeadTool] });

  if (modelResponse.tool_calls) {
    const toolCall = modelResponse.tool_calls[0];
    const functionName = toolCall.function.name;
    const functionArgs = JSON.parse(toolCall.function.arguments);

    // 2. Execute the corresponding function in your code
    if (functionName === 'create_lead') {
      // 3. Make the API call
      const result = await createLeadInCRM(functionArgs.name, functionArgs.email);

      // 4 & 5. Return the result to the LLM for the next turn
      const finalResponse = await llm.chat(userInput, {
        tool_result: { tool_call_id: toolCall.id, content: result }
      });
      return finalResponse.content;
    }
  } else {
    return modelResponse.content;
  }
}

Defining Tools for CRM Actions

To make your functions available to the LLM, you must define their schema. This schema, often in JSON, tells the model what the function does, what parameters it accepts, and their data types.

Tool Schema for Record Creation (create_lead):

{
  "type": "function",
  "function": {
    "name": "create_lead",
    "description": "Creates a new lead record in the CRM.",
    "parameters": {
      "type": "object",
      "properties": {
        "name": { "type": "string", "description": "The full name of the lead." },
        "company": { "type": "string", "description": "The company name." },
        "email": { "type": "string", "description": "The lead's email address." },
        "phone": { "type": "string", "description": "The lead's phone number." }
      },
      "required": ["name", "email", "phone"]
    }
  }
}

Tool Schema for Record Update (update_address):

{
  "type": "function",
  "function": {
    "name": "update_address",
    "description": "Updates the shipping address for an existing customer.",
    "parameters": {
      "type": "object",
      "properties": {
        "customerId": { "type": "string", "description": "The unique ID of the customer." },
        "street": { "type": "string", "description": "The new street address." },
        "city": { "type": "string", "description": "The new city." },
        "state": { "type": "string", "description": "The new state or province." },
        "zipCode": { "type": "string", "description": "The new postal or ZIP code." }
      },
      "required": ["customerId", "street", "city", "state", "zipCode"]
    }
  }
}

CRM Field Mapping

Field mapping happens when your code translates the parameters from the LLM’s tool call into the body of an API request. The properties in your tool schema should correspond directly to the fields required by your CRM’s API endpoint.

For example, if the LLM calls create_lead with { "name": "John Doe", "email": "john.doe@example.com", "phone": "555-1234" }, your createLeadInCRM function would map these to the Salesforce Lead SObject fields:

// Example mapping for Salesforce API
const sfLeadObject = {
  LastName: args.name.split(' ').pop(), // Simple split for example
  FirstName: args.name.split(' ').shift(),
  Company: args.company || 'Unknown', // Handle optional fields
  Email: args.email,
  Phone: args.phone,
  Status: 'Open - Not Contacted'
};

// Then use sfLeadObject in your POST request body

A Real-World Example: A Technical Walkthrough of an AI Sales Call

Here’s a step-by-step breakdown of an automated sales call, showing the sequence of tool calls and data flow.

  1. Initiation and Context: An outbound call is triggered. The agent’s first action is a tool call to getContactDetails(phoneNumber).
    • Tool Call: {"tool": "getContactDetails", "phoneNumber": "+15551234567"}
    • API Action: GET /crm/v3/objects/contacts?properties=firstname,lifecyclestage,hs_latest_source&idProperty=phone_number&q=+15551234567
    • API Response: {"firstname": "Alex", "lifecyclestage": "lead", ...}
  2. Personalized Conversation: The API response is fed back to the LLM. The model uses this data to generate a personalized opening: “Hi Alex, I see you were checking out our new SUV online.”
  3. Capturing Needs: As Alex speaks, the LLM extracts entities. When Alex says he wants a test drive, the LLM determines the schedule_appointment tool should be used.
  4. Tool Call to Schedule: The LLM generates the tool call to book the appointment.
    • Tool Call: {"tool": "schedule_appointment", "contactId": "12345", "requestedTime": "next Friday at 2 PM"}
    • API Action: Your code calls a find_available_slot function, then executes a POST to your scheduling API, which in turn creates a Meeting object in the CRM linked to the contact.
    • API Response: {"status": "success", "appointmentId": "A9876", "confirmedTime": "2026-04-10T14:00:00-07:00"}
  5. Confirmation: The agent receives the success response and confirms with the user: “Great, I’ve booked you for a test drive next Friday at 2 PM.” The appointment is now in the CRM.
  6. Automated Follow-Up (Webhook): After the call, a post-call webhook trigger sends a payload with the full transcript, call recording URL, and a summary to a specified endpoint. Your service can use this to send a confirmation email via another API call and post a summary to a sales Slack channel.

Building a Reliable and Secure System

Granting an AI write-access to your CRM requires robust security, governance, and error handling.

Security and Authentication

Never hardcode API keys. Use OAuth 2.0 authentication for CRM access. The standard flow involves:

  1. Redirecting the user to the CRM’s authorization URL.
  2. Receiving an authorization code after the user grants consent.
  3. Exchanging the code for an access_token and a refresh_token.
  4. Storing these tokens securely (e.g., in a managed secret store).
  5. Using the access_token in the Authorization: Bearer <token> header for all subsequent API requests.
  6. Using the refresh_token to get a new access_token when the old one expires.

Governance and Safety

Implement a tool choice policy for write actions. This is business logic in your application that gates sensitive operations. For example, before executing a tool that issues a refund over a certain amount, you can implement a human-in-the-loop approval flow.

async function processRefund(args) {
  if (args.amount > 100) {
    // Instead of calling refund API, create a pending approval record
    await db.createPendingApproval('refund', args);
    return "A refund request for $" + args.amount + " has been sent for manager approval.";
  } else {
    // Proceed with API call for smaller amounts
    return await paymentGateway.refund(args.chargeId, args.amount);
  }
}

Reliability and Resilience

Network requests can fail. Your tool-executing functions must include error handling and retry logic, ideally with exponential backoff.

// Simplified retry logic
async function updateSalesforceWithRetry(record, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch('https://your-instance.salesforce.com/...', { /* ... */ });
      if (response.ok) return await response.json();
    } catch (error) {
      if (i === retries - 1) throw error; // Rethrow after last attempt
      await new Promise(res => setTimeout(res, 1000 * Math.pow(2, i))); // Exponential backoff
    }
  }
}

Implement structured audit logging for every tool call and its outcome. Logging events as JSON allows for easy parsing, searching, and analysis in observability platforms, which is critical for debugging and meeting compliance standards like SOC 2.

Advanced Techniques for Efficiency

For production systems, optimizing for latency and interoperability is key.

Parallel Tool Calls

If a user request requires updating multiple systems (e.g., CRM, billing, and shipping), execute them concurrently instead of sequentially using parallel tool calls. In Node.js, Promise.all() is a straightforward way to achieve this, reducing the total wait time to that of the single longest call.

// Example of parallel updates
async function updateUserProfile(userId, data) {
  const crmUpdate = updateCrm(userId, data.crmProfile);
  const billingUpdate = updateBilling(userId, data.billingProfile);
  const shippingUpdate = updateShipping(userId, data.shippingProfile);

  // Executes all three API calls concurrently
  const [crmResult, billingResult, shippingResult] = await Promise.all([
    crmUpdate,
    billingUpdate,
    shippingUpdate
  ]);

  return { crmStatus: 'OK', billingStatus: 'OK', shippingStatus: 'OK' };
}

MCP Extension for CRM Tool

For better interoperability, you can adopt standards like the Model Context Protocol (MCP). An MCP extension for a CRM tool defines a standard interface for how any MCP-compliant agent interacts with that CRM. This reduces vendor lock-in and simplifies integration. Platforms like SigmaMind AI provide an MCP server to help developers orchestrate agents and tools in a standardized way, accelerating development.

Integrating With Your Existing CRM

Most platforms provide pre-built connectors or detailed API docs for popular CRMs.

Salesforce Integration

To create a new Lead in Salesforce (which has over 150,000 customers), you would make a POST request to the /services/data/vXX.X/sobjects/Lead/ endpoint.

Node.js fetch example for Salesforce:

async function createSalesforceLead(accessToken, instanceUrl, leadData) {
  const endpoint = `${instanceUrl}/services/data/v58.0/sobjects/Lead/`;
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      FirstName: leadData.firstName,
      LastName: leadData.lastName,
      Company: leadData.company,
      Email: leadData.email,
      Status: 'Open - Not Contacted'
    })
  });
  return response.json();
}

HubSpot Integration

To update a contact in HubSpot, used by over 200,000 businesses, you’d send a PATCH request to /crm/v3/objects/contacts/{contactId}.

Node.js fetch example for HubSpot:

async function updateHubspotContact(accessToken, contactId, properties) {
  const endpoint = `https://api.hubapi.com/crm/v3/objects/contacts/${contactId}`;
  const response = await fetch(endpoint, {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ properties }) // e.g., { "lifecyclestage": "opportunity" }
  });
  return response.json();
}

Platforms like SigmaMind AI include an app library with pre-built connectors that handle the OAuth flow and API mapping for you, abstracting away this boilerplate code.

Why This Matters for Your Business

Implementing tool calling to update your CRM automates data entry, enforces data hygiene, and frees up your team to focus on complex tasks. By building a direct, real-time bridge between conversations and your system of record, you create more efficient workflows and faster, more responsive customer experiences.

If you’re ready to start building production-grade voice agents that integrate with your CRM, try SigmaMind AI for free and see how our developer-first platform can accelerate your roadmap.

Frequently Asked Questions

What is tool calling in simple terms?

Tool calling, or function calling, is the mechanism that allows an LLM to request the execution of predefined code functions during a conversation. The model generates a JSON object specifying the function and its arguments, your code executes it, and the result is returned to the model to inform its response.

Can a voice AI update any CRM?

Yes, if the CRM exposes a REST or GraphQL API. While platforms may offer pre-built integrations for major CRMs like Salesforce and HubSpot, you can use their generic API call tools or custom functions to connect to virtually any CRM or backend service.

Is it safe to let an AI update my CRM records?

Yes, provided you follow standard security best practices. Use OAuth 2.0 for authentication so API keys and passwords are never exposed. Implement your own business logic to add guardrails, such as requiring human approval for high-stakes actions like deleting records or issuing large refunds.

How does the AI know what information to put in the CRM?

Through the tool schema you provide. The JSON schema for each tool defines the function’s purpose and the exact parameters (e.g., name, email, company) it requires. The LLM uses this schema to structure the data it extracts from the conversation before passing it to your function.

What happens if the AI makes a mistake or an API fails?

Production-grade implementations must include robust error handling. Your code should wrap API calls in try-catch blocks and implement a retry strategy (like exponential backoff) for transient network errors. All tool call attempts, successes, and failures should be logged to an observability platform for auditing and debugging.

Evolve with SigmaMind AI

Build, launch & scale conversational AI agents

Contact Sales