kimaai_chatbot_blocked

kimaai_chatbot_blocked Hook #

The kimaai_chatbot_blocked action fires whenever a chatbot request is blocked by the gate (i.e., when kimaai_chatbot_gate does not return true). It’s designed for logging, analytics, security monitoring, and user-facing diagnostics.

This hook is triggered before the REST API returns a 403 response to the frontend.


When it fires #

A request is considered “blocked” when the kimaai_chatbot_gate filter returns anything other than true, for example:

  • a string (used as the error message shown to the user)
  • a WP_Error (its message is shown to the user)
  • any other non-true value (falls back to a generic message)

When blocked, the plugin:

  1. builds the error message
  2. calls do_action( 'kimaai_chatbot_blocked', ... )
  3. logs a warning
  4. returns WP_REST_Response([ 'error' => $message ], 403)

Hook signature #

/**
 * Action fired when a request is blocked by the gate.
 *
 * @param string $reason Message returned to the client.
 * @param array $payload Normalized payload.
 * @param array $data Raw request data.
 * @param WP_REST_Request $request Request.
 */
do_action('kimaai_chatbot_blocked', $error_message, $payload, $data, $request);

Parameters #

1) $reason (string) #

The message that will be returned to the client (frontend) as:

{ "error": "..." }

It comes from:

  • $allowed->get_error_message() if the gate returned WP_Error
  • the returned string if the gate returned a string
  • otherwise a default translated message

2) $payload (array) #

A normalized payload assembled by the chatbot handler. At minimum includes:

  • prompt (string) — the normalized prompt after kimaai_chatbot_prompt
  • postId (int)
  • selectedTools (string[])
  • later in the request lifecycle it may include more, but at the time of blocking it usually contains the above

3) $data (array) #

The raw JSON body from the request, e.g.:

  • message
  • postId

4) $request (WP_REST_Request) #

The REST request object (headers, route, IP-related context if you derive it elsewhere, etc.).


Basic usage: log blocked prompts #

add_action('kimaai_chatbot_blocked', function ($reason, $payload, $data, $request) {
  error_log('[KimaAI Chatbot Blocked] ' . $reason);
  error_log('Prompt: ' . ($payload['prompt'] ?? ''));
  error_log('Post ID: ' . (int) ($payload['postId'] ?? 0));
}, 10, 4);

Example: track blocked events in analytics (non-invasive) #

add_action('kimaai_chatbot_blocked', function ($reason, $payload) {
  // Pseudocode: replace with your analytics integration.
  if (function_exists('my_analytics_track')) {
    my_analytics_track('kimaai_chatbot_blocked', [
      'reason' => $reason,
      'postId' => (int) ($payload['postId'] ?? 0),
      'hasToolsSelected' => !empty($payload['selectedTools']),
    ]);
  }
}, 10, 4);

Example: notify admins when certain blocks spike #

You can increment a transient counter and email admins when it exceeds a threshold.

add_action('kimaai_chatbot_blocked', function ($reason) {
  $key = 'kimaai_blocked_count_' . gmdate('YmdH'); // per hour
  $count = (int) get_transient($key);
  $count++;
  set_transient($key, $count, HOUR_IN_SECONDS);

  if ($count === 25) {
    wp_mail(
      get_option('admin_email'),
      'KimaAI Chatbot: high block rate',
      "Blocked requests reached 25 this hour.\nLatest reason: {$reason}"
    );
  }
}, 10, 4);

Example: capture context safely (privacy-aware) #

If you need to store diagnostics, avoid raw prompts and store a hash instead.

add_action('kimaai_chatbot_blocked', function ($reason, $payload, $data, $request) {
  $prompt = (string) ($payload['prompt'] ?? '');
  $prompt_hash = $prompt !== '' ? hash('sha256', $prompt) : '';

  $entry = [
    'time'        => time(),
    'reason'      => $reason,
    'prompt_hash' => $prompt_hash,
    'postId'      => (int) ($payload['postId'] ?? 0),
    'route'       => method_exists($request, 'get_route') ? $request->get_route() : '',
  ];

  // Store however you want (options table, custom table, external logger, etc.)
  error_log('[KimaAI Blocked] ' . wp_json_encode($entry));
}, 10, 4);

Gate: kimaai_chatbot_gate (blocks/permits) #

You typically pair your blocking logic with logging via kimaai_chatbot_blocked.

add_filter('kimaai_chatbot_gate', function ($allowed, $prompt, $payload) {
  // Block empty-ish messages
  if (trim($prompt) === '') {
    return __('Please enter a message.', 'your-textdomain');
  }

  // Block specific terms
  if (stripos($prompt, 'refund my card') !== false) {
    return new WP_Error('kimaai_blocked_sensitive', __('Please contact support for billing requests.', 'your-textdomain'));
  }

  return true;
}, 10, 3);

Prompt normalization: kimaai_chatbot_prompt #

Runs before the gate, useful for trimming, removing repeated whitespace, etc.

Rate limit action: kimaai_chatbot_rate_limited #

Separate from gate-blocks (fires when the daily message limit is hit).


Notes and best practices #

  • Don’t echo output inside the hook. This runs during a REST request and can corrupt JSON responses.
  • Treat $payload/$data as user input (sanitize before storing/logging).
  • If you store anything, consider privacy and avoid logging full prompts unless you truly need them.
  • Use the hook for telemetry, alerts, auditing, and debugging—not for modifying the response (the decision to block has already been made).

Updated on December 13, 2025