Уиджети — Hanc.AI
5 форми1 таг скрипт14 езика

Гласов агент на вашия сайт.
Един таг, без бекенд.

Пет уеб компонента, които позволяват на посетителя да говори с вашия агент — на глас, в браузъра, без да инсталира нищо. Разговорът върви по WebRTC, отговорът идва за около секунда, а агентът може да отваря страници и да вижда какво е на екрана.

Тази сфера е уиджетът. Натиснете и говорете.

Пет форми

Изберете формата, от която страницата има нужда

Един и същ агент, пет начина да се стигне до него. Смесвайте свободно — два тага с едно agent-id е обичайна схема.

Сфера в потока

Сфера в потока

370 px по подразбиране, стои в потока на страницата. Задайте нужната ширина; на тесен екран се смалява сама.

<hanc-ai-inline-call>

Секция на лендинг, страница за контакт — там, където разговорът е смисълът на блока.

Плаваща сфера

Плаваща сфера

120 px, закована на 32 px от долния десен ъгъл. Още три ъгъла по избор или static, за да я сложите в потока.

<hanc-ai-floating-call>

Достъпна от всяка страница и не заема място в оформлението.

Хапче

Хапче

Хоризонтален бутон: отляво сфера 48 px, отдясно вашият надпис. Стои в потока като всеки друг бутон.

<hanc-ai-pill-call>

В ред от бутони, в хедъра, вътре в карта.

Плаващо хапче

Плаващо хапче

Същият бутон, закован на 32 px от долния десен ъгъл. Същите четири ъгъла по избор.

<hanc-ai-pill-floating-call>

Когато кръглата сфера привлича твърде много внимание, но я искате винаги подръка.

Форма за обратно обаждане

Форма за обратно обаждане

Избор на държава, номер, който се форматира докато го пишете, и един бутон. Колко пъти да се звъни повторно се настройва на агента, не в маркъпа.

<hanc-ai-callback>

За тези, които не биха говорили през браузъра — и там, където микрофонът е неудобен.

Пет минути

Инсталиране

Един задължителен атрибут: идентификаторът на агента от вашето табло. API ключове нямат място в маркъпа — всичко в HTML се вижда от посетителя.

  1. 1

    Вземете идентификатора на агента

    Низ като 69d20781de6244c89509eb08, от таблото.

  2. 2

    Добавете скрипта

    Един ред в <head>. През npm е един импорт — таговете се регистрират сами.

  3. 3

    Поставете тага

    Там, където разговорът има място. Задължителен е само agent-id.

  4. 4

    Обслужвайте по HTTPS

    На http:// браузърът не дава микрофон. Докато разработвате, localhost върши работа.

index.html
<!-- 1. the script, once, in <head> -->
<script src="https://unpkg.com/hanc-webrtc-widgets" async></script>

<!-- 2. the widget, wherever the call belongs -->
<hanc-ai-inline-call
  agent-id="69d20781de6244c89509eb08"
  size="320"
  theme="tangerine"
  button-start-text="Talk to us">
</hanc-ai-inline-call>
1 script tag 0 dependencies WebRTC

React

Под версия 19 непознатите props се подават като низове, така че обекти не могат да минат оттам. Обвийте с @lit/react — официалният път, който дава и типизация, и събития.

Next.js

Уиджетът има нужда от браузър: 'use client' и динамичен импорт с ssr: false. Иначе билдът се чупи при сървърния рендеринг.

Vue

Работи без обвивка. Кажете на бъндлера, че таговете hanc-ai- са персонализирани елементи.

Той води страницата

Агентът може да отваря страници и да вижда какво е на екрана

Гласовият отговор често е грешната среда — никой не иска да му четат таблица с доставки. Затова агентът може да изпрати команда на страницата и да я попита какво гледа посетителят. Контролът остава у вашия код: той решава какво да изпълни.

Hanc.AI
navigate
page_context
cart_state
Уиджетът
navigate

Агентът отваря страница във вашия сайт — продукт, раздел, предварително попълнена форма.

page_context

Страницата отговаря къде е посетителят и какво се показва, за да говори агентът за този продукт, а не изобщо.

cart_state

Страницата отговаря какво има в количката и колко струва, за да каже агентът сумата на глас.

Всяка команда пристига като отменяемо DOM събитие agent-command. Извикването на preventDefault() значи «обработено»; respond(data) връща отговор на агента. Ако игнорирате събитието, на агента се казва, че не е обработено, и той се връща към говоренето.

Командите са молби, не заповеди — проверявайте всеки път, преди да го последвате. Примерът отхвърля всичко, което не е път вътре в сайта.

widget.js
widget.addEventListener('agent-command', (event) => {
  const command = event.detail;

  if (command.type === 'navigate') {
    const path = command.payload?.path;
    // Only same-site paths. Never follow an absolute URL.
    if (!path?.startsWith('/') || path.includes('://')) return;
    event.preventDefault();          // "handled" — the ACK protocol
    router.push(path);
  }

  if (command.type === 'cart_state') {
    event.preventDefault();
    command.respond({                // answer travels back to the agent
      items: cart.map(i => ({ name: i.name, price: i.price })),
      total: cart.total,
      currency: 'UAH',
    });
  }
});

Работи на

milotec.com.ua

Агентът води посетителя до продукт, казва какво има на текущата страница и прочита количката.

Мобилни приложения

Същият уиджет във вашето приложение

И iOS, и Android го показват в уеб изглед. Съберете малка HTML страница в кода и я заредете с HTTPS база — без защитен източник двигателят няма да даде микрофон на страницата.

Агентът не се чува

Уеб изгледът няма да пусне WebRTC звука, докато аудио сесията на приложението стои в режим възпроизвеждане. Превключете я към разговорен режим с изход към високоговорителя за времето на разговора и я върнете след това.

Агентът отговаря на грешен език

Уиджетът взима езика от navigator.language, а в уеб изглед това е системният език, не избраният в приложението. Подменете го при старта на документа — и закърпете fetch, като добавите browser_language към заявката за стая, което вграденият уиджет сам не изпраща.

Микрофонът иска и двете половини

Системното разрешение за приложението и разрешението за страницата в уеб изгледа. На Android поискайте системното преди отварянето на екрана; на iOS удовлетворете заявката на страницата в делегата.

Същият уиджет във вашето приложение
Работи в приложението RunOrJog
SupportView.swift
let html = """
<hanc-ai-inline-call
    agent-id="\(agentId)"
    support-session-token="\(sessionToken)"></hanc-ai-inline-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async></script>
"""

// An HTTPS base is required — without a secure origin
// the engine will not hand the page a microphone.
webView.loadHTMLString(html, baseURL: URL(string: "https://hanc.ai"))
Кой е на разговора

Дайте на агента да види влезлия потребител — и само него

Подайте токен в support-session-token. Уиджетът го прикача към разговора както е, ние го предаваме на вашата система в хедъра X-Hanc-Support-Token, а вашият MCP сървър решава кой е това. За нас токенът е непрозрачен: не го разглобяваме, не го проверяваме и не го съхраняваме.

Вашето приложение
Уиджетът
Hanc.AI
Вашият MCP
Вашите данни

Никога не се доверявайте на идентификатор, който пристига вътре в токен като твърдение. Питайте издателя на токена кой е това и работете с отговора.

ПодходМоже ли да се подправиОценка
Открит идентификаторТривиалноНедопустимо
Шифрован идентификаторНе, но може да се предяви повторноПоловин решение
Токен на вашия доставчик за входНе: подписът е на доставчикаРаботи
Еднократен сървърен талонНе, и повторно също неНай-доброто

Включете на връзката «изисква разпознат събеседник» и при анонимен разговор вашите инструменти изобщо няма да се вдигнат — агентът няма да каже нищо за чужд акаунт, дори ако по-късно в кода ви се появи грешка.

Разговор без токен не получава никакъв достъп до акаунт. Това е поведението по подразбиране, не опция.

your_mcp_server.py
async def verified_user_id(ctx) -> str:
    token = ctx.request.headers.get("x-hanc-support-token", "").strip()
    if not token:
        raise ValueError("No signed-in user on this call.")

    # Ask the issuer who this is. Never read the id out of the token.
    resp = await http.get(f"{AUTH_URL}/auth/v1/user",
                          headers={"Authorization": f"Bearer {token}"})
    if resp.status_code != 200:
        raise ValueError("Token invalid or expired.")

    return resp.json()["id"]        # ← the trusted identity
Външен вид

Трябва да изглежда като вашия сайт, а не като нашия

Единадесет теми, светла и тъмна по системна настройка или принудително, и още около петнадесет атрибута за самата сфера.

default
emerald
rose
amber
cyan
purple
blue
white
black
tangerine
ember
АтрибутКакво задаваПо подразбиране
agent-id Кой агент отговаря. Единственият задължителен
theme Една от единадесетте цветови теми default
size Размер в пиксели; на тесни екрани се смалява сам 370
button-start-text Надписът на бутона Try to call
position Ъгъл за плаващите форми bottom-right
glow-intensity Сила на сиянието, 0–2 0.8
audio-reactivity Колко силно сферата откликва на гласа 3.0
terms-enabled Панел за съгласие преди разговора false
sound-enabled Звуци в началото и края true
support-session-token Токенът на влезлия потребител

Събития за вашия код

Нито едно от събитията не носи данни: и двете са обикновен Event, тоест получавате самия факт и момента. Съдържание на разговора няма нито в едното, нито в другото — транскрипциите и записите живеят в таблото и в API.

Направо

Какво защитава и какво не е защита

Каналът е криптиран

Управляващите заявки по HTTPS, звукът по WSS и SRTP. Без HTTPS браузърът и без това не дава микрофон.

Агентът се проверява

Разговор се вдига само за съществуващ идентификатор на агент.

Достъпът е ограничен по честота

Издаването на достъп до разговор е ограничено — срещу brute force и злоупотреба.

Токенът на сесията не се задържа

Чете се наново при всеки разговор и никога не се записва в нашата база.

Списъкът с разрешени домейни не е граница на сигурността

Тази проверка работи в браузъра. Полезна е, за да не тръгне уиджетът по невнимание върху чуждо копие на вашата страница, но не пречи на никого да се обърне директно към услугата. Смятайте за публично всичко, което агентът би казал на анонимен събеседник, а останалото пазете с токен на сесията.

Какво и къде остава

В браузъра

Два записа в localStorage: маркер на посетителя и фактът на съгласието

Звук

На поток. Записва се само ако записът е включен за агента

Транскрипция

Пази се заедно със записа, чете се в таблото

Разположение

Обработка и съхранение в ЕС

Ограничения, които е добре да знаете предварително

Без HTTPS няма микрофон

Тествайте на localhost или защитен домейн

Safari иска жест преди звука

Разговорът трябва да започва с кликване

Блокери и проксита могат да режат WebRTC

Оставете формата за обратно обаждане като резервен път

В частен прозорец маркерът не се пази

Всеки разговор изглежда като първи — това е нормално

React под 19 не подава обекти като атрибут

Обвийте с @lit/react

Сървърният рендеринг се чупи при директен импорт

Динамичен импорт с ssr: false

Вашият телефон, който най-накрая
работи за вас.

Започнете безплатно за 60 секунди. Без кредитна карта. Отменете по всяко време. Просто телефонът, който сам вдига.

Започнете безплатно
Book a Meeting