Integration Guide

Add an AI chat widget to any webpage in 3 steps. Conversations stay private inside an iframe — your page only sees tool calls.

1. Create Your Agent

Register an agent via the API. Choose a method:

curl -X POST https://your-server.com/v1/agents \
  -H "Authorization: Bearer ozw_your-api-key" \
  -H "Content-Type: application/yaml" \
  -d '
name: Form Helper
tools:
  - name: get_form_data
    description: Retrieves the current form values
  - name: update_form_data
    description: Updates form fields
    inputSchema:
      type: object
      properties:
        name:
          type: string
          description: The new name
        address:
          type: string
          description: The new address
instructions: |
  You help users fill out forms.
  Call get_form_data to read current field values.
  Call update_form_data to save changes.
'

Loading API explorer...

Configure your agent visually using the Q form builder — no YAML or cURL needed.

Open Agent Builder →

You'll get back an agent_key to use in the next step. The agent key carries the personality, model, and tools — no client-side config needed.

Key: Tool schemas (description + inputSchema) are stored server-side with the agent — the LLM gets the correct parameter names automatically.

2. Add the Widget

Paste this into your HTML with the agent key from Step 1:

<script>
  window.OzwellChatConfig = {
    apiKey: 'agnt_key-your-agent-key-here'
  };
</script>
<script src="https://your-server.com/embed/ozwell-loader.js"></script>

That's it for a basic chatbot! The widget automatically discovers available tools from your agent config.

3. Handle Tool Calls on Your Page

When the AI decides to use a tool, the loader dispatches a DOM event. You handle it and call respond() with the result:

document.addEventListener('ozwell-tool-call', (e) => {
  const { name, arguments: args, respond } = e.detail;

  if (name === 'get_form_data') {
    respond({
      name: document.getElementById('name').value,
      email: document.getElementById('email').value
    });
  }
});

No tools? Skip Steps 1 and 3 — just embed the widget with a parent API key.

Ozwell Chatbot Client Demo

Embedded chat with tool execution via MCP JSON-RPC and postMessage

How It Works (Sequence Diagram)

sequenceDiagram participant Browser participant Ozwell as Reference Server participant LLM as LLM Backend
(Gateway or Ollama) 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 agnt_key-... Ozwell->>LLM: Forward request Note over Ozwell,LLM: Gateway or Ollama
(based on config) rect rgb(230, 255, 230) Note over Ozwell,Widget: SSE STREAMING LLM-->>Ozwell: Stream: chunk 1 Ozwell-->>Widget: data: {"delta":{"content":"Hello"}} LLM-->>Ozwell: Stream: chunk 2 Ozwell-->>Widget: data: {"delta":{"content":"!"}} Note over Ozwell: Heartbeat every 25s
: heartbeat LLM-->>Ozwell: Stream: finish_reason=stop Ozwell-->>Widget: data: [DONE] end Widget->>Widget: Parse tool calls from response end Widget->>Handler: 4. MCP JSON-RPC: tools/call Note over Widget,Handler: Only tool calls cross boundary Handler->>Handler: 5. Execute tool (update form) Handler-->>Widget: 6. MCP JSON-RPC response

User Information

Type directly or use chat to update fields

Live Event Log

Watch MCP tool calls and postMessage in action