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
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