TakonAI/Widget Documentation
v1

Quick Start

Tambahkan satu baris script tag ke halaman HTML Anda. Widget akan otomatis muncul sebagai floating button di kanan bawah halaman.

<script
  src="https://cdn.ztakonai.com"
  data-widget-id="wgt_abc123"
  data-api-key="tk_live_xxxx">
</script>
html

Script Tag Attributes

AttributeRequiredDescription
data-widget-id*stringWidget ID dari TakonAI dashboard (format: wgt_...)
data-api-key*stringPublic API key dari TakonAI dashboard (format: tk_live_...)
data-base-urlstringOverride URL widget — hanya untuk development/staging. Default: https://cdn.ztakonai.com

Embed Guide

Widget bekerja dengan menginjeksi sebuah <iframe> ke halaman Anda. Komunikasi antara halaman host dan widget dilakukan via postMessage.

Cara Kerja

  1. Script tag loader dieksekusi saat halaman load.
  2. Loader membuat floating bubble button (fixed, bottom-right, z-index 9990).
  3. Saat user klik bubble, iframe /embed diinjeksi dan chat panel dibuka.
  4. Iframe berkomunikasi dengan halaman host via postMessage.
  5. window.Takonai tersedia untuk kontrol programmatic setelah script dimuat.

Inisialisasi dengan User Context

Panggil window.Takonai.init() setelah halaman selesai dimuat untuk menghubungkan widget dengan sesi user Anda.

window.Takonai.onReady = () => {
  window.Takonai.init({
    externalId: 'user_123',       // ID unik user dari sistem Anda
    currentStep: 1,               // Step aktif saat ini (opsional)
    context: {                    // Data konteks tambahan (opsional)
      planType: 'pro',
      cartTotal: 150000,
    },
  });
};
js

Mengelola Banyak Step (Multi-Step)

Untuk halaman yang memiliki urutan step — seperti form checkout atau pendaftaran wizard — Anda dapat memisahkan konfigurasi form menjadi beberapa step di dashboard TakonAI.

Di sisi frontend, Anda perlu memberitahu widget setiap kali user berpindah step menggunakan setStep(). Dengan cara ini, AI hanya memproses Tool/Form Filling yang sesuai dengan form di step yang sedang aktif.

Cara kerja multi-step

  1. Buat konfigurasi widget di dashboard dengan beberapa step, masing-masing memiliki form yang berbeda.
  2. Saat halaman pertama dimuat, panggil init({ currentStep: 1 }).
  3. Setiap kali user pindah ke step berikutnya, panggil setStep(n) agar AI tahu step mana yang aktif.
  4. AI hanya akan mengisi form di step yang sedang aktif — tidak ada kebocoran data antar step.
// Step 1 — saat widget siap
window.Takonai.onReady = () => {
  window.Takonai.init({
    externalId: 'usr_123',
    currentStep: 1,
  });
};

// Step 2 — saat user klik tombol "Lanjut"
function goToStep2() {
  showStep(2); // tampilkan form step 2 di halaman Anda

  window.Takonai.setStep(2, {
    // opsional: kirim data dari step sebelumnya sebagai konteks
    buyerName: document.querySelector('[name="full_name"]').value,
  });
}

// Step 3 — opsional, lanjut ke step berikutnya
function goToStep3() {
  showStep(3);
  window.Takonai.setStep(3);
}
js

Gunakan callback onFill untuk mengisi form yang tepat berdasarkan step yang dikirim AI:

window.Takonai.onFill = ({ step, formName, data }) => {
  // Pilih form yang sesuai dengan step aktif
  const formMap = {
    1: document.getElementById('form-buyer'),
    2: document.getElementById('form-shipping'),
    3: document.getElementById('form-payment'),
  };
  const formEl = formMap[step];
  if (!formEl) return;

  Object.entries(data).forEach(([field, value]) => {
    const el = formEl.querySelector('[name="' + field + '"]');
    if (el) el.value = value;
  });
};
js

window.Takonai

Global object yang di-expose oleh widget loader script. Tersedia setelah script tag dimuat.

init(opts)

Method

Inisialisasi widget dengan konteks user. Harus dipanggil di dalam callback onReady agar iframe siap menerima pesan. Widget akan mengirim TAKONAI_INIT ke iframe dan menerima konfirmasi TAKONAI_INIT_ACK.

window.Takonai.init(opts: TakonaiInitOptions): void

interface TakonaiInitOptions {
  externalId: string;                  // Required — ID user dari sistem Anda
  currentStep?: number;                // Optional — step aktif (default: 1)
  context?: Record<string, unknown>;   // Optional — data konteks dinamis
  welcomeMessage?: string;             // Optional — override pesan sapaan dari dashboard
}
ts

Parameters

NameTypeDescription
externalId*stringID unik user dari sistem Anda. Digunakan untuk identifikasi sesi.
currentStepnumberStep aktif saat init. Default: 1.
contextobjectData konteks bebas yang diteruskan ke AI (kategori produk, nilai form, dll).
welcomeMessagestringOverride pesan sapaan yang dikonfigurasi di dashboard. Berguna untuk personalisasi per-user atau per-halaman.

Example

window.Takonai.onReady = () => {
  window.Takonai.init({
    externalId: 'usr_4891',
    currentStep: 2,
    context: {
      category: 'electronics',
      priceRange: '500k-1jt',
    },
    welcomeMessage: 'Halo, Budi! Ada yang bisa kami bantu hari ini?',
  });
};
js

setStep(step, context?)

Method

Update step aktif widget, misalnya saat user berpindah halaman atau mengisi form multi-step. Mengirim pesan TAKONAI_STEP_CHANGED ke iframe.

window.Takonai.setStep(step: number, context?: Record<string, unknown>): void
ts

Parameters

NameTypeDescription
step*numberNomor step baru (1-indexed, sesuai konfigurasi widget di dashboard).
contextobjectKonteks baru yang akan menggantikan konteks sebelumnya.
// User pindah ke step checkout pengiriman
window.Takonai.setStep(2, {
  selectedItems: ['item_001', 'item_002'],
  total: 320000,
});
js

setContext(context)

Method

Update konteks tanpa mengubah step aktif. Berguna saat data halaman berubah tapi posisi step tidak berubah. Mengirim TAKONAI_CONTEXT_UPDATE.

window.Takonai.setContext(context: Record<string, unknown>): void
ts
// User memilih produk lain tanpa pindah step
window.Takonai.setContext({
  selectedProduct: 'SKU-9921',
  color: 'black',
  size: 'XL',
});
js

Contoh: Validasi Data Form

Gunakan setContext untuk mengirim data yang sudah diisi user ke widget. AI akan mengetahui isi form saat ini, sehingga bisa menjawab pertanyaan seperti "apakah data saya sudah benar?" tanpa user perlu mengetik ulang.

// Kirim data form setiap kali ada perubahan (gunakan 'change' bukan 'input'
// agar tidak terlalu sering mengirim pesan ke widget)
document.getElementById('checkout-form').addEventListener('change', () => {
  window.Takonai.setContext({
    form_full_name: document.querySelector('[name="full_name"]').value,
    form_email:     document.querySelector('[name="email"]').value,
    form_phone:     document.querySelector('[name="phone"]').value,
    form_address:   document.querySelector('[name="address"]').value,
  });
});

// User bisa bertanya:
// "apakah email saya sudah benar?" → AI tahu nilainya dari context
// "cek nomor HP saya" → AI baca form_phone dari context
js

Tips

  • Gunakan event change atau blur (bukan input) agar tidak mengirim terlalu banyak update ke widget.
  • Prefix key dengan form_ untuk memudahkan AI membedakan data form dari konteks lain.
  • Jangan kirim data sensitif seperti password atau nomor kartu kredit.

open() / close()

Method

Buka atau tutup chat panel secara programmatic, tanpa user harus klik bubble button.

window.Takonai.open(): void
window.Takonai.close(): void
ts
// Buka widget otomatis setelah 5 detik
setTimeout(() => {
  window.Takonai.open();
}, 5000);

// Tutup widget setelah form selesai diisi
window.Takonai.onFill = (payload) => {
  fillMyForm(payload.data);
  window.Takonai.close();
};
js

onFill(payload)

Callback

Dipanggil ketika AI berhasil menjalankan sebuah tool (tool use selesai). formName adalah nama tool yang dipanggil, dan data adalah JSON payload sesuai schema yang Anda definisikan di dashboard. Anda bebas menggunakan payload ini untuk apapun — mengisi form HTML, memperbarui state aplikasi, memanggil API backend, atau memicu aksi UI lainnya.

window.Takonai.onFill = (payload: TakonaiFillPayload) => void

interface TakonaiFillPayload {
  step: number;                        // Step yang aktif saat tool dipanggil
  formName: string;                    // Nama tool (dari konfigurasi widget)
  data: Record<string, unknown>;       // JSON payload hasil tool call AI
}
ts

Parameters

FieldTypeDescription
stepnumberNomor step yang baru saja di-fill oleh AI.
formNamestringNama form sesuai konfigurasi widget di dashboard.
dataobjectKey-value hasil isian AI. Key sesuai field name di konfigurasi form.

Example

window.Takonai.onFill = ({ step, formName, data }) => {
  // Contoh 1: isi form HTML seperti biasa
  if (formName === 'form_checkout') {
    Object.entries(data).forEach(([field, value]) => {
      const el = document.querySelector(`[name="${field}"]`);
      if (el) el.value = value;
    });
  }

  // Contoh 2: langsung panggil API backend
  if (formName === 'create_booking') {
    fetch('/api/booking', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data),
    });
  }

  // Contoh 3: update state aplikasi (React, Vue, dsb)
  if (formName === 'add_to_cart') {
    store.dispatch('cart/add', { sku: data.sku, qty: data.qty });
  }

  // Contoh 4: navigasi
  if (formName === 'navigate') {
    router.push(data.path);
  }
};
js

onReady()

Callback

Dipanggil ketika widget iframe telah selesai dimuat dan siap menerima komunikasi. Anda wajib memanggil init() di dalam callback ini.

window.Takonai.onReady = () => void
ts

Example

window.Takonai.onReady = () => {
  console.log('Widget siap digunakan!');
  window.Takonai.init({ externalId: 'usr_123' });
};
js

onError(payload)

Callback

Dipanggil ketika terjadi error di dalam widget (streaming gagal, config tidak ditemukan, dll).

window.Takonai.onError = (payload: TakonaiErrorPayload) => void

interface TakonaiErrorPayload {
  code: string;     // Error code, contoh: 'STREAM_ERROR', 'CONFIG_NOT_FOUND'
  message: string;  // Pesan error human-readable
}
ts
window.Takonai.onError = ({ code, message }) => {
  console.error('[TakonAI]', code, message);
  // Log ke Sentry, tampilkan fallback UI, dll
};
js

sendImage(url)

Method

Lampirkan gambar dari URL publik ke composer chat widget secara programatik. Gambar belum dikirim sampai user mengetik pesan dan menekan tombol Send — sehingga Anda bisa pra-lampirkan gambar produk sebelum user mulai chat.

URL harus menggunakan skema https:// dan dapat diakses publik, karena Anthropic akan men-fetch URL tersebut langsung saat memproses pesan.

window.Takonai.sendImage(url: string): void
ts

Parameters

NameTypeDescription
url*stringURL gambar publik (https:// wajib). Tidak mendukung base64 atau URL yang memerlukan autentikasi.

Example

// Pra-lampirkan foto produk saat user membuka detail produk
window.Takonai.sendImage('https://cdn.toko.com/products/kaos-putih.jpg');

// User bisa langsung tanya "berapa harga ini?" dan AI sudah bisa melihat gambarnya
js

Catatan

  • Maksimal 3 gambar per pesan. Memanggil sendImage saat sudah mencapai batas akan diabaikan.
  • Gambar yang sudah dilampirkan via sendImage akan dibersihkan otomatis setelah pesan terkirim.
  • Callback onImageUpload akan dipanggil setiap kali gambar berhasil dilampirkan, termasuk dari sendImage.

onImageUpload(payload)

Callback

Dipanggil setiap kali gambar berhasil dilampirkan ke composer chat — baik via tombol paperclip di widget, paste dari clipboard, drag-and-drop, maupun panggilan sendImage().

window.Takonai.onImageUpload = (payload: TakonaiImagePayload) => void

interface TakonaiImagePayload {
  url: string;        // URL publik gambar di Supabase Storage (atau URL asli untuk sendImage)
  mimeType: string;   // MIME type gambar, contoh: "image/jpeg"
  sizeBytes: number;  // Ukuran file dalam bytes (0 untuk sendImage)
  fileName: string;   // Nama file asli
}
ts

Parameters

FieldTypeDescription
urlstringURL gambar yang siap diakses. Untuk upload file, ini adalah URL Supabase Storage. Untuk sendImage, ini adalah URL yang dipass.
mimeTypestringMIME type gambar (image/jpeg, image/png, image/webp, image/gif).
sizeBytesnumberUkuran file dalam bytes. Bernilai 0 untuk gambar yang dilampirkan via sendImage(url).
fileNamestringNama file asli dari upload, atau bagian akhir URL untuk sendImage.

Example

// Analytics: lacak setiap gambar yang diupload user
window.Takonai.onImageUpload = ({ url, mimeType, sizeBytes, fileName }) => {
  console.log('Image attached:', fileName, '(' + Math.round(sizeBytes / 1024) + 'KB)');

  // Contoh: tampilkan preview di sidebar halaman host
  document.getElementById('image-preview').src = url;
};
js

postMessage Events

Widget berkomunikasi dengan halaman host via window.postMessage. Anda dapat meng-intercept event ini langsung jika perlu kontrol lebih dalam.

Host → Widget

Pesan yang dikirim dari halaman host ke iframe widget.

TypePayloadDikirim oleh
TAKONAI_INITTakonaiInitOptionswindow.Takonai.init()
TAKONAI_STEP_CHANGED{ currentStep, context? }window.Takonai.setStep()
TAKONAI_CONTEXT_UPDATE{ context }window.Takonai.setContext()
TAKONAI_SEND_IMAGE{ url: string }window.Takonai.sendImage()

Widget → Host

Pesan yang dikirim dari iframe widget ke halaman host.

TypePayloadKapan dikirim
TAKONAI_READY{}Widget iframe selesai dimuat dan config berhasil di-fetch.
TAKONAI_CONFIG_READY{ primaryColor, fabPosition, fabOffsetX, fabOffsetY, fabImageUrl }Config widget berhasil di-fetch. Berisi data branding dan FAB customization.
TAKONAI_CONFIG_ERROR{}Config gagal di-fetch (widget ID / API key tidak valid, whitelist error). Bubble FAB disembunyikan.
TAKONAI_INIT_ACK{ widgetName, steps }Setelah host memanggil init() dan widget memproses request.
TAKONAI_FILLTakonaiFillPayloadAI berhasil menggunakan tool untuk mengisi form.
TAKONAI_IMAGE_UPLOADEDTakonaiImagePayloadGambar berhasil dilampirkan (dari upload file atau sendImage).
TAKONAI_ERRORTakonaiErrorPayloadTerjadi error di dalam widget.

Intercept Manual

// Intercept langsung jika perlu (biasanya tidak diperlukan)
window.addEventListener('message', (event) => {
  if (event.data?.type === 'TAKONAI_FILL') {
    console.log('Fill event:', event.data.payload);
  }
});
js

Type Reference

// Opsi untuk window.Takonai.init()
interface TakonaiInitOptions {
  externalId: string;
  currentStep?: number;
  context?: Record<string, unknown>;
}

// Payload dari callback onFill
interface TakonaiFillPayload {
  step: number;
  formName: string;
  data: Record<string, unknown>;
}

// Payload dari callback onError
interface TakonaiErrorPayload {
  code: string;
  message: string;
}

// Payload dari callback onImageUpload
interface TakonaiImagePayload {
  url: string;
  mimeType: string;
  sizeBytes: number;
  fileName: string;
}

// Global window.Takonai object
interface TakonaiWidget {
  init(opts: TakonaiInitOptions): void;
  setStep(step: number, context?: Record<string, unknown>): void;
  setContext(context: Record<string, unknown>): void;
  open(): void;
  close(): void;
  sendImage(url: string): void;
  onReady: ((payload?: Record<string, unknown>) => void) | null;
  onOpen: (() => void) | null;
  onClose: (() => void) | null;
  onMessage: ((payload: any) => void) | null;
  onFill: ((payload: TakonaiFillPayload) => void) | null;
  onError: ((payload: TakonaiErrorPayload) => void) | null;
  onImageUpload: ((payload: TakonaiImagePayload) => void) | null;
}

declare global {
  interface Window {
    Takonai: TakonaiWidget;
  }
}
ts

Widget Configuration

Konfigurasi widget dilakukan di dashboard TakonAI. Berikut field-field yang tersedia saat membuat atau mengedit widget.

Provider & Model

FieldKeterangan
providerstringProvider AI. Default: anthropic. Pilih openai_compatible untuk BYOK.
provider_base_urlstringBase URL API untuk openai_compatible (misal: https://api.openai.com/v1).
provider_api_keystringAPI key untuk openai_compatible. Disimpan terenkripsi.
provider_modelstringModel yang digunakan (misal: gpt-4o, claude-sonnet-4-20250514).

BYOK (openai_compatible)

Gunakan provider ini jika ingin menggunakan API key sendiri dari OpenAI, Groq, Together, atau provider lain yang kompatibel dengan format OpenAI Chat Completions API. Fitur Custom Skills hanya tersedia di provider ini.

Fitur AI

FieldDefaultKeterangan
thinking_enabledfalseAktifkan extended thinking / chain-of-thought (label: 'Berpikir...').
thinking_budget_tokensBatas token untuk proses thinking. Hanya berlaku jika thinking_enabled = true.
web_search_enabledfalseIzinkan AI melakukan pencarian web (label: 'Mencari di web...').
web_fetch_enabledfalseIzinkan AI mengambil konten dari URL (label: 'Mengambil halaman...').
search_providerProvider pencarian web (misal: tavily). Wajib jika web_search_enabled = true.
search_api_keyAPI key untuk search provider.

Branding & Tampilan

FieldDefaultKeterangan
primary_color#32CDCDWarna aksen utama widget (hex). Digunakan untuk bubble, header, tombol send, dan bubble pesan user.
avatar_url/logo.webpURL logo/avatar yang ditampilkan di header widget dan watermark background.
welcome_messagestringPesan sambutan saat widget pertama kali dibuka. Bisa di-override via init({ welcomeMessage }).
hide_watermarkfalseSembunyikan watermark logo di background chat. Tersedia untuk plan Growth ke atas.

FAB Customization

Floating Action Button (FAB) bisa dikustomisasi posisi, offset, dan gambarnya melalui dashboard.

FieldDefaultKeterangan
fab_positionbottom-rightPosisi FAB: bottom-right, bottom-left, top-right, atau top-left.
fab_offset_x0Offset horizontal dalam pixel dari posisi default.
fab_offset_y0Offset vertikal dalam pixel dari posisi default.
fab_image_urlURL gambar custom untuk FAB. Wajib format .webp, maksimal 256KB. Jika tidak diisi, FAB menggunakan ikon default dengan primary_color.

Data FAB dikirim ke halaman host via event TAKONAI_CONFIG_READY sehingga widget.js bisa menerapkan posisi dan gambar yang sesuai. Jika config gagal di-fetch, event TAKONAI_CONFIG_ERROR dikirim dan bubble FAB disembunyikan.

Rate Limiting & Keamanan

FieldKeterangan
external_id_daily_limitnumberBatas maksimal pesan per externalId per hari. Jika tercapai, widget menampilkan error DAILY_LIMIT_REACHED.
allowed_originsstring[]Daftar domain yang diizinkan (whitelist). Format: https://example.com (tanpa trailing slash). Kosongkan untuk mengizinkan semua domain.

Image Upload

Widget mendukung upload gambar via tombol paperclip, paste dari clipboard (Ctrl+V / Cmd+V), drag-and-drop, atau programmatic via sendImage(url).

BatasanNilai
Formatimage/png, image/jpeg, image/webp, image/gif
Ukuran maks per file5 MB
Maks gambar per pesan3

Form Configuration

Sebelum widget bisa mengisi form, Anda perlu mengkonfigurasi Form di TakonAI dashboard. Form mendefinisikan tool yang digunakan AI untuk mengekstrak data dari percakapan dan mengirimkannya ke halaman Anda.

Konsep: Form sebagai AI Tool

Setiap form di TakonAI adalah sebuah AI tool. Saat AI memutuskan intent user sudah cukup jelas, ia memanggil tool tersebut dan menghasilkan JSON sesuai skema yang Anda definisikan. JSON ini dikirim ke halaman Anda via callback onFill — Anda bebas menggunakannya untuk apapun: mengisi HTML form, memanggil API, memperbarui state, atau memicu aksi UI. Nama "form" hanyalah konvensi; secara teknis ini adalah structured output dari AI dengan schema yang sepenuhnya Anda kontrol.

Struktur Payload Kompleks (Nested JSON)

Anthropic Tool Schema sepenuhnya mendukung stuktur nested seperti objects dan arrays. Ini sangat bermanfaat ketika Anda ingin output payload dari onFill siap pakai untuk request ke backend API Anda (seperti format produk dengan berbagai atribut dan varian).

Berikut adalah contoh konversi payload untuk produk (Tiket Wisata) yang kompleks:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Nama produk tiket"
    },
    "sku": {
      "type": "string",
      "description": "Kode SKU tiket"
    },
    "description": {
      "type": "string",
      "description": "Deskripsi lengkap terkait produk wisata"
    },
    "category_id": {
      "type": "integer",
      "description": "ID kategori produk (misal: 3 untuk tiket wisata)"
    },
    "price": {
      "type": "number",
      "description": "Harga jual"
    },
    "publish_rate": {
      "type": "number",
      "description": "Harga coret / harga publish"
    },
    "product_advantages_item": {
      "type": "array",
      "description": "Keunggulan produk",
      "items": {
        "type": "object",
        "properties": {
          "name": { "type": "string" }
        }
      }
    },
    "attributes": {
      "type": "array",
      "description": "Atribut varian (contoh: paket, waktu)",
      "items": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "items": {
            "type": "array",
            "items": { "type": "string" }
          },
          "priority": { "type": "integer" }
        }
      }
    },
    "varian_items": {
      "type": "array",
      "description": "Kombinasi hasil varian beserta spesifikasinya",
      "items": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "sku": { "type": "string" },
          "price": { "type": "number" },
          "stok": { "type": "integer" }
        }
      }
    },
    "tracking_adds": {
      "type": "object",
      "description": "Pengaturan tracking pixel",
      "properties": {
        "all_event": { "type": "boolean" },
        "facebook_pixel": {
          "type": "object",
          "properties": {
            "pixel_id": { "type": "array", "items": { "type": "string"} },
            "event": { "type": "array", "items": { "type": "string"} }
          }
        }
      }
    }
  },
  "required": ["name", "sku", "description", "price", "attributes", "varian_items"]
}
json

Tips Penting: Untuk skema yang sangat kompleks seperti pembuatan varian produk, disarankan menggunakan system prompt tambahan di dashboard agar AI tahu bagaimana cara mengisi field tertentu (misal: "Pastikan sku formatnya kebab-case"). Anda juga bisa langsung mem-pass sebagian struktur default (seperti properti tracking_adds) tersebut pada halaman host Anda setelah menerima callback onFill, alih-alih memaksa AI membuat keseluruhan payload statis.


Custom Skills

Custom Skills memungkinkan widget memanggil API eksternal secara server-side saat percakapan berlangsung. Skill dieksekusi oleh backend TakonAI — bukan di browser user — sehingga API key dan endpoint Anda tetap aman.

Catatan

Custom Skills hanya tersedia untuk widget dengan provider openai_compatible (BYOK).

Cara Kerja

  1. AI memutuskan perlu memanggil skill berdasarkan description.
  2. Backend mengirim SSE process event ke frontend (label: "Menjalankan [Nama Skill]...").
  3. Backend melakukan HTTP request ke api_url yang dikonfigurasi.
  4. Response API dikembalikan sebagai konteks ke AI.
  5. AI melanjutkan percakapan dengan informasi dari API.
User chat → AI → Skill Call → Backend HTTP Request → API Response → AI lanjut jawab
text

Field Skill

FieldWajibKeterangan
name*stringNama skill (snake_case). Contoh: cek_ongkir
description*stringDeskripsi kapan AI harus memanggil skill ini. Semakin spesifik, semakin akurat.
api_url*stringURL endpoint API yang akan dipanggil (harus https://).
method*stringHTTP method: GET atau POST.
parameters*JSONJSON Schema yang mendefinisikan parameter yang dikirim AI ke API.
headersJSONHeader tambahan (misal: Authorization, Content-Type).
enabledbooleanAktifkan/nonaktifkan skill. Default: true.

Contoh: Cek Ongkir

{
  "name": "cek_ongkir",
  "description": "Panggil skill ini saat user ingin mengetahui biaya pengiriman. Butuh kota asal, kota tujuan, dan berat dalam gram.",
  "api_url": "https://api.rajaongkir.com/starter/cost",
  "method": "POST",
  "headers": {
    "key": "your_api_key_here",
    "Content-Type": "application/json"
  },
  "parameters": {
    "type": "object",
    "required": ["origin", "destination", "weight"],
    "properties": {
      "origin": {
        "type": "string",
        "description": "ID kota asal pengiriman"
      },
      "destination": {
        "type": "string",
        "description": "ID kota tujuan pengiriman"
      },
      "weight": {
        "type": "integer",
        "description": "Berat paket dalam gram"
      }
    }
  }
}
json

Skill vs Form

FormSkill
EksekusiFrontend (via onFill)Backend (server-side HTTP)
TujuanMengisi form di halaman hostMengambil data dari API eksternal
OutputData dikirim ke halaman hostResponse masuk ke konteks AI
ProviderSemua providerHanya openai_compatible
KonfigurasiMenu Forms → attach ke Widget StepTab Skills di halaman Widget Detail

Error Codes

Daftar error code yang mungkin dikirim via callback onError atau event TAKONAI_ERROR:

CodePesan DefaultKeterangan
DAILY_LIMIT_REACHEDBatas percakapan hari ini tercapaiexternalId sudah melebihi external_id_daily_limit.
INSUFFICIENT_BALANCELayanan tidak tersediaSaldo/kredit habis (provider default).
BILLING_ERRORLayanan tidak tersediaMasalah billing.
RATE_LIMITTerlalu banyak permintaanRate limit dari provider AI.
STREAM_ERRORTerjadi kesalahanError saat streaming response dari AI.
CONFIG_NOT_FOUNDWidget ID atau API key tidak valid.
INVALID_IMAGE_URLURL gambar tidak valid (harus https://).

Full Example

Contoh integrasi lengkap untuk form checkout multi-step. Widget di-init saat user login, step di-update saat user berpindah halaman, dan form diisi otomatis saat AI selesai.

<!DOCTYPE html>
<html>
<head>
  <title>Checkout</title>
</head>
<body>

  <!-- Step 1: Data Pembeli -->
  <form id="form-buyer">
    <input name="full_name" placeholder="Nama Lengkap" />
    <input name="email" placeholder="Email" />
    <input name="phone" placeholder="No. HP" />
    <button type="button" onclick="goToStep2()">Lanjut</button>
  </form>

  <!-- Step 2: Alamat Pengiriman -->
  <form id="form-shipping" style="display:none">
    <input name="address" placeholder="Alamat" />
    <input name="city" placeholder="Kota" />
    <input name="postal_code" placeholder="Kode Pos" />
    <button type="submit">Bayar</button>
  </form>

  <!-- 1. Embed widget -->
  <script
    src="https://cdn.ztakonai.com"
    data-widget-id="wgt_abc123"
    data-api-key="tk_live_xxxx">
  </script>

  <script>
    // 2. Init saat widget siap (iframe dimuat)
    window.Takonai.onReady = () => {
      window.Takonai.init({
        externalId: 'usr_123', // Ganti dengan ID unik user Anda
        currentStep: 1,
        context: {
          cartItems: 3,
          totalAmount: 450000,
        },
      });
    };

    // 3. Isi form otomatis saat AI selesai
    window.Takonai.onFill = ({ step, formName, data }) => {
      const formEl = step === 1
        ? document.getElementById('form-buyer')
        : document.getElementById('form-shipping');

      Object.entries(data).forEach(([field, value]) => {
        const el = formEl.querySelector('[name="' + field + '"]');
        if (el) el.value = value;
      });
    };

    // 4. Handle error
    window.Takonai.onError = ({ code, message }) => {
      console.error('[TakonAI Error]', code, message);
    };

    // 5. Update step saat user pindah halaman
    function goToStep2() {
      document.getElementById('form-buyer').style.display = 'none';
      document.getElementById('form-shipping').style.display = 'block';

      window.Takonai.setStep(2, {
        buyerName: document.querySelector('[name="full_name"]').value,
      });
    }
  </script>

</body>
</html>
html