OpenAI Agents in WordPress

Yesterday, I deployed my first OpenAI Agent directly inside a WordPress environment. Earlier that morning, I had started a Udemy course on OpenAI Agents SDK automation — but it kicked off with Anaconda and Python, which didn’t align with my goal of integrating the stack natively within WordPress.

So I pivoted and brought GitHub Copilot into the loop. Over time, I’ve learned how to use Copilot far more effectively — not as a conversational assistant (like ChatGPT’s Q/A loop), but as a pattern-driven code generator. LLM’s excel at language and pattern recognition and so do I, accidentally. So for me the architectural pattern approach works a lot more ‘natural’. Once you shift your mindset from prompting line-by-line edits to describing architectural intent, the AI begins producing complete specifications. In Agent mode, it executes those specs iteratively, building out functionality step by step — exactly how a competent junior developer would.

I started re-skilling right after my surgeries back in September 2021 — this time deep-diving into JavaScript, React, and Next.js.
That decision turned out to be spot-on: most of the emerging AI-augmented UX frameworks and “vibe tools” are React-based because of its declarative paradigm, which aligns best with LLM’s.

Agents Server

AI Agents SDK WordPress

By the evening, I already had it up and running inside WordPress.

You can use the OpenAI Agents SDK in TypeScript to build a lightweight TS/JS wrapper application and deploy it on Vercel as an HTTP API. The server code itself is hosted on GitHub.

I’m using OPENAI_API_KEY and API_KEY as Vercel secrets — no need for the local .env configuration, the dot-env just serves as a reminder.

Once you have it up and running you can use the API from WordPress :

    /**
     * Get list of available agents
     *
     * @return array|false API response or false on failure
     */
    public function get_agents() {
        if (empty($this->api_key)) {
            return array(
                'success' => false,
                'error' => 'missing_api_key',
                'message' => __('API key is not configured.', 'ai-agents-client')
            );
        }
        
        $endpoint = '/api/agents';
        return $this->make_request('GET', $endpoint);
    }

    /**
     * Make HTTP request to API
     *
     * @param string $method HTTP method (GET, POST, etc.)
     * @param string $endpoint API endpoint
     * @param array $data Request data for POST requests
     * @param int $retry_count Current retry attempt
     * @return array|false API response or false on failure
     */
    private function make_request($method, $endpoint, $data = array(), $retry_count = 0) {
        $url = $this->base_url . $endpoint;
        
        $headers = array(
            'x-api-key' => $this->api_key,
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
            'User-Agent' => 'WordPress-AI-Agents-Client/' . AI_AGENTS_CLIENT_VERSION
        );
        
        // Add authorization header if auth API key is available
        if (!empty($this->auth_api_key)) {
            $headers['Authorization'] = 'Bearer ' . $this->auth_api_key;
        }
        
        $args = array(
            'method' => $method,
            'timeout' => $this->timeout,
            'headers' => $headers,
            'data_format' => 'body'
        );
        
        if ($method === 'POST' && !empty($data)) {
            $args['body'] = wp_json_encode($data);
        }
        
        // Log the request for debugging (only in debug mode)
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log("AI Agents API Request: {$method} {$url}");
            if (!empty($data)) {
                error_log("AI Agents API Request Data: " . wp_json_encode($data));
            }
        }
        
        $response = wp_remote_request($url, $args);
        
        // Handle WordPress HTTP errors
        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();
            
            // Log the error
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log("AI Agents API Error: " . $error_message);
            }
            
            return array(
                'success' => false,
                'error' => 'http_error',
                'message' => sprintf(__('HTTP Error: %s', 'ai-agents-client'), $error_message)
            );
        }
        
        $status_code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        
        // Log the response for debugging (only in debug mode)
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log("AI Agents API Response Code: {$status_code}");
            error_log("AI Agents API Response Body: " . $body);
        }
        
        // Handle rate limiting with retry logic
        if ($status_code === 429 && $retry_count < 3) {
            $retry_delay = pow(2, $retry_count); // Exponential backoff: 1s, 2s, 4s
            sleep($retry_delay);
            return $this->make_request($method, $endpoint, $data, $retry_count + 1);
        }
        
        // Parse JSON response
        $parsed_response = json_decode($body, true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            return array(
                'success' => false,
                'error' => 'invalid_json',
                'message' => __('Invalid JSON response from API.', 'ai-agents-client')
            );
        }
        
        // Handle different HTTP status codes
        if ($status_code >= 200 && $status_code < 300) {
            // Success response
            return $parsed_response;
        } elseif ($status_code === 401) {
            return array(
                'success' => false,
                'error' => 'unauthorized',
                'message' => __('Invalid API key or unauthorized access.', 'ai-agents-client')
            );
        } elseif ($status_code === 403) {
            return array(
                'success' => false,
                'error' => 'forbidden',
                'message' => __('Access forbidden. Check your API permissions.', 'ai-agents-client')
            );
        } elseif ($status_code === 404) {
            return array(
                'success' => false,
                'error' => 'not_found',
                'message' => __('API endpoint not found.', 'ai-agents-client')
            );
        } elseif ($status_code === 429) {
            return array(
                'success' => false,
                'error' => 'rate_limited',
                'message' => __('Rate limit exceeded. Please try again later.', 'ai-agents-client')
            );
        } elseif ($status_code >= 500) {
            return array(
                'success' => false,
                'error' => 'server_error',
                'message' => __('Server error. Please try again later.', 'ai-agents-client')
            );
        } else {
            // Return the parsed response even for other status codes
            // as it might contain error details from the API
            return $parsed_response ?: array(
                'success' => false,
                'error' => 'unknown_error',
                'message' => sprintf(__('Unexpected response code: %d', 'ai-agents-client'), $status_code)
            );
        }
    }

…so far, so good, (so what?)

Today I am going to learn how to use memory and tools.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top