Skip to content

SDK

Each handler receives a PluginSDK instance (sdk parameter) with these methods:

Log a message with plugin context. Messages appear in plugin logs.

def on_message_received(event, sdk):
sdk.log("Processing incoming message")
sdk.log("Error occurred", level="error")
sdk.log("Debug info", level="warn")
ParameterTypeDefaultDescription
messagestring:Log message text
levelstring"info"Log level: "info", "warn", or "error"

sdk.send_message(agent_id, external_user_id, channel_id, text)

Section titled “sdk.send_message(agent_id, external_user_id, channel_id, text)”

Send a message to a user via an agent session on a specific channel.

def on_turn_complete(event, sdk):
session = sdk.get_session(event['session_id'])
agent_id = session.get('agent_id')
user_id = session.get('user_id')
channel_id = session.get('channel_id')
sdk.send_message(
agent_id=agent_id,
external_user_id=user_id,
channel_id=channel_id,
text="Your turn is complete!"
)
ParameterTypeDescription
agent_idstringTarget agent ID
external_user_idstringUser identifier on the channel (e.g. Telegram user ID)
channel_idstringChannel ID (UUID) or channel type hint like 'telegram'
textstringMessage text to send

Returns: {"success": bool, "session_id": str} on success, or {"success": False, "error": str} on failure.

sdk.http_request(method, url, headers=None, json=None, data=None, timeout=30)

Section titled “sdk.http_request(method, url, headers=None, json=None, data=None, timeout=30)”

Make an HTTP request to an external API.

def on_message_received(event, sdk):
response = sdk.http_request(
method="POST",
url="https://api.example.com/webhook",
json={"session_id": event.get("session_id"), "message": event.get("message")},
timeout=10
)
if response.get("ok"):
sdk.log(f"Webhook sent: {response['status_code']}")
else:
sdk.log(f"Webhook failed: {response.get('error')}", level="error")
ParameterTypeDefaultDescription
methodstring:HTTP method: "GET", "POST", "PUT", "DELETE", etc.
urlstring:Target URL
headersdictNoneOptional HTTP headers
jsondictNoneJSON body (automatically serialized)
datastringNoneRaw body data
timeoutint30Request timeout in seconds

Returns: {"status_code": int, "body": str, "headers": dict, "ok": bool} on success, or {"error": str, "ok": False} on failure.

sdk.get_session_messages(session_id, agent_id=None, limit=50)

Section titled “sdk.get_session_messages(session_id, agent_id=None, limit=50)”

Read messages from a session.

def on_turn_complete(event, sdk):
messages = sdk.get_session_messages(
session_id=event['session_id'],
limit=10
)
sdk.log(f"Last 10 messages: {len(messages)}")
ParameterTypeDefaultDescription
session_idstring:Session ID
agent_idstringNoneOptional agent ID filter
limitint50Max number of messages to return

Returns: List of message dicts.

Get enriched session details (includes agent_name, channel_type, etc.).

def on_message_received(event, sdk):
session = sdk.get_session(event['session_id'])
agent_name = session.get('agent_name', 'Unknown')
sdk.log(f"Session agent: {agent_name}")
ParameterTypeDescription
session_idstringSession ID

Returns: Dict with session details.

Introduced in v1.3.0.

A plugin can add its own tabs to the plugin detail page. Drop any file named <slug>_tab.html into the plugin’s templates/ directory and it automatically appears as an extra tab:

  • manage_tab.html → a tab with id manage and label Manage
  • settings_tab.html → a tab with id settings and label Settings

The HTML partial is injected into the detail page’s tab area. To run setup code when the tab first opens, define a lazy initializer in the partial:

plugins/myplugin/templates/manage_tab.html
<div id="myplugin-manage"><!-- manage UI --></div>
<script>
// Runs once, the first time the "manage" tab is opened.
function tabInit_manage() {
// wire up your manage UI here
}
</script>

The convention is window.tabInit_<slug>() — the platform calls it when the tab becomes visible.

Introduced in v1.3.0.

Plugin REST endpoints now support discovery (the platform can enumerate the endpoints a plugin exposes) and pagination for large result sets. When an endpoint returns a list, accept limit / offset (or equivalent) parameters so clients can page through results instead of loading everything at once.

Multiple-Choice Prompts (ask_user_question)

Section titled “Multiple-Choice Prompts (ask_user_question)”

Introduced in v1.3.0 as a plugin; built into Evonic since v1.6.0.

The ask_user_question tool lets an agent pause mid-turn and ask the user one or more multiple-choice questions. Each question renders as an interactive card in the web chat (or as inline buttons on Telegram), and the answer is returned to the agent as the tool result.

  • Each question needs 2–4 options (minimum 2, maximum 4), and every option must have a label.
  • An option can be marked recommended to suggest an answer.
  • The agent waits for the answer before continuing its turn.

It is no longer a plugin: every agent has an Ask User Questions toggle under Tools & capabilities (on by default) and needs no tool assignment. A leftover plugins/ask_user/ folder is ignored after upgrading.

Plugin and tool definitions can declare "channels": ["web", "telegram"] to be listed only on those channel types — useful when a tool depends on the rich question UI.

See ask_user_question for parameters and per-channel behaviour.