Credentials #
define( 'GOAIF_ANTHROPIC_API_KEY', '...' );
define( 'GOAIF_OPENAI_API_KEY', '...' );
Matching environment variables are also recognized. PHP constants take precedence. These values are provider secrets and are never database-encrypted by the plugin.
define( 'GOAIF_CREDENTIAL_ENCRYPTION_KEY', 'def00000...' );
Optional Defuse Crypto ASCII-safe key used only for credentials saved through WordPress. Choose the encryption method before saving credentials; changing it requires re-entering saved values.
Trusted Proxies #
define( 'GOAIF_TRUSTED_PROXIES', '192.0.2.0/24, 2001:db8::/32' );
Entries are merged with Controls values. Invalid entries are ignored. Use only official ranges for the service directly in front of WordPress.
Provider Timeouts #
define( 'GOAIF_PROVIDER_TIMEOUT', 60 );
define( 'GOAIF_ASYNC_WALL_CLOCK_LIMIT', 120 );
GOAIF_PROVIDER_TIMEOUT overrides the source-aware provider HTTP timeout. Without it, frontend text, streamed text, and frontend image requests use 60 seconds; other synchronous requests use 45 seconds. Async and workflow runs use the async wall-clock value as their provider ceiling.
Public Limits #
The default visitor limit is 10 requests in 3,600 seconds. The configured limit is constrained to 1–100 and the window to 60–86,400 seconds. The network ceiling is three times the visitor limit, capped at 100.
Filters #
add_filter( 'goaif_openai_image_request_body', function ( $body, $request ) {
$body['background'] = 'opaque';
return $body;
}, 10, 2 );
Adjusts the OpenAI image request body immediately before it is sent. The body has already been validated against the reviewed provider contract, so anything added here is sent as-is and is your responsibility to keep valid for the selected model. Always return the array; a non-array return is discarded and the unfiltered body is sent.
add_filter( 'goaif_image_moderation_message', function ( $message, $context ) {
return $context['base'];
}, 10, 2 );
The message shown when OpenAI declines an image prompt on content grounds. $context carries base, lines (the sentences appended to it), stage, categories, prompt, and the three attribution buckets: visitor_suggestions (traced to the visitor’s answers), feed_level_rules (traced to the feed’s own prompt) and unattributed_topics (named by OpenAI, matched in neither). The example above keeps the opening sentence and drops everything appended. Return a string; anything else is discarded. The per-feed Content Refusal Message setting supplies base, and this filter runs after it.
feed_level_rules is deliberately absent from the default message: those causes are the administrator’s to fix, so exposing them here would tell a visitor to change text they cannot reach. Add them only for an audience that can act on them.
add_filter( 'goaif_image_moderation_rules', function ( $rules ) {
unset( $rules['distress'] );
return $rules;
} );
The table mapping refusals onto suggestions. Each entry accepts:
categories— labels OpenAI reports inmoderation_details. Each reported category selects at most one rule, preferring an exact match, sosexual/minorsuses the rule listing it rather than also repeating the generalsexualrule.patterns— whole-word, case-insensitive keywords, a trailing “s” tolerated. Serve two purposes: they decide whose wording it was by testing the sent prompt against the feed template, and they select the rule outright when no reported category maps to one. OpenAI frequently answers with the catch-allother, so that second path is the common case, not the exception; results reached that way are flaggedinferredin the filter context and labelled as such in the admin table.suggestion— the sentence shown when the wording is the visitor’s.topic— a short noun phrase (“weapons, injuries, or conflict”) used when ownership cannot be established: “This was declined for {topic}. Check your answers…”.
At most three suggestions are appended to any message. Return the array; anything else is discarded. Write both suggestion and topic in the visitor’s voice, about their own answers.
add_filter( 'goaif_generated_value_is_html', function ( $is_html, $value, $field ) {
return $is_html;
}, 10, 3 );
Whether generated output bound for a rich-text destination is already HTML. When it is, the value is saved as written; when it is not, the supported Markdown subset is converted first. The default decision looks for the tags the converter itself emits (p, br, h1–h6, ul, ol, li, blockquote, strong, em, b, i, a). Return true to keep output that uses other tags, or false to force Markdown conversion and escape any tags in it. wp_kses_post() runs on both paths, so this filter cannot be used to save unsafe markup.
Field Output Adapters #
use GravityOpsAIFeedRuntimeFieldsFieldOutputAdapterRegistration;
add_filter( 'goaif_field_output_adapter_registrations', function ( $registrations ) {
$registrations[] = FieldOutputAdapterRegistration::exact_type(
'my_custom_field',
new My_Custom_Field_Output_Adapter()
);
return $registrations;
} );
Adds explicit field-output adapters. The adapter must implement FieldOutputAdapterInterface; frontend use additionally requires FrontendFieldOutputAdapterInterface. Register one exact declared type, effective input type, or effective field class. There is no catch-all selector, and extension-provided destinations require Premium or Agency. Replacing an intentional protected denial is available only through the third argument of exact_type() and should be reserved for a reviewed adapter that owns that exact custom field type.
add_filter( 'goaif_field_output_adapter_support', function ( $supported, $field, $target_id, $adapter, $support ) {
if ( 'my_custom_field' === $field->type && ! my_site_allows_ai_output( $field, $target_id ) ) {
return false;
}
return $supported;
}, 10, 5 );
Vetoes an exactly resolved adapter for one live field configuration. It cannot enable an unregistered or intentionally denied field. Return a Boolean; invalid values and exceptions fail closed before a provider request.
Active Output Plan #
use GravityOpsAIFeedRuntimeOutputOutputPlan;
add_filter( 'goaif_active_output_plan', function ( $plan, $context ) {
$items = array_values(
array_filter(
$plan->get_items(),
static fn( $item ) => 'internal_notes' !== $item->get_response_name()
)
);
return new OutputPlan(
$items,
$plan->get_existing_values(),
$plan->requires_structured_output()
);
}, 10, 2 );
Can remove or reorder the exact immutable items already approved for the current provider request. It cannot add a destination, duplicate an item, change Existing Values policy, or weaken the structured-output requirement. Return a non-empty OutputPlan; invalid plans and exceptions fail closed. $context contains only feed_id, form_id, entry_id, and source.
Normalized Values And Terminal Events #
add_filter( 'goaif_normalized_field_output', function ( $value, $item, $context ) {
return $value;
}, 10, 3 );
Filters one canonical semantic value before persistence or frontend delivery. The same adapter normalizes the returned value again, so this filter cannot bypass the current field contract. $item is the active OutputPlanItem; $context contains only the safe request identifiers.
add_action( 'goaif_field_persistence_result', function ( $outcome, $context ) {
// Observe one field's persisted or skipped status without receiving its generated value.
}, 10, 2 );
add_action( 'goaif_text_feed_terminal', function ( $context ) {
// Observe the final feed status without receiving prompts, entry values, or provider output.
} );
The per-field action supplies field_id, status, and reason_code, followed by the safe request context. The terminal action supplies those request identifiers plus status, outcome, error_code, persistence_status, persisted_field_ids, and skipped_field_ids. These payloads deliberately exclude prompts, provider output, and entry values.
add_filter( 'goaif_text_generation_clients', function ( $clients ) {
return $clients;
} );
Provider-keyed text clients. Each must implement TextGenerationClientInterface; entries that do not are dropped.
Storage #
Plugin options use the goaif_ prefix. Custom tables store usage events, generation tokens, rate limits, and image sessions. Uninstall removes plugin options, scheduled cleanup, tables, entry metadata, and lock transients.
Runtime Sources #
Internal source names include submission_sync, submission_async, realtime_ajax, realtime_stream, image_stream, rerun, and workflow_step. Trigger matching applies to normal submission/frontend sources; a rerun or workflow step is an explicit administrator/workflow action.