{"id":16570,"date":"2025-10-17T09:13:52","date_gmt":"2025-10-17T07:13:52","guid":{"rendered":"https:\/\/www.juust.org\/?p=16570"},"modified":"2025-10-17T10:01:15","modified_gmt":"2025-10-17T08:01:15","slug":"openai-agents-in-wordpress","status":"publish","type":"post","link":"https:\/\/www.juust.org\/index.php\/openai-agents-in-wordpress\/2025\/10\/","title":{"rendered":"OpenAI Agents in WordPress"},"content":{"rendered":"\n<p>Yesterday, I deployed my first <strong>OpenAI Agent<\/strong> directly inside a WordPress environment. Earlier that morning, I had started a Udemy course on OpenAI Agents SDK automation \u2014 but it kicked off with Anaconda and Python, which didn\u2019t align with my goal of integrating the stack natively within WordPress.<\/p>\n\n\n\n<p>So I pivoted and brought GitHub Copilot into the loop. Over time, I\u2019ve learned how to use Copilot far more effectively \u2014 not as a conversational assistant (like ChatGPT\u2019s Q\/A loop), but as a pattern-driven code generator. LLM&#8217;s excel at language and pattern recognition and so do I, accidentally. So for me the architectural pattern approach works a lot more &#8216;natural&#8217;. Once you shift your mindset from prompting line-by-line edits to describing architectural intent, the AI begins producing complete specifications<strong>.<\/strong> In <strong>Agent mode<\/strong>, it executes those specs iteratively, building out functionality step by step \u2014 exactly how a competent junior developer would.<\/p>\n\n\n\n<p>I started re-skilling right after my surgeries back in September 2021 \u2014 this time deep-diving into JavaScript, React, and Next.js.<br \/>That decision turned out to be spot-on: most of the emerging AI-augmented UX frameworks and <strong>\u201cvibe tools\u201d<\/strong> are React-based because of its declarative paradigm, which aligns best with LLM&#8217;s.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Agents Server<\/h2>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.juust.org\/wp-content\/uploads\/2025\/10\/afbeelding-2.png\"><img fetchpriority=\"high\" decoding=\"async\" width=\"893\" height=\"554\" src=\"https:\/\/www.juust.org\/wp-content\/uploads\/2025\/10\/afbeelding-2.png\" alt=\"AI Agents SDK WordPress\" class=\"wp-image-16569\" srcset=\"https:\/\/www.juust.org\/wp-content\/uploads\/2025\/10\/afbeelding-2.png 893w, https:\/\/www.juust.org\/wp-content\/uploads\/2025\/10\/afbeelding-2-300x186.png 300w, https:\/\/www.juust.org\/wp-content\/uploads\/2025\/10\/afbeelding-2-768x476.png 768w\" sizes=\"(max-width: 893px) 100vw, 893px\" \/><\/a><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<p>By the evening, I already had it up and running inside WordPress.<\/p>\n\n\n\n<p>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 <a href=\"https:\/\/github.com\/juustesout\/agent-server\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a>.<\/p>\n\n\n\n<p>I\u2019m using <strong>OPENAI_API_KEY<\/strong> and <strong>API_KEY<\/strong> as Vercel secrets \u2014 no need for the local <code>.env<\/code> configuration, the dot-env just serves as a reminder.<\/p>\n\n\n\n<p><\/p>\n<\/div>\n<\/div>\n\n\n\n<p>Once you have it up and running you can use the API from WordPress :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    \/**\n     * Get list of available agents\n     *\n     * @return array|false API response or false on failure\n     *\/\n    public function get_agents() {\n        if (empty($this-&gt;api_key)) {\n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'missing_api_key',\n                'message' =&gt; __('API key is not configured.', 'ai-agents-client')\n            );\n        }\n        \n        $endpoint = '\/api\/agents';\n        return $this-&gt;make_request('GET', $endpoint);\n    }<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    \/**\n     * Make HTTP request to API\n     *\n     * @param string $method HTTP method (GET, POST, etc.)\n     * @param string $endpoint API endpoint\n     * @param array $data Request data for POST requests\n     * @param int $retry_count Current retry attempt\n     * @return array|false API response or false on failure\n     *\/\n    private function make_request($method, $endpoint, $data = array(), $retry_count = 0) {\n        $url = $this-&gt;base_url . $endpoint;\n        \n        $headers = array(\n            'x-api-key' =&gt; $this-&gt;api_key,\n            'Content-Type' =&gt; 'application\/json',\n            'Accept' =&gt; 'application\/json',\n            'User-Agent' =&gt; 'WordPress-AI-Agents-Client\/' . AI_AGENTS_CLIENT_VERSION\n        );\n        \n        \/\/ Add authorization header if auth API key is available\n        if (!empty($this-&gt;auth_api_key)) {\n            $headers&#91;'Authorization'] = 'Bearer ' . $this-&gt;auth_api_key;\n        }\n        \n        $args = array(\n            'method' =&gt; $method,\n            'timeout' =&gt; $this-&gt;timeout,\n            'headers' =&gt; $headers,\n            'data_format' =&gt; 'body'\n        );\n        \n        if ($method === 'POST' &amp;&amp; !empty($data)) {\n            $args&#91;'body'] = wp_json_encode($data);\n        }\n        \n        \/\/ Log the request for debugging (only in debug mode)\n        if (defined('WP_DEBUG') &amp;&amp; WP_DEBUG) {\n            error_log(\"AI Agents API Request: {$method} {$url}\");\n            if (!empty($data)) {\n                error_log(\"AI Agents API Request Data: \" . wp_json_encode($data));\n            }\n        }\n        \n        $response = wp_remote_request($url, $args);\n        \n        \/\/ Handle WordPress HTTP errors\n        if (is_wp_error($response)) {\n            $error_message = $response-&gt;get_error_message();\n            \n            \/\/ Log the error\n            if (defined('WP_DEBUG') &amp;&amp; WP_DEBUG) {\n                error_log(\"AI Agents API Error: \" . $error_message);\n            }\n            \n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'http_error',\n                'message' =&gt; sprintf(__('HTTP Error: %s', 'ai-agents-client'), $error_message)\n            );\n        }\n        \n        $status_code = wp_remote_retrieve_response_code($response);\n        $body = wp_remote_retrieve_body($response);\n        \n        \/\/ Log the response for debugging (only in debug mode)\n        if (defined('WP_DEBUG') &amp;&amp; WP_DEBUG) {\n            error_log(\"AI Agents API Response Code: {$status_code}\");\n            error_log(\"AI Agents API Response Body: \" . $body);\n        }\n        \n        \/\/ Handle rate limiting with retry logic\n        if ($status_code === 429 &amp;&amp; $retry_count &lt; 3) {\n            $retry_delay = pow(2, $retry_count); \/\/ Exponential backoff: 1s, 2s, 4s\n            sleep($retry_delay);\n            return $this-&gt;make_request($method, $endpoint, $data, $retry_count + 1);\n        }\n        \n        \/\/ Parse JSON response\n        $parsed_response = json_decode($body, true);\n        \n        if (json_last_error() !== JSON_ERROR_NONE) {\n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'invalid_json',\n                'message' =&gt; __('Invalid JSON response from API.', 'ai-agents-client')\n            );\n        }\n        \n        \/\/ Handle different HTTP status codes\n        if ($status_code &gt;= 200 &amp;&amp; $status_code &lt; 300) {\n            \/\/ Success response\n            return $parsed_response;\n        } elseif ($status_code === 401) {\n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'unauthorized',\n                'message' =&gt; __('Invalid API key or unauthorized access.', 'ai-agents-client')\n            );\n        } elseif ($status_code === 403) {\n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'forbidden',\n                'message' =&gt; __('Access forbidden. Check your API permissions.', 'ai-agents-client')\n            );\n        } elseif ($status_code === 404) {\n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'not_found',\n                'message' =&gt; __('API endpoint not found.', 'ai-agents-client')\n            );\n        } elseif ($status_code === 429) {\n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'rate_limited',\n                'message' =&gt; __('Rate limit exceeded. Please try again later.', 'ai-agents-client')\n            );\n        } elseif ($status_code &gt;= 500) {\n            return array(\n                'success' =&gt; false,\n                'error' =&gt; 'server_error',\n                'message' =&gt; __('Server error. Please try again later.', 'ai-agents-client')\n            );\n        } else {\n            \/\/ Return the parsed response even for other status codes\n            \/\/ as it might contain error details from the API\n            return $parsed_response ?: array(\n                'success' =&gt; false,\n                'error' =&gt; 'unknown_error',\n                'message' =&gt; sprintf(__('Unexpected response code: %d', 'ai-agents-client'), $status_code)\n            );\n        }\n    }<\/code><\/pre>\n\n\n\n<p>&#8230;so far, so good, (so what?)<\/p>\n\n\n\n<p>Today I am going to learn how to use memory and tools.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A basic OpenAI Agents SDK based API server on Vercel to develop Agents in Wordpress<\/p>\n","protected":false},"author":5796,"featured_media":16573,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_sitemap_exclude":false,"_sitemap_priority":"","_sitemap_frequency":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[4],"tags":[],"class_list":["post-16570","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-juust"],"_links":{"self":[{"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/posts\/16570","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/users\/5796"}],"replies":[{"embeddable":true,"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/comments?post=16570"}],"version-history":[{"count":3,"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/posts\/16570\/revisions"}],"predecessor-version":[{"id":16577,"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/posts\/16570\/revisions\/16577"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/media\/16573"}],"wp:attachment":[{"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/media?parent=16570"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/categories?post=16570"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.juust.org\/index.php\/wp-json\/wp\/v2\/tags?post=16570"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}