Integration Guide

1. Add the Widget Script

<script src="https://your-server.com/embed/ozwell-loader.js"></script>

That's it for basic chat! Add config for more features:

2. Define MCP Tools (Optional)

Tell the widget what actions are available:

<script>
  // Documentation example - shows configuration options
  window.OzwellChatConfig = {
    debug: true,  // Shows tool execution details (set false for production)
    tools: [{
      type: 'function',
      function: {
        name: 'update_form_data',
        description: 'Updates user profile information',
        parameters: {
          type: 'object',
          properties: {
            name: { type: 'string', description: 'New name (optional)' },
            address: { type: 'string', description: 'New address (optional)' },
            zipCode: { type: 'string', description: 'New zip code (optional)' }
          },
          required: []
        }
      }
    }]
  };
</script>

3. Implement Tool Handlers (Your Code)

Write code to execute tools when AI calls them:

window.addEventListener('message', (e) => {
  if (e.data.source === 'ozwell-chat-widget' &&
      e.data.type === 'tool_call') {

    // Execute the tool on YOUR page
    if (e.data.tool === 'update_form_data') {
      if (e.data.payload.name) nameInput.value = e.data.payload.name;
      if (e.data.payload.address) addressInput.value = e.data.payload.address;
      if (e.data.payload.zipCode) zipInput.value = e.data.payload.zipCode;
    }

    // Send result back to widget
    OzwellChat.iframe.contentWindow.postMessage({
      source: 'ozwell-chat-parent',
      type: 'tool_result',
      result: { success: true }
    }, '*');
  }
});

How It Works

  • Widget auto-mounts and auto-detects endpoint
  • LLM calls tools when user requests actions
  • Tool calls sent to parent via postMessage
  • Parent executes and sends result back
  • Widget shows natural confirmation

Ozwell Chatbot Client Demo

Embedded chat with tool execution via iframe-sync and postMessage

How It Works (Sequence Diagram)

sequenceDiagram participant Browser participant Ozwell as Reference Server participant Ollama as Ollama Container participant Widget as Widget (iframe) participant Handler as Tool Handler Browser->>Ozwell: 1. Load ozwell-loader.js Note over Browser,Ozwell: Script tag embed Browser->>Browser: 2. User clicks chat button Browser->>Widget: 3. Create iframe (lazy loading) Note over Widget: Chat widget loads rect rgb(255, 243, 205) Note over Widget: 🔒 SECURE BOUNDARY
All chat messages stay in iframe Widget->>Widget: User types message Widget->>Ozwell: POST /v1/chat/completions
(stream=true) Note over Widget,Ozwell: Authorization: Bearer ollama Ozwell->>Ollama: Forward to Ollama API
(qwen2.5-coder:3b) Note over Ozwell,Ollama: Internal IP: 10.15.123.17:8080 rect rgb(230, 255, 230) Note over Ozwell,Widget: 🔄 SSE STREAMING Ollama-->>Ozwell: Stream: chunk 1 Ozwell-->>Widget: data: {"delta":{"content":"Hello"}} Ollama-->>Ozwell: Stream: chunk 2 Ozwell-->>Widget: data: {"delta":{"content":"!"}} Note over Ozwell: ❤️ Heartbeat every 25s
: heartbeat Ollama-->>Ozwell: Stream: chunk N Ozwell-->>Widget: data: {"delta":{"content":"..."}} Ollama-->>Ozwell: Stream: finish_reason=stop Ozwell-->>Widget: data: [DONE] end Widget->>Widget: Parse tool calls from response end Widget->>Handler: 4. postMessage: tool_call Note over Widget,Handler: Only tool calls cross boundary Handler->>Handler: 5. Execute tool (update form) Handler-->>Widget: 6. postMessage: tool_result Browser->>Widget: 7. iframe-sync: state update Note over Browser,Widget: Widget always has page context

User Information

Type directly or use chat to update fields

Live Event Log

Watch iframe-sync and postMessage in action