Whatever message this page gives is out now! Go check it out!

Function tools

Last update:
May 18, 2026
Function tools allow LLMs integrated into ColdFusion to call your own business logic, specifically, ColdFusion CFC methods or MCP clients, during a conversation. Instead of only generating text, the AI can trigger real actions, fetch data, or perform computations by invoking these tools.

How do function tools work?

  • Declaration: Register function tools in the Agent configuration using a TOOLS array. Each entry points to a CFC and optionally specifies which methods to expose.
  • Schema: ColdFusion automatically derives each tool's name, parameter types, and description from the CFC method signature and hints. You can override the description explicitly.
  • Invocation: When the LLM decides a tool is needed, the Agent returns a response struct containing a toolExecutionRequests array. Each entry describes the tool the model wants to call and the arguments it wants to pass. Your code is responsible for executing the tool and handling the result.
  • Description: Always provide a clear, scenario-based DESCRIPTION for each exposed method. Without one, the AI may not invoke the tool even when the user's query clearly matches. Good descriptions tell the model when to use the tool, not just what it does.

Why are function tools important?

  • Enterprise integration: Allow your AI agent to interact with real business systems — fetching account data, creating tickets, validating data, or triggering workflows.
  • Enhanced capabilities: The AI can go beyond text generation, performing tasks that require up-to-date or sensitive information from your internal systems.
  • Controlled access: You decide which functions are exposed, ensuring security and relevance.

Tool configuration — two approaches

Expose all public CFC methods
Omit the METHODS array to expose every public method in the CFC. ColdFusion derives tool names and parameter schemas automatically from the method signatures.
Use this when you want the AI to have access to the full CFC and all its capabilities.

agent = Agent({
    CHATMODEL : chatModel,
    TOOLS     : [
        { CFC : "tools.SupportTool" }   // all public methods exposed
    ]
});
            
Expose specific methods only
Include a METHODS array to expose only named methods. Each entry requires a METHOD name and a DESCRIPTION that tells the model when and why to use it.
Use this for security, relevance, or when you want fine-grained control over what the AI can do.

agent = Agent({
    CHATMODEL : chatModel,
    TOOLS     : [
        {
            CFC     : "tools.SupportTool",
            METHODS : [
                {
                    METHOD      : "getTicketStatus",
                    DESCRIPTION : "Get the status of a support ticket by ID. Use this when the user asks about the progress or state of a ticket, e.g., 'What is the status of ticket TKT-12345?'"
                },
                {
                    METHOD      : "createTicket",
                    DESCRIPTION : "Create a new support ticket. Use this when the user wants to report an issue or request support."
                }
            ]
        }
    ]
});
            
You can also mix CFCs — expose all methods from one and only selected methods from another:

TOOLS : [
    { CFC : "tools.WeatherTool" },                          // all methods
    { CFC : "tools.SupportTool", METHODS : [...] }          // specific methods only
]
            

The response — toolExecutionRequests

When the LLM decides to call a tool, agent.chat() returns a struct with a toolExecutionRequests array instead of (or in addition to) a plain message. Each entry in the array describes the tool call the model wants to make:
FieldTypeDescription
nameStringThe name of the CFC method to invoke
argumentsStructThe arguments the model wants to pass to the method
Your application is responsible for checking for toolExecutionRequests, executing the tool, and handling the result.

response = agent.chat("What is the status of ticket TKT-12345?", "user1");

if (structKeyExists(response, "toolExecutionRequests")
    && arrayLen(response.toolExecutionRequests) > 0) {

    toolRequest = response.toolExecutionRequests[1];
    writeOutput("Tool requested: " & toolRequest.name);
    writeOutput("Arguments: "     & serializeJSON(toolRequest.arguments));

    // Execute the tool and handle the result in your application
}
            

Full example

SupportTool.cfc

component output=false {

    remote string function getTicketStatus(required string ticketId) {
        hint="Returns the current status of a support ticket by its ID.";
        if (arguments.ticketId == "TKT-12345") {
            return "in progress";
        }
        return "closed";
    }

    remote struct function createTicket(
        required string summary,
        required string priority
    ) {
        hint="Creates a new support ticket with the given summary and priority.";
        return {
            id       : createUUID(),
            summary  : arguments.summary,
            priority : arguments.priority,
            status   : "new"
        };
    }

}
            
ticket.cfm — expose specific methods

<cfscript>
    chatModel = ChatModel({
        PROVIDER  : "openAi",
        APIKEY    : "#application.apiKey#",
        MODELNAME : "gpt-4o-mini"
    });

    agent = Agent({
        CHATMODEL  : chatModel,
        CHATMEMORY : { MAXMESSAGES : 20, PERUSER : true },
        TOOLS      : [
            {
                CFC     : "tools.SupportTool",
                METHODS : [
                    {
                        METHOD      : "getTicketStatus",
                        DESCRIPTION : "Get the status of a support ticket by ID. Use this when the user asks about the progress or state of a ticket."
                    },
                    {
                        METHOD      : "createTicket",
                        DESCRIPTION : "Create a new support ticket from user input. Use this when the user wants to report an issue or request support."
                    }
                ]
            }
        ]
    });

    response = agent.chat("My ticket ID is TKT-12345. What is its status?", "user1");

    if (structKeyExists(response, "toolExecutionRequests")
        && arrayLen(response.toolExecutionRequests) > 0) {
        toolReq = response.toolExecutionRequests[1];
        writeOutput("Tool: " & toolReq.name & " | Args: " & serializeJSON(toolReq.arguments));
    } else {
        writeOutput(response.message);
    }
</cfscript>
            
ticket_allMethods.cfm — expose all CFC methods

<cfscript>
    chatModel = ChatModel({
        PROVIDER  : "openAi",
        APIKEY    : "#application.apiKey#",
        MODELNAME : "gpt-4o-mini"
    });

    agent = Agent({
        CHATMODEL : chatModel,
        TOOLS     : [{ CFC : "tools.SupportTool" }]    // all public methods exposed
    });

    response = agent.chat("Create a ticket for a login issue with high priority.", "user1");

    if (structKeyExists(response, "toolExecutionRequests")
        && arrayLen(response.toolExecutionRequests) > 0) {
        toolReq = response.toolExecutionRequests[1];
        writeOutput("Tool: " & toolReq.name & " | Args: " & serializeJSON(toolReq.arguments));
    } else {
        writeOutput(response.message);
    }
</cfscript>
            
Note:
Best practice: Use specific method exposure (METHODS array) in production to limit what the AI can invoke. Reserve the all-methods approach for development or when all CFC methods are intentionally part of the agent's capabilities.

Share this page

Was this page helpful?
We're glad. Tell us how this page helped.
We're sorry. Can you tell us what didn't work for you?
Thank you for your feedback. Your response will help improve this page.

On this page