hudhaifas / silverstripe-gpt-actions
Expose secure server-side actions to ChatGPT via OpenAPI and expirable API keys.
Installs: 63
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:silverstripe-vendormodule
Requires
This package is not auto-updated.
Last update: 2025-08-01 01:18:08 UTC
README
Expose your custom server-side logic to GPTs and AI clients via secure, structured endpoints.
The silverstripe-gpt-actions module allows you to define and expose server-side actions through a secure HTTP interface for integration with custom GPTs (ChatGPT plugins) or other AI tools.
It supports:
- Custom GET endpoints per action
- OpenAPI schema generation (
/gpt/openapi
) for easy GPT integration - Secure access using expirable API keys
- CMS management of API keys
- Google Analytics 4 (GA4) usage tracking (optional)
- Developer-friendly action registration and manifest system
โ Requires SilverStripe 4.10+ or 5.x
๐ฆ Installation
composer require hudhaifas/silverstripe-gpt-actions
Enable the module in your SilverStripe project, then run:
vendor/bin/sake dev/build flush=1
๐ง Use Cases
This module is ideal for:
- Enabling GPTs to access domain-specific actions directly
- Exposing structured data and tools to AI models
- Creating secure and discoverable AI endpoints
- Tracking GPT usage analytics via GA4
๐งฉ Defining Actions
Create a PHP class implementing a run()
static function and a describe()
static method:
namespace MyApp\GPTActions; use Exception; class GetEntityByIDAction { public static function run(array $parameters) { if (!isset($parameters['EntityID'])) { throw new Exception("Missing parameter: EntityID"); } $entity = MyEntity::get_by_id($parameters['EntityID']); return [ 'ID' => $entity->ID, 'Name' => $entity->Name, 'Details' => $entity->Details ]; } public static function describe(): array { return [ 'name' => 'GetEntityByID', 'description' => 'Retrieve an entity by its unique ID.', 'parameters' => [ 'EntityID' => [ 'type' => 'integer', 'required' => true, 'description' => 'The numeric ID of the entity' ], ], ]; } }
The
describe()
method is used to auto-generate OpenAPI documentation.
โ๏ธ Registering Actions
Register actions in your YAML config (e.g., app/_config/gpt-actions.yml
):
GptActions\Util\GPTActionRegistry: available_actions: GetEntityByID: MyApp\GPTActions\GetEntityByIDAction SearchEntities: MyApp\GPTActions\SearchEntitiesAction
๐ Available Endpoints
GET /gpt/action/{ActionName}?param1=value1&...
Invokes a specific action. Example:
GET /gpt/action/GetEntityByID?EntityID=123
Authorization: Bearer YOUR_API_KEY
GET /gpt/openapi
Returns a dynamic OpenAPI 3.1 JSON schema for all registered actions.
๐ API Key Authentication
Manage API keys from the CMS under the GPT Keys section.
Each key:
- Is a 64-character token
- Can be linked to a
Member
- Can expire and/or be deactivated
- Inherits the same permissions and access scope as the linked
Member
Authentication Methods:
- โ
Recommended:
Authorization: Bearer YOUR_KEY
- ๐งช Testing only:
?key=YOUR_KEY
๐ก๏ธ Request Authentication
The module uses the GPTAuthenticator
class to validate incoming requests.
Internally, each request to /gpt/*
is authenticated via the controllerโs init()
method:
if (!GPTAuthenticator::authenticate($this->getRequest())) { return $this->httpError(401, 'Unauthorized GPT access'); }
You may reuse the GPTAuthenticator::authenticate()
method anywhere in your project.
โ๏ธ SiteConfig Integration
To customize OpenAPI schema metadata and enable analytics, the module extends SiteConfig
with:
Field | Purpose |
---|---|
GPTActionTitle |
Appears in OpenAPI info.title |
GPTActionDescription |
Appears in OpenAPI info.description |
GPTAnalyticsMeasurementID |
GA4 Measurement ID |
GPTAnalyticsAPISecret |
GA4 API Secret |
All can be set from the CMS Settings UI.
๐ GPT Usage Analytics (Optional)
If configured via SiteConfig
, the module will send usage events to Google Analytics 4 (GA4) using the [Measurement Protocol].
Tracked event: gpt_action_called
Event parameters:
Param | Example | Description |
---|---|---|
action_name |
GetEntityByID | Name of the called action |
success |
true/false |
Whether the action succeeded |
๐ Example OpenAPI Output
{ "openapi": "3.1.0", "info": { "title": "My Custom GPT", "description": "Custom actions exposed for GPT integration.", "version": "1.0.0" }, "paths": { "/gpt/action/GetEntityByID": { "get": { "summary": "Retrieve an entity by ID.", "parameters": [ { "name": "EntityID", "in": "query", "required": true, "schema": { "type": "integer" } } ] } } } }
๐งช Testing Endpoints
fetch('https://yourdomain.com/gpt/action/GetEntityByID?EntityID=123', { headers: { Authorization: 'Bearer YOUR_KEY' } }) .then(res => res.json()) .then(console.log);
๐ค Creating a Custom GPT
You can easily create a ChatGPT plugin (Custom GPT) that consumes the OpenAPI spec exposed at /gpt/openapi
.
๐ See docs/CustomGPT.md for a walkthrough on publishing your GPT on ChatGPT.com.
๐ License
MIT
โ๏ธ Maintainer
Hudhaifa โ amlineage.com