Custom AI tools and function calling

Registering your own functions for the Aimogen Pro chatbot and agents to call, with a complete worked example.

Beyond the built-in extensions, you can register your own tools. The AI then decides when to call them and supplies the arguments.

The plugin ships a working example at examples/function_call.php.

The two hooks#

aiomatic_ai_functions registers the tool, so the model knows it exists.

aiomatic_ai_reply_raw receives the raw provider response, where you detect a call to your tool and execute it.

A complete example#

Registering a tool that emails the site administrator:

php
add_filter( 'aiomatic_ai_functions', function ( $query, $god_extensions = false ) {

    $functions = is_array( $query ) ? $query : array();

    $functions['functions'][] = array(
        'type'     => 'function',
        'function' => new Aiomatic_Query_Function(
            'send_email',
            'Send an email to the administrator of this website',
            array(
                new Aiomatic_Query_Parameter( 'subject', 'The subject of the email', 'string', true ),
                new Aiomatic_Query_Parameter( 'message', 'The message of the email', 'string', true ),
            ),
            false
        ),
    );

    // Optional: the text shown while the tool runs.
    $functions['message'] = 'Sure, I just sent an email to admin, they will respond soon.';

    return $functions;
}, 999, 2 );

Then handle the call:

php
add_filter( 'aiomatic_ai_reply_raw', function ( $reply, $query ) {

    if ( empty( $reply->tool_calls ) ) {
        return $reply;
    }

    foreach ( $reply->tool_calls as $tool_call ) {

        if ( ! isset( $tool_call->type ) || $tool_call->type !== 'function' ) {
            continue;
        }

        if ( isset( $tool_call->function->arguments ) && is_string( $tool_call->function->arguments ) ) {
            $tool_call->function->arguments = json_decode( $tool_call->function->arguments );
        }

        if ( $tool_call->function->name !== 'send_email' ) {
            continue;
        }

        $subject = sanitize_text_field( $tool_call->function->arguments->subject );
        $message = wp_kses_post( $tool_call->function->arguments->message );

        wp_mail( get_option( 'admin_email' ), $subject, $message );

        // Optionally set the text the AI appears to reply with.
        if ( ! isset( $reply->choices ) ) {
            $reply->choices    = array();
            $reply->choices[0] = new stdClass();
        }
        $reply->choices[0]->text             = 'Email sent.';
        $reply->choices[0]->message->content = 'Email sent.';
    }

    return $reply;
}, 10, 2 );

The classes#

Aiomatic_Query_Function( $name, $description, $parameters, $required ) and Aiomatic_Query_Parameter( $name, $description, $type, $required ).

The description is not documentation — it is the instruction to the model. It is how the model decides whether to call your tool. Be specific about when it should and should not be used:

php
new Aiomatic_Query_Function(
    'check_order_status',
    'Look up the current status of a customer order by its order number. ' .
    'Use this only when the visitor gives an order number. ' .
    'Do not use it to look up products, and do not guess an order number.',
    array( new Aiomatic_Query_Parameter( 'order_number', 'The order number, digits only', 'string', true ) ),
    false
);

Requirements#

A function-calling model. See Selecting models.

Tool calling enabled for the placement. The preview, global and per-shortcode switches are separate. See Chatbot Extensions.

Responses API toggles off, if tools do not fire. Several beta implementations do not support them.

FilterPurpose
aiomatic_ai_functionsRegister tools
aiomatic_post_ai_functionsThe tool list after built-ins are added
aiomatic_ai_reply_rawThe raw response, for handling calls
aiomatic_ai_responses_reply_rawThe same, for the Responses API path
aiomatic_google_tools_ai_reply_rawThe same, for the Google path
aiomatic_function_resultThe tool result before it goes back to the model

Actions: aiomatic_tool_result and aiomatic_tool_direct_message.

Security#

A defensive tool:

php
$order_number = preg_replace( '/[^0-9]/', '', (string) $args->order_number );

if ( $order_number === '' || strlen( $order_number ) > 12 ) {
    return 'Invalid order number.';
}

$order = my_get_order( (int) $order_number );

if ( ! $order ) {
    return 'No order found with that number.';
}

// Return only what the visitor is entitled to see.
return sprintf( 'Order %d is currently %s.', $order->id, $order->status );

Note the last line: return the minimum. Everything a tool returns goes into the model context and may be repeated to the visitor.

MCP as an alternative#

If your tool would be useful to more than this plugin, consider exposing it as an MCP server instead. Aimogen Pro can connect to it, and so can any other MCP-capable client.

Still stuck? Open a support ticket and include the diagnostics from Aimogen Pro › System & Logs › System Info.