Sitemap

Build Smart WordPress Plugins: A Guide to LLM Integrations with a Robust Boilerplate

8 min readJan 18, 2026

--

Press enter or click to view image in full size

The world of LLM integrations is rapidly changing how we build intelligent applications. Imagine a WordPress website that can understand complex queries, generate content, or even summarize conversations, all powered by AI. Integrating Large Language Models (LLMs) like OpenAI, Gemini, and Grok directly into your WordPress plugin can unlock these powerful AI capabilities.

This article will guide you through a robust WordPress plugin boilerplate, detailing the architecture and core classes responsible for these advanced LLM integrations in WordPress. We’ll explore a well-structured plugin designed for extensibility and maintainability, providing a solid foundation for your AI-powered WordPress projects.

Ready to dive into the code? Here’s the GitHub repository for the complete plugin:

https://github.com/d5b94396feba3/llms-apis-wp-boilerplate-plugin

Let’s begin!

The Foundation: WordPress Plugin Boilerplate for LLM Integrations

Our example plugin, my-wp-plugin, is built upon a standardized WordPress development approach. This structure promotes scalability and maintainability, which is especially crucial when dealing with complex LLM integrations. It ensures a clear separation of concerns, making the plugin easier to develop, debug, and maintain.

Here’s a quick look at the typical directory structure:

my-wp-plugin/
├── 📄 my-wp-plugin.php # Main plugin file
├── 📁 includes/ # Core PHP classes
│ ├── 📄 class-main.php # Plugin orchestrator
│ ├── 📄 class-loader.php # Hook manager
│ ├── 📄 class-activator.php # Activation handler
│ └── 📄 class-deactivator.php # Deactivation handler
├── 📁 admin/ # Backend functionality ONLY
│ ├── 📄 class-admin.php # Admin controller
│ └── 📁 partials/ # Admin HTML templates
├── 📁 public/ # Frontend functionality ONLY
│ └── 📄 class-public.php # Frontend controller
├── 📁 assets/ # ALL static files (CSS, JS, Images)
├── 📁 languages/ # Translation files
└── 📄 uninstall.php # Cleanup when deleted

For our LLM integrations specifically, the most critical classes we’ll focus on reside within the includes/ directory.

The Central Brain: AICA_Plugin_LLM_Processor

The AICA_Plugin_LLM_Processor class acts as the central hub for all interactions with the LLMs within the plugin. Think of it as the brain that orchestrates the entire process: it selects the active LLM (Grok, OpenAI, or Gemini), constructs the full system instruction, and dispatches requests to the correct LLM-specific integration class.

The Constructor (`__construct`)

This method is vital for dynamically loading the correct LLM integration. Based on the user’s settings (e.g., chosen in the WordPress admin area), it instantiates the appropriate class for Grok, OpenAI, or Gemini.

class AICA_Plugin_LLM_Processor {
private $plugin_slug;
private $system_instruction;
private $llm_model;
    public function __construct($plugin_slug) {
$this->plugin_slug = $plugin_slug;
$this->system_instruction = get_option('ai_agent_system_prompt', 'You are an AI Assistant...');
$active_llm_model = get_option('llm_model', 'Grok'); if ($active_llm_model == "Grok") {
$this->llm_model = new AICA_Plugin_LLM_Grok($this->plugin_slug);
} elseif ($active_llm_model == "OpenAI") {
$this->llm_model = new AICA_Plugin_LLM_OpenAI($this->plugin_slug);
} elseif ($active_llm_model == "Gemini") {
$this->llm_model = new AICA_Plugin_LLM_Gemini($this->plugin_slug);
}
}
// ... rest of the class
}

Getting an LLM Response (`get_llm_response`)

This is the primary method for handling user queries and generating LLM responses. It carefully constructs the system_instruction by combining a core prompt, user-defined prompts, positive/negative feedback examples from the database, and content from the plugin's knowledge base. It then delegates the actual API call to the llm_api_v2 method of the currently active LLM model, which supports various types of inputs (multimodal).

Chat Summarization (`get_chat_summary`)

This utility method uses the llm_api_v3 (text-only) of the chosen LLM to summarize a conversation history. It prepares a structured prompt with the chat transcript and requests a concise summary, useful for customer service logs or quick overviews.

Automated System Prompt Generation (`generate_automated_system_prompt`)

Leveraging the LLM’s own capabilities, this method can automatically generate a sophisticated system prompt based on your website’s knowledge base content. It uses a template, replaces a placeholder with extracted content, and then calls llm_api_v3 to generate a tailor-made prompt for your AI assistant.

Deep Dive into Individual LLM Integrations

To ensure flexibility, each LLM (Gemini, Grok, OpenAI) has its own dedicated class. This modular design abstracts away the specific details of each API, making it easier to add new LLMs or update existing ones without disrupting the entire plugin. They all share common patterns:

  • llm_api_v2: Handles multimodal inputs (text, images, documents) and manages conversation history.
  • llm_api_v3: Designed for simpler, text-only interactions, often used for tasks like summarization or prompt generation.
  • prepare_attachments: A private helper method to process local files (extract text from PDFs/TXTs, encode images to Base64, or upload large files to the LLM's service).
  • request_llm_service_name: The core method that makes the actual API call to the respective LLM, including robust error handling.

Let’s break down each integration to see how they manage diverse inputs and API requirements for seamless LLM integrations in WordPress.

1. Gemini Integration (`AICA_Plugin_LLM_Gemini`)

This class handles all communication with Google’s Gemini API, supporting both text and multimodal inputs. It’s smart about managing file uploads, especially for large documents.

llm_api_v2 and prepare_attachments

Gemini’s llm_api_v2 is designed to handle attachments efficiently. For images, it encodes them as Base64 data. For PDFs and plain text files, it checks their size: small files are directly embedded, while larger files (over 1MB) are uploaded to Gemini's file service via upload_to_gemini to get a file_uri. This optimizes API calls and handles large data payloads effectively.

// Excerpt from AICA_Plugin_LLM_Gemini::prepare_attachments
private function prepare_attachments(): array {
$file_id = get_option('ai_agent_knowledge_file_id');
$data = ['multimodal_parts' => [], 'file_context_text' => ""];
    if (!$file_id) return $data;    $file_path = get_attached_file($file_id);
$mime_type = get_post_mime_type($file_id);
$file_size = filesize($file_path);
$extraction_threshold = 1 * 1024 * 1024; // 1MB
if (strpos($mime_type, 'image') !== false) {
$data['multimodal_parts'][] = [
'inline_data' => [
'mime_type' => $mime_type,
'data' => base64_encode(file_get_contents($file_path))
]
];
}
else if ($mime_type === 'application/pdf' || $mime_type === 'text/plain') {
if ($file_size < $extraction_threshold) {
// ... extract text directly ...
} else {
$transient_key = 'aica_gemini_uri_' . $file_id;
$file_uri = get_transient($transient_key);
if (false === $file_uri) {
$file_uri = $this->upload_to_gemini($file_path, $mime_type);
if ($file_uri) set_transient($transient_key, $file_uri, 1 * HOUR_IN_SECONDS);
}
if ($file_uri) {
$data['multimodal_parts'][] = [
'file_data' => [
'mime_type' => $mime_type,
'file_uri' => $file_uri
]
];
}
}
}
return $data;
}

upload_to_gemini

This method handles the specific resumable upload protocol required by Gemini for large files. It first initiates an upload to get a unique upload URL, then sends the file content, often in chunks, to ensure reliable transfer.

request_gemini

This private method constructs the final API payload for Gemini, including the system instruction, conversation history, and generation settings like temperature. It then sends the request using WordPress’s `wp_remote_post` function, managing potential errors and parsing the LLM’s response.

2. Grok Integration (`AICA_Plugin_LLM_Grok`)

The Grok integration allows your WordPress plugin to tap into xAI’s Grok models. This implementation supports both direct text and file-based multimodal interactions, making it a comprehensive solution for LLM integrations.

llm_api_v2 and prepare_attachments

Similar to Gemini, Grok’s llm_api_v2 uses prepare_attachments for file handling. Images are Base64 encoded and included directly in the user message. For PDF or plain text files, if they are small, their content is appended to the system instruction. For larger files, the ensure_grok_file method is called to upload the file to Grok's service, and the returned file_id is then referenced in the request.

// Excerpt from AICA_Plugin_LLM_Grok::prepare_attachments
private function prepare_attachments(): array {
$file_id = get_option('ai_agent_knowledge_file_id');
$data = ['multimodal_parts' => [], 'file_context_text' => ""];
    if (!$file_id) return $data;    $file_path = get_attached_file($file_id);
if (!$file_path || !file_exists($file_path)) return $data;
$mime_type = get_post_mime_type($file_id);
$file_size = filesize($file_path);
$threshold = 1 * 1024 * 1024; // 1MB
if (strpos($mime_type, 'image') !== false) {
$data['multimodal_parts'][] = [
'type' => 'image_url',
'image_url' => ['url' => "data:$mime_type;base64," . base64_encode(file_get_contents($file_path)), 'detail' => 'auto']
];
}
else if ($mime_type === 'application/pdf' || $mime_type === 'text/plain') {
if ($file_size < $threshold) {
// ... extract text directly ...
} else {
$grok_file_id = $this->ensure_grok_file($file_path, $file_id);
error_log("grok_file_id : ".$grok_file_id); if ($grok_file_id) {
$data['multimodal_parts'][] = [
'type' => 'file',
'file' => ['file_id' => $grok_file_id]
];
}
}
}
return $data;
}

ensure_grok_file

This method handles uploading files to Grok’s /v1/files endpoint using a multipart/form-data request. It's designed to be efficient by caching the file ID, preventing redundant uploads of the same file within a short period, saving on API costs and improving performance.

request_grok

This method constructs the full message payload for Grok, including the system prompt (referred to as developer_text in the code) and the conversation history. It then sends this payload to the /v1/chat/completions endpoint, managing API keys and handling error responses from Grok.

3. OpenAI Integration (`AICA_Plugin_LLM_OpenAI`)

The OpenAI integration connects your plugin to various OpenAI models, including those supporting multimodal capabilities (like GPT-4o). This particular implementation uses the /v1/responses endpoint, which is optimized for conversational AI with structured input/output, enhancing your WordPress LLM integrations.

llm_api_v2 and prepare_attachments

For llm_api_v2, prepare_attachments processes incoming files. Images are Base64 encoded as input_image types. Text-based documents (PDF, TXT) are either directly embedded if small or uploaded to OpenAI's file service via ensure_openai_file to obtain a file_id, which is then referenced as an input_file type. This flexible handling supports diverse data types.

// Excerpt from AICA_Plugin_LLM_OpenAI::prepare_attachments
private function prepare_attachments(): array {
$file_id = get_option('ai_agent_knowledge_file_id');
$data = ['multimodal_parts' => [], 'file_context_text' => ""];
    if (!$file_id) return $data;    $file_path = get_attached_file($file_id);
if (!$file_path || !file_exists($file_path)) {
error_log("AICA OpenAI: File path not found for ID $file_id");
return $data;
}
$mime_type = get_post_mime_type($file_id);
$file_size = filesize($file_path);
$threshold = 10 * 1024 * 1024; // 10MB
if (strpos($mime_type, 'image') !== false) {
$data['multimodal_parts'][] = [
'type' => 'input_image',
'image_url' => ['url' => "data:$mime_type;base64," . base64_encode(file_get_contents($file_path))]
];
}
else if ($mime_type === 'application/pdf' || $mime_type === 'text/plain') {
if ($file_size < $threshold) {
// ... extract text directly ...
} else {
$openai_file_id = $this->ensure_openai_file($file_path, $file_id);
if ($openai_file_id) {
$data['multimodal_parts'][] = [
'type' => 'input_file',
'file' => ['file_id' => $openai_file_id]
];
}
}
}
return $data;
}

ensure_openai_file

This method uploads files to OpenAI’s /v1/files endpoint with a purpose of user_data. It also uses a transient cache to store the OpenAI file ID, preventing redundant uploads and speeding up subsequent requests, similar to Grok.

format_conversation_items

This method is crucial for structuring the conversation for the OpenAI /v1/responses endpoint. It meticulously formats messages into an items array, clearly differentiating between input_text (user queries) and output_text (assistant responses), and integrating any multimodal parts seamlessly.

request_openai

This method constructs the final payload for the /v1/responses endpoint, including instructions (system prompt), input (formatted conversation items), the chosen model, and temperature. It then sends the request and processes the structured response from OpenAI, handling potential API errors for a robust experience.

Key Takeaways for Powerful WordPress LLM Integrations

Here’s what makes this boilerplate approach so effective for embedding AI into your WordPress site:

  • Modular Design: The plugin uses a boilerplate to separate concerns, making LLM integrations clean, manageable, and easy to extend. This means you can add new features or modify existing ones without breaking everything.
  • Dynamic LLM Selection: Users can easily switch between Grok, OpenAI, and Gemini models directly from WordPress settings. The plugin’s architecture handles this seamlessly without requiring code changes.
  • Multimodal Support: The llm_api_v2 methods and prepare_attachments enable rich interactions with various data types, including images and documents. Your AI can "see" and "read" different types of content.
  • Context Management: System instructions are dynamically built, incorporating core prompts, user-defined settings, feedback mechanisms, and knowledge base content. This ensures more relevant and personalized AI responses.
  • Robust Error Handling: Each integration includes checks for missing API keys, connection errors, and specific LLM-reported errors, providing clearer feedback and a more stable user experience.

This architecture provides a powerful and flexible way to embed cutting-edge AI capabilities directly into your WordPress applications. By understanding these core classes and their interactions, you’re well-equipped to build intelligent features that enhance user experience and automate complex tasks in your WordPress plugin development.

Get Started and Share Your Thoughts!

What are your thoughts on building LLM-powered WordPress plugins? Have you implemented similar LLM integrations in WordPress or faced unique challenges? Share your experiences and questions in the comments below!

If you found this deep dive helpful, please consider sharing it with your network and following me for more content on AI, WordPress, and plugin development.

Complete code at this repo:

https://github.com/d5b94396feba3/llms-apis-wp-boilerplate-plugin

--

--

Md Shahibur Rahman
Md Shahibur Rahman

Written by Md Shahibur Rahman

Full-Stack Engineer | Web, AI & Automation | Preferred & Top 3% @ Freelancer | Solopreneur sharing insights on projects and tech I’m passionate about