Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/ishinaillab/ishi-social-ai-gateway/archive/refs/heads/main.zipIshi Social AI Gateway 1.1.0
Secure transport gateway between Ishi Nail Lab's social channels and the existing AI Engine chatbot.
Version 1.1 keeps the original asynchronous ManyChat bridge and adds a production synchronous Chatfuel endpoint. AI Engine remains the single conversational brain; this plugin does not duplicate Ishi's prompt, Knowledge, Easy MCP, or LatePoint logic.
Architecture
Chatfuel
Instagram
↓
Chatfuel
↓
Ishi Chatfuel Bridge (Node)
↓ HTTPS + dedicated Bearer token
POST /wp-json/ishi-social-ai/v1/respond
↓
AI Engine chatbot
↓
Knowledge / Easy MCP / LatePoint
↓
JSON reply
↓
Chatfuel bridge
↓
Instagram
Legacy ManyChat
Social channel
↓
ManyChat
↓
POST /wp-json/ishi-social-ai/v1/message
↓
Action Scheduler / WP-Cron
↓
AI Engine chatbot
↓
ManyChat sendContent
The ManyChat path remains asynchronous because its external-request timeout is shorter than a complete AI/tool turn can be.
What changed in 1.1
- Added synchronous
POST /respondfor Chatfuel. - Added a separate Chatfuel bridge credential. Do not reuse the Chatfuel API token.
- Added durable, concurrency-safe idempotency backed by a WordPress database table.
- Added persistent handoff state storage.
- Replaced transient-only rate counters for the AI path with atomic database counters.
- Added a stable plugin-owned HMAC secret for new Chatfuel conversation identifiers and hashed storage keys. Legacy ManyChat chat IDs keep the v1.0 derivation so existing AI Engine discussion continuity is preserved.
- Added strict JSON and opaque-identifier validation.
- Added
Cache-Control: no-store/Pragma: no-cacheon gateway responses. - Added structured, non-sensitive AI failures.
- Preserved the original ManyChat endpoint and delivery behavior.
- Uses AI Engine's supported PHP chatbot API:
simpleChatbotQuery( $botId, $message, [ 'chatId' => $chatId ], true ).
Requirements
- WordPress 6.9+
- PHP 8.1+
- AI Engine with the configured Ishi chatbot available
- AI Engine Discussions enabled when persistent conversation history is desired
- Chatfuel bridge app for the synchronous Instagram transport
The production site currently uses PHP 8.3, which satisfies this plugin's requirement.
Installation / upgrade
- Back up WordPress and the database.
- Install/replace the existing Ishi Social AI Gateway plugin with v1.1.0.
- Activate the plugin. The upgrade routine creates/updates the required database tables automatically.
- Go to Settings → Ishi Social AI Gateway.
- Confirm the exact AI Engine chatbot ID used by Ishi.
- Generate a Chatfuel Bridge Token and copy it immediately.
- Keep the existing legacy gateway token if the ManyChat integration is still in use.
The Chatfuel token is shown only once. WordPress stores only its SHA-256 hash.
Chatfuel synchronous endpoint
Method:
POST
URL:
https://povnailstudio.com/wp-json/ishi-social-ai/v1/respond
Headers:
Authorization: Bearer <ISHI CHATFUEL BRIDGE TOKEN>
Content-Type: application/json
Accept: application/json
Request:
{
"channel": "instagram",
"contact_id": "CHATFUEL_CONTACT_ID",
"message_id": "CHATFUEL_MESSAGE_ID",
"message": "Do you have slots tomorrow?"
}
For v1, the synchronous route intentionally accepts Instagram only and requires message_id.
Normal response:
{
"ok": true,
"reply": "Ishi's reply",
"handoff": false
}
Handoff response:
{
"ok": true,
"reply": "",
"handoff": true
}
Idempotency
The first request atomically claims channel + message_id before rate limiting or AI Engine.
If the same completed message is submitted again within the idempotency TTL, the gateway returns the stored response and does not invoke AI Engine again.
A simultaneous duplicate that arrives while the first request is still processing receives HTTP 409. A failed AI request can be retried safely.
Only HMAC hashes of social identifiers are stored in the idempotency/state/rate tables; message text and AI reply text are not written to normal logs.
Conversation continuity
For Chatfuel, the plugin derives an opaque stable AI Engine chatId from the social channel + contact ID using HMAC-SHA256 and a plugin-owned server secret. Legacy ManyChat keeps its v1.0 chat-ID derivation to avoid breaking existing AI Engine discussions during the upgrade.
The raw Chatfuel contact ID is not inserted into AI instructions.
If AI Engine Discussions are enabled, AI Engine can use that stable chatId to restore/persist the chatbot discussion using its normal chatbot pipeline.
Human handoff
The state endpoint remains:
POST /wp-json/ishi-social-ai/v1/state
It uses the legacy gateway token for backward compatibility.
Body:
{
"channel": "instagram",
"contact_id": "123456789",
"state": "human_active"
}
Supported states:
ai_activehuman_requiredhuman_active
When the stored state is not ai_active, /respond returns handoff: true without calling AI Engine.
Chatfuel remains the primary authority for live operator takeover. The Node bridge also re-checks Chatfuel conversation status before it sends an AI reply. WordPress state is a secondary fail-safe.
There is also a server-side filter for deterministic escalation rules:
apply_filters( 'ishi_social_ai_handoff_required', false, $payload, $reply );
The plugin deliberately does not parse free-form AI prose for magic handoff phrases.
Rate limits
Rate limits are evaluated only after idempotency has been claimed, so harmless duplicate delivery does not consume another paid AI turn.
Defaults:
- 12 AI requests/minute per social contact
- 120 AI requests/minute globally
Both are configurable in Settings → Ishi Social AI Gateway.
Legacy ManyChat endpoint
Existing endpoint:
POST /wp-json/ishi-social-ai/v1/message
It continues to accept the legacy social payload and queues AI work through Action Scheduler when available, otherwise WP-Cron.
The final response is still delivered through ManyChat's Public API.
Health endpoint
GET /wp-json/ishi-social-ai/v1/health
Use the legacy gateway token.
It reports non-secret readiness information including:
- plugin/schema version
- AI Engine PHP API readiness
- Chatfuel bridge token readiness
- legacy gateway token readiness
- ManyChat key readiness
- queue backend
Server-side secrets
Recommended production configuration keeps third-party credentials out of the database where practical.
Supported constants include:
define( 'ISHI_SOCIAL_MANYCHAT_API_KEY', '...' );
define( 'ISHI_SOCIAL_GATEWAY_TOKEN_HASH', 'sha256-hash-here' );
define( 'ISHI_SOCIAL_CHATFUEL_TOKEN_HASH', 'sha256-hash-here' );
define( 'ISHI_SOCIAL_CHAT_ID_SECRET', 'long-random-secret-here' );
Do not reuse:
- Chatfuel API token
- OpenAI API key
- Easy MCP token
- PayMongo credentials
- Short.io credentials
- WordPress password
as the Chatfuel bridge token.
Data/storage
v1.1 creates:
{prefix}ishi_social_ai_requests— hashed durable idempotency ledger{prefix}ishi_social_ai_states— hashed persistent handoff state{prefix}ishi_social_ai_rates— hashed rate-limit counters
Expired rows are cleaned lazily at most once per hour when the synchronous endpoint receives traffic.
The plugin does not store raw Chatfuel contact/message IDs in these tables.
Required pre-production tests
Keep the Node bridge disabled until all of these pass:
- Authentication — missing/wrong Chatfuel bridge token is rejected.
- Normal AI request — valid Instagram payload returns
ok: true, a non-emptyreply, andhandoff: false. - Idempotency — send the exact same
message_idtwice; the second request returns the stored response without another AI turn. - Concurrent duplicate — a duplicate while the first is still running is rejected as already processing.
- Handoff — set the conversation to
human_active;/respondreturnshandoff: truewith an empty reply and does not invoke AI. - Resume — set the same conversation back to
ai_active; new message IDs can reach AI again. - Oversized message — more than 4,000 characters is rejected before AI Engine.
- Unsupported channel — the Chatfuel synchronous endpoint rejects anything other than Instagram.
Only after these pass should Hostinger set:
ISHI_BRIDGE_ENABLED=true