A voice-powered AI assistant that can see and interact with any web page through Webfuse. Users click a floating orb to start a conversation, and the assistant can click buttons, fill forms, scroll, navigate, and more — all by voice.
User speaks ──> Vapi (voice + LLM) ──> Tool call ──> Webfuse Automation API ──> Page action
- The extension renders a floating orb widget in a Webfuse Session
- User clicks the orb to start a voice call with a Vapi assistant
- The assistant has access to browser automation tools (click, type, scroll, etc.)
- Tools are executed via the Webfuse Automation API, which interacts with the live page
| Tool | Description |
|---|---|
take_dom_snapshot |
Read the page structure (HTML with Webfuse IDs for targeting) |
click_element |
Click a button, link, or any element |
type_text |
Type into input fields |
press_key |
Press keyboard keys (Enter, Escape, Tab, etc.) |
navigate_to |
Navigate to a URL |
git clone https://github.com/webfuse-com/extension-vapi-voice-agent.git
cd extension-vapi-voice-agent
pnpm installpnpm buildThis bundles the extension into the dist/ folder using Vite, producing:
dist/
background.js # Minimal background script
content.js # Automation API relay
popup.html # Orb widget UI
popup.js # Vapi SDK + tools (bundled)
manifest.json # Extension manifest
- Go to Webfuse Studio and create a Space
- Open Settings (gear icon) > Extensions
- Click Upload Extension and select the
dist/folder - The extension is now installed in your Space
You can set your Vapi credentials in two ways:
Edit manifest.json and set the value fields:
{
"env": [
{
"key": "VAPI_PUBLIC_KEY",
"value": "your-vapi-public-key",
"description": "Your Vapi public API key from the Vapi Dashboard"
},
{
"key": "VAPI_ASSISTANT_ID",
"value": "your-assistant-id",
"description": "The Vapi assistant ID to use for voice conversations"
}
]
}Then rebuild with pnpm build.
After uploading the extension:
- Open Settings (gear icon) > Extensions
- Click on Vapi Voice Widget
- Click Configure next to Environment Variables
- Set
VAPI_PUBLIC_KEYandVAPI_ASSISTANT_ID
This approach keeps your keys out of the code and lets you change them without rebuilding.
- Sign in to the Vapi Dashboard
- Create a new Assistant
- Copy the Assistant ID — this is your
VAPI_ASSISTANT_ID - Copy your Public Key from the dashboard — this is your
VAPI_PUBLIC_KEY
The extension uses an inline assistant configuration with client-side tools. If you set a
VAPI_ASSISTANT_ID, the extension will use your pre-configured assistant. The inline config includes a system prompt and tools for web automation — seesrc/tools.tsto customize.
vapi-voice-widget/
src/
popup.ts # Orb UI + Vapi SDK + tool call handling
tools.ts # Webfuse Automation tool definitions
content.ts # Automation API relay (runs in page context)
background.ts # Auto-opens the popup on session start
types/
webfuse.d.ts # TypeScript types for Webfuse extension APIs
popup.html # Orb widget HTML + CSS (animations, glow states)
manifest.json # Extension manifest (permissions, env vars)
build.ts # Vite build script (bundles each entry as IIFE)
package.json
tsconfig.json
The extension uses three contexts, each with a specific role:
| Context | File | Role |
|---|---|---|
| Popup | popup.ts |
Runs the Vapi SDK (voice + audio), handles tool calls, renders the orb UI. Popup has WebRTC access and respects host_permissions for CSP. |
| Content | content.ts |
Thin relay that executes Webfuse Automation API calls on the page. Reloads on navigation. |
| Background | background.ts |
Auto-opens the popup when the session starts. |
Why the popup? In Webfuse,
host_permissionsdo not apply to content scripts (to preserve the proxied page's CSP). The popup is the only context that has both unrestricted network access (for Daily.co WebRTC) and full browser APIs (microphone, audio). SeeREPORT.mdfor the full investigation.
Edit src/popup.ts and change the voice provider/ID in vapi.start():
voice: { provider: "vapi", voiceId: "Elliot" },See Vapi Voice Options for available voices.
Edit src/tools.ts to add new automation tools or modify existing ones. Each tool needs:
- A handler in
handleToolCall()that calls the Webfuse Automation API - A Vapi tool definition in the
vapiToolsarray
See the Webfuse Automation API Reference for all available methods.
Edit the systemPrompt export in src/tools.ts to change how the assistant behaves.