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
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.