Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.autoplay.ai/llms.txt

Use this file to discover all available pages before exploring further.

This guide has three parts:
  1. Setup Tidio AI Agent — Add your knowledge base, configure agent instructions, and create an action that fetches live context from your server.
  2. Setup API Server and Listener — Run a FastAPI server and Autoplay SDK listener that capture and serve real-time events.
  3. Add Chatbot to Frontend — Embed the Tidio widget in your app.

🤖 Part 1 — Setup Tidio AI Agent

Data Sources

Go to Lyro data sources and click Add knowledge.
Tidio Lyro data sources page with Add knowledge button
Select the Website URL option.
Add knowledge modal with Website URL option selected
Add your website URL.
Website URL input field in Tidio Lyro data sources

Agent Guidance & Instructions

In the left sidebar, go to BehaviorGuidance and edit the Communication Style. Select Custom.
Tidio Guidance panel with Communication Style set to Custom
Paste the following into the Instructions box:
Tidio’s Instructions field has a 9,000-character limit. The prompt below fits within this limit, but if you customise it, make sure you stay under the ceiling.
You are a friendly and helpful assistant for users of this product.

Focus on helping people find their way in the UI, complete workflows, and
understand features. Assume some users are seeing the product for the first time.

## 💬 How to use the "Current User Activity" record

You will get the user's recent activity from "Get Events Data" action. This shows
what THIS user has been doing on the platform in the last 2 minutes — which page
they are on and what they clicked. The activity is scoped to their session, so it
reflects only their actions, not anyone else's.

When this record is present:

1. **Acknowledge their activity naturally** — for example:
   "I can see you're currently on the Projects page" or
   "It looks like you've been exploring the Dashboard."

2. **Use it to give specific directions** — instead of generic
   instructions, reference where they are:
   "From the page you're on, click the blue 'Add Project' button
   at the top right."

3. **Detect if they might be lost** — if their actions show them
   clicking around without a clear pattern, gently offer help:
   "It looks like you might be looking for something specific.
   Can I help you find it?"

4. **Don't force it** — if the user's question has nothing to do
   with their current activity, just answer the question normally.
   Don't mention their activity unless it's helpful.

## ❓ How to answer questions

- **Be specific**: reference actual button names, tab labels, and
  menu items from the knowledge base.
- **Use numbered steps**: when explaining how to do something,
  always use a numbered list.
- **Keep it simple**: avoid technical jargon. Explain as if the
  user has never used the platform before.
- **Be encouraging**: use phrases like "Great question!" or
  "That's easy to do" to make users feel comfortable.
- **Offer next steps**: after answering, suggest what they might
  want to do next.
- **Admit when you don't know**: if the knowledge base doesn't
  have the answer, say so honestly.

## 🌐 Language

Respond in the same language the user writes in.

## ✅ Examples of good responses

User is on the Dashboard, asks "How do I create a project?":
  "I can see you're currently on the Dashboard. To create a new
   project:
   1. Click on 'My Projects' in the left sidebar
   2. Click the 'Add Project' button at the top right
   3. Choose the type, template, or options that match what you're creating
   4. Fill in the required details and click 'Create'
   Would you like me to explain what each field means?"

User is on the Invoice page, asks "Where are settings?":
  "The settings aren't on this page — you can find them by clicking
   on your profile icon in the top right corner, then selecting
   'Settings' from the dropdown menu."

User has no activity context, asks "What can I do here?":
  "Welcome! Here's what you can do:
   1. Dashboard — see an overview of your work
   2. My Projects — create and manage projects
   3. Reports — view analytics or exports
   4. Billing — manage invoices or account settings
   What would you like to explore first?"
Press Save and close.
Tidio agent instructions filled in with the custom prompt

Setup Actions for Autoplay SDK API Service

Lyro Actions are available on all Tidio plans, but direct setup support from Tidio is only included on the Plus plan and above. If you hit issues, the Tidio docs at help.tidio.com are the best self-serve resource.
A small number of Tidio accounts still use a legacy version of this feature, where you’ll see two separate options — Simple Actions and Smart Actions — instead of a single “Actions” menu. If you see this, use Smart Actions. The steps are the same.
Go to ActionsCreate ActionCreate from Scratch.
Tidio Actions panel with Create from Scratch option
Add a name (e.g. Get Events Data) and a brief description in the Instructions field.
Tidio action name and instructions fields filled in
Click Edit Sequence.
Edit Sequence view in Tidio action builder
Add an API call node.
API call node added to the Tidio action sequence
Click API callConfigure HTTP request.
Configure HTTP request panel in Tidio API call node
Fill in the request configuration:
  • Request name — any descriptive name
  • Authentication — select API key
  • Secret key — set any secret string, or generate one:
openssl rand -hex 32
  • Add a new header with key x-secret-key and value referencing the API key variable you just set.
x-secret-key header configured in the Tidio HTTP request
  • MethodPOST
  • URL — your Autoplay SDK event server’s public URL (e.g. the Ngrok HTTPS URL from Part 2)
Click Test request — this calls the server and returns a response. In the right panel, click context on the response.
Test request response panel with context field highlighted
Add a new session variable and save it as context.
Session variable named context saved in Tidio action
Finally click Add requestSave and close to save the action.
Tidio action saved and ready with the context variable
Make sure the action is enabled and that the context session variable is available to the agent in its instructions. The agent references it automatically through the “Get Events Data” action.

🐍 Part 2 — Setup API Server and Listener

Prerequisites

  • Python 3.10+
  • An OpenAI API key
  • uvicorn for serving the FastAPI app
  • (Optional) Cloudflare Tunnel or Ngrok for local development
Install dependencies:
pip install fastapi httpx openai uvicorn autoplay-sdk

Project Structure

|- .env          # store your env var secrets
|- listener.py   # the Autoplay SDK event listener
|- server.py     # FastAPI server that serves events to Tidio

Setup your secrets in a .env file

EVENTS_FILE_PATH="event_data.txt"

AUTOPLAY_STREAM_URL="YOUR_AUTOPLAY_STREAM_URL"
AUTOPLAY_UNKEY_API_KEY="YOUR_AUTOPLAY_UNKEY_API_KEY"

API_KEY="YOUR_API_KEY"
API_KEY is the same secret string you set in the Tidio action’s API key field. It can be any string, e.g. "DKFGEO293KDDA92", or the output of openssl rand -hex 32.

Setup the API Server (server.py)

import os
from fastapi import FastAPI, Header, Query, HTTPException
from dotenv import load_dotenv

load_dotenv()

app = FastAPI()

EVENTS_FILE = os.getenv("EVENTS_FILE_PATH", "events.txt")
API_KEY = os.getenv("API_KEY")
PORT = int(os.getenv("PORT", 5000))


def read_events() -> str:
    if not os.path.exists(EVENTS_FILE):
        return "No events recorded yet."
    with open(EVENTS_FILE, "r", encoding="utf-8") as f:
        content = f.read().strip()
    return content or "No events recorded yet."


def trim_events(content: str, max_lines: int = 100) -> str:
    lines = content.splitlines()
    return "\n".join(lines[-max_lines:])


@app.post("/context")
def generate_event_context(
    secret: str | None = Query(default=None),
    x_secret_key: str | None = Header(default=None),
):
    token = x_secret_key or secret
    if API_KEY and token != API_KEY:
        raise HTTPException(status_code=401, detail="Unauthorized")

    raw = read_events()
    context = trim_events(raw, max_lines=100)
    return {
        "context": context,
        "line_count": len(context.splitlines()),
    }


@app.get("/health")
def health():
    return {"status": "ok"}


if __name__ == "__main__":
    import uvicorn

    print(f"Starting context server on port {PORT}...")
    uvicorn.run("server:app", host="0.0.0.0", port=PORT)

Setup the Event Listener (listener.py)

import asyncio
import os
import time

import dotenv
import openai
from autoplay_sdk import (
    ActionsPayload,
    AsyncAgentContextWriter,
    AsyncConnectorClient,
    AsyncSessionSummarizer,
)

dotenv.load_dotenv()

STREAM_URL = os.getenv("AUTOPLAY_STREAM_URL")
UNKEY_API_KEY = os.getenv("AUTOPLAY_UNKEY_API_KEY")
EVENTS_FILE_PATH = os.getenv("EVENTS_FILE_PATH")

async_openai = openai.AsyncOpenAI()


def api_call(func):
    async def wrapper(*args, **kwargs):
        try:
            return await func(*args, **kwargs)
        except Exception as e:
            print(f"Error in API call: {e}")

    return wrapper


@api_call
async def llm(prompt: str) -> str:
    r = await async_openai.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0.3,
        max_tokens=256,
    )
    return r.choices[0].message.content


@api_call
async def write_actions_to_file(payload: ActionsPayload):
    print("\n=== WRITING ACTIONS TO FILE ===")
    # Reset file if last modified more than 2 minutes ago (new session)
    if os.path.exists(EVENTS_FILE_PATH):
        last_modified_time = os.path.getmtime(EVENTS_FILE_PATH)
        if time.time() - last_modified_time > 2 * 60:
            open(EVENTS_FILE_PATH, "w").close()
    with open(EVENTS_FILE_PATH, "a") as f:
        for i, action in enumerate(payload.actions):
            f.write(f"[{i}] Action: {action.title}\n")
            f.write(f"     Details: {action.description}\n")
            f.write(f"     Page:    {action.canonical_url}\n")


# Raw actions are written directly to file; tell the writer to do nothing for actions
async def dummy_write_actions(session_id: str, text: str) -> None:
    pass


@api_call
async def overwrite_summary(session_id: str, summary: str) -> None:
    print("\n=== OVERWRITING SUMMARY ===")
    with open(EVENTS_FILE_PATH, "a") as f:
        f.write(f"\n=== SUMMARY ===\n{summary}\n")


summarizer = AsyncSessionSummarizer(llm=llm, threshold=5)

agent_writer = AsyncAgentContextWriter(
    summarizer=summarizer,
    write_actions=dummy_write_actions,
    overwrite_with_summary=overwrite_summary,
    debounce_ms=0,
)


async def handle_actions_interceptor(payload: ActionsPayload):
    await write_actions_to_file(payload)
    await agent_writer.add(payload)


async def main():
    async with AsyncConnectorClient(url=STREAM_URL, token=UNKEY_API_KEY) as client:
        client.on_actions(handle_actions_interceptor)
        print("Listening for live website clicks... (Press Ctrl+C to stop)")
        await client.run()


if __name__ == "__main__":
    asyncio.run(main())

Run the server, listener, and expose to the internet

Start the API server:
uvicorn server:app --reload --port 5000
Expose it publicly with Ngrok:
ngrok http 5000
Copy the Ngrok HTTPS URL and paste it as the URL in the Tidio API call action from Part 1. Start the listener:
python listener.py

🌐 Part 3 — Add Chatbot to your Frontend App

Go to https://www.tidio.com/panel/settings/live-chat/installation and copy the Code Snippet.
Tidio installation settings page with the Code Snippet
Open your frontend application and paste the snippet just before the closing </body> tag of your index.html, as recommended by Tidio’s installation guide:
<!-- Tidio chat widget — paste from your Tidio installation settings -->
<script src="//code.tidio.co/YOUR_PUBLIC_KEY.js" async></script>
Tidio HTML snippet pasted inside index.html
The exact snippet is generated by Tidio — copy it directly from the installation settings page rather than using the example above.

✨ Final result

After everything is running, you should see live events flowing through the listener and server, and the Tidio Lyro agent responding with real-time context.

Listener

Terminal showing the Autoplay SDK listener receiving live events

API Server

Terminal showing the FastAPI server responding to Tidio requests

Chatbot

Tidio Lyro AI Agent in action with context-aware responses

Next: Step 2 — Define proactive triggers