Yarabot Chat WP Registry grade A. No security issues foundWP RegistryNo security issues foundOpen the reportA
Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/yarabot-ir/yarabot-wp-plugin/releases/download/v1.2.0/yarabot-chat-1.2.0.zipYarabot Chat — WordPress Plugin
Embed a Yarabot AI chat widget on any WordPress site. Visitors chat with your published Yarabot agent directly from the front end. The plugin acts as a secure server-side proxy — your sk-* API key never reaches the browser.
Requirements
| Requirement | Minimum |
|---|---|
| WordPress | 5.9+ |
| PHP | 7.4+ |
| PHP extension | curl, built against nghttp2 (HTTP/2 — see below) |
| Yarabot agent | Must be status=published and is_public=true |
Installation
Option A — Upload via WordPress Admin
- Download or clone this repository.
- Zip the folder:
zip -r yarabot-chat.zip yarabot-chat/ - In WordPress Admin go to Plugins → Add New → Upload Plugin.
- Upload the zip and click Activate.
Option B — Manual FTP/SSH
- Upload the
yarabot-chat/folder to/wp-content/plugins/. - In WordPress Admin go to Plugins and activate Yarabot Chat.
Configuration
After activation go to Settings → Yarabot Chat and fill in:
| Field | Description |
|---|---|
| *API Key (sk-)** | Your sk-* token with agent scope |
| Agent ID | The published public agent to embed — from Manage Agent in your Yarabot dashboard |
| Show the widget | Turns the front-end widget on or off without losing your credentials |
| Widget position | Which corner the floating button docks to — bottom right (default), bottom left, top right, top left |
Click Save Settings, then Test connection to confirm the credentials reach the agent. The widget appears on every front-end page once the key and agent ID are set.
The API key is stored in
wp_options, is never rendered back into the settings page HTML, and is never sent to the browser.
The API endpoint is not a setting — it is fixed at https://backend.yarabot.ir/api/v1. A self-hosted or staging backend can override it from wp-config.php:
define( 'YARABOT_CHAT_API_BASE', 'https://staging.example.com/api/v1' );
How It Works
Browser JS ──POST──► WordPress REST API (yarabot/v1/chat)
X-Visitor-Id: <per-browser uuid>
│
PHP reads sk-* key + Agent ID
from wp_options (server-side only)
│
▼
Yarabot API (over HTTP/2)
POST /api/v1/public/agents/{id}/query
Authorization: sk-<key>
X-Visitor-Id: <forwarded>
{ "stream": true }
│
NDJSON events relayed byte-for-byte
back through WP (PHP cURL)
│
▼
Browser JS renders
streaming response
The WordPress REST endpoint is POST /wp-json/yarabot/v1/chat. It accepts:
{
"message": "What is the return policy?",
"session_id": ""
}
Sources
Retrieved passages arrive as a sources event and are listed under the reply in
the order the answer cites them ([1], [2], …). They are never deduplicated or
filtered: a file-backed chunk has an empty source_url, and dropping those
would break the numbering the answer refers to. Such a source is labelled with
the passage text instead of a link.
The stream format
The reply is newline-delimited JSON — not Server-Sent Events, despite the
upstream Content-Type: text/event-stream. One event object per line:
{"type":"chunk", "data":"The return policy"}
{"type":"sources","data":[{"source_url":"https://…", "content":"…"}]}
{"type":"done", "data":{"session_id":"…","msg_id":"…"}}
session_id and msg_id arrive only in the final done event. The plugin
stores session_id in localStorage and passes it back on the next message to
continue the conversation.
Why HTTP/2 matters
The CDN in front of the Yarabot backend only streams the agent's reply token by
token over HTTP/2. Asked over HTTP/1.1 it buffers the whole answer and delivers
it in a single burst at the end. The plugin therefore requests
CURL_HTTP_VERSION_2TLS and sends Accept-Encoding: identity, since a
compressed reply would also be buffered before it could be flushed onward.
Session isolation
One sk-* token serves every visitor of the site, so the backend scopes session
ownership to the X-Visitor-Id header. The widget mints a UUID per browser and
the proxy forwards it; without it, one visitor could continue or react to
another's conversation by guessing its id.
Chat Widget
The widget loads on every front-end page as a floating button, docked to the corner chosen in the settings (bottom right by default). Clicking it opens the chat panel; the button turns into a close control while the panel is open.
Features:
- Streaming responses, token by token, with a stop button
- Regenerate the last reply (
PUT …/sessions/{sid}/{mid}?stream=true) - Markdown rendering (bold, lists, links, inline and fenced code)
- Conversation persisted across page navigation for 24 hours
- Per-browser visitor id, so sessions never cross between visitors
- Welcome message, agent name, avatar and theme colour pulled from the agent
- Suggested questions as clickable chips
- Like / dislike on each reply
- Collapsible source list, in the order the answer cites them as [1], [2], …
- "New conversation" button
- Voice input when the agent's model accepts audio and the browser can transcribe
- RTL-first layout and Persian typography (Yekan Bakh)
- Responsive — adapts to mobile screens
File Structure
yarabot-chat/
├── yarabot-chat.php # Plugin entry point
├── includes/
│ ├── class-yarabot-settings.php # Admin settings (WP Settings API)
│ └── class-yarabot-rest.php # REST proxy + streaming relay
├── admin/
│ └── settings-page.php # Settings page template
├── assets/
│ ├── css/yarabot-chat.css # Widget styles
│ ├── js/yarabot-chat.js # Widget JavaScript
│ ├── js/yarabot-admin.js # "Test connection" button
│ ├── fonts/ # Yekan Bakh woff2/woff files
│ └── images/ # Logo files
├── vendor/
│ └── plugin-update-checker/ # Update notifications (MIT)
├── readme.txt # WordPress-format readme + changelog
└── .github/workflows/release.yml # Builds and publishes the release zip
Customization
Appearance
All visual variables are CSS custom properties on #yarabot-chat-widget in
assets/css/yarabot-chat.css:
--yr-green: #267a66; /* header, user bubbles, buttons */
--yr-red: #eb5759; /* error states */
--yr-orange: #f09e29; /* reserved for highlights */
--yr-panel-w: 380px; /* chat panel width */
--yr-panel-h: 560px; /* chat panel max height */
--yr-toggle-size: 60px; /* floating button diameter */
Override any of these in your theme's CSS without editing the plugin files. If
the agent has a theme_color set in the Yarabot dashboard, it overrides
--yr-green at runtime.
The docking corner is a setting, not a CSS override — pick it under
Settings → Yarabot Chat → Widget position. It is applied as a
data-position attribute on #yarabot-chat-widget, so a theme can still
fine-tune the offsets:
#yarabot-chat-widget[data-position="bottom-right"] {
bottom: 40px;
right: 40px;
}
Filters
| Filter | Default | Purpose |
|---|---|---|
yarabot_chat_rate_limit |
15 |
Messages allowed per visitor per window; 0 disables throttling |
yarabot_chat_rate_window |
60 |
Throttle window, in seconds |
yarabot_chat_timeout |
180 |
cURL timeout for a single reply, in seconds |
yarabot_chat_history_ttl_ms |
86400000 |
How long a visitor's conversation is remembered |
yarabot_chat_api_base |
Yarabot production | The API base URL, for self-hosted backends |
Updates
The plugin is distributed from GitHub Releases, not wordpress.org. Sites see new
versions under Dashboard → Updates and can update in place, using
Plugin Update Checker
(MIT, bundled in vendor/).
Cutting a release
WordPress compares the Version: header in yarabot-chat.php — not the git
tag — so all three have to agree:
- Bump
Version:inyarabot-chat.php. - Bump
Stable tag:inreadme.txtand add a== Changelog ==entry. That changelog is what sites read in the "View version x.y.z details" popup. - Tag and push:
git tag v1.2.0 && git push --tags
The Release workflow refuses to build if the tag, the plugin header and the
stable tag disagree — a mismatch would silently mean no site is ever offered the
update. It then builds yarabot-chat-<version>.zip from .distignore and
attaches it to the release.
Sites check for updates roughly every 12 hours, so a new release is not instantaneous. GitHub's unauthenticated API limit (60 requests/hour per IP) is not a concern at that cadence.
Troubleshooting
Widget does not appear
- Confirm the plugin is activated, Show the widget is checked, and all three settings fields are saved. The widget is not rendered at all while the plugin is unconfigured.
- Check your browser console for JavaScript errors.
"Test connection" reports 404 — Agent not found
- The agent must be
status=publishedandis_public=truein your Yarabot dashboard. - The token must belong to the agent's owner. A token cannot invoke someone else's agent, even a published one.
401 / 403 errors
- 401: API key is wrong or expired.
- 403: the token is deactivated, lacks
agentscope, or itsagent_idslist does not include this agent. Update access viaPATCH /token/{token_id}/access.
402 — Insufficient balance
- Top up your Yarabot wallet.
"cURL is required" error
- Your server's PHP installation does not have the
curlextension enabled. Contact your host or enableextension=curlinphp.ini.
Responses don't stream (text appears all at once)
- Most often the request fell back to HTTP/1.1, where the CDN buffers the whole answer. Check
curl_version()['features']for HTTP/2 support — a PHP cURL built without nghttp2 cannot negotiate it. - Otherwise the buffering is local: some hosts buffer output regardless of PHP settings. The plugin clears output buffers, disables zlib compression and sends
X-Accel-Buffering: no, but a reverse proxy in front of WordPress can still override this.
Chat resets on every page load
- The conversation lives in
localStorage. Private/incognito windows and browsers blocking site data will start fresh each time.
Too many messages error
- The per-visitor throttle kicked in. Adjust it with the
yarabot_chat_rate_limitfilter.
Security Notes
- The
sk-*key is stored inwp_options(the standard WP option store), never echoed back into the settings form, and never included in any REST response. Limit admin access to trusted users. - The REST endpoint at
yarabot/v1/chatis publicly accessible by design — it is a chat widget endpoint. It is protected by a per-visitor rate limit rather than a nonce: a nonce baked into a full-page-cached response goes stale within 12 hours and WordPress then rejects every request with a 403. - Raw Yarabot API error messages and HTTP bodies are never forwarded to the browser. Only sanitized, translated error strings are sent.
- Agent metadata relayed by
yarabot/v1/infois passed through an explicit allow-list, so a future API field cannot leak to the front end by accident.
License
GPL-2.0-or-later
Releases
3 releases. Each count is every asset in that release; expand a row for the breakdown.