Skip to content

Configuration ​

A bot's settings are one JSON document. The admin panel edits a draft; publishing checks it and freezes a copy as a new version, which live chats switch to (conversations already under way keep the version they started with). See Concepts.

Every setting has a default, so {} is a complete bot once a brain is connected. The REST API takes the same document: PATCH /api/v1/bots/{id} with { "patch": { ... } } deep-merges a partial config into the draft (arrays and null replace), and POST /api/v1/bots/{id}/publish publishes it. See REST API.

json
{
  "identity": { "agentName": "Ava", "instructions": "Help visitors with orders and returns." },
  "appearance": { "layout": "drawer", "theme": { "accent": "#0ea5e9" } },
  "security": { "allowedOrigins": ["https://www.example.com"] }
}

Sections: Schema version, Identity, Welcome, Brain, Voice, Vision, Face, Appearance, Texts, Greeting, Behaviour, Security, Knowledge, Tools

Schema version ​

SettingTypeDefault
schemaVersion11The version of this format. Always 1 for now.

Identity ​

Who the agent is, and what it should do. Admin panel: the bot's Identity tab.

SettingTypeDefault
identity.agentNamestring
1 to 60 chars
"Ava"The agent's name: the chat's title, and {{agent.name}} in texts.
identity.rolestring
up to 120 chars
"Virtual assistant"Its role, e.g. "Support assistant": the subtitle under the name (unless texts.subtitle is set) and part of the prompt.
identity.businessNamestring
up to 120 chars
""Your business's name, for the prompt and {{business.name}} (which falls back to the agent's name).
identity.languagestring
up to 35 chars
"en"The default language, as a tag like en or de. The agent replies in it when languagePolicy is fixed, or when it can't tell the visitor's language.
identity.languagePolicy'match_visitor' | 'fixed'"match_visitor"match_visitor: reply in the visitor's language. fixed: always reply in language (voice engines are told to use it too).
identity.timezonestring
up to 64 chars
"UTC"The agent is told the date and time in this zone (an IANA name such as Europe/London).
identity.personality.preset'friendly' | 'professional' | 'playful' | 'concise' | 'empathetic' | 'custom'"friendly"A tone of voice. custom uses only personality.text.
identity.personality.textstring
up to 2000 chars
""More about its personality, added after the preset.
identity.instructionsstring
up to 20000 chars
""What the agent should do and know: your main prompt. It can use {{agent.name}}, {{agent.role}}, {{business.name}}, {{page.url}}, {{page.title}}, and {{visitor.name}} and {{visitor.email}} (filled in for verified visitors only). They are filled in when a conversation starts.
identity.guardrailsstring
up to 5000 chars
""Things the agent must not do or discuss. It can use {{agent.name}}, {{agent.role}}, {{business.name}}, {{page.url}}, {{page.title}}, and {{visitor.name}} and {{visitor.email}} (filled in for verified visitors only). They are filled in when a conversation starts.

Welcome ​

The first thing the chat shows. Admin panel: the bot's Identity tab.

SettingTypeDefault
welcome.messagestring
up to 500 chars
"Hi! I'm {{agent.name}}. How can I help you today?"The first message in the chat (the agent knows it said it). It can use {{agent.name}}, {{agent.role}} and {{business.name}}. Empty: no welcome.
welcome.suggestedPromptsstring[]
up to 6 items, each up to 80 chars
[]Up to 6 one-tap questions shown until the visitor sends a message.
welcome.speakGreetingbooleanfalseIn voice, the agent says hello first when the conversation starts with voice.

Brain ​

The text model that writes the replies (and, in the cascade voice, the spoken ones). Admin panel: the bot's Brain tab.

SettingTypeDefault
brain.connectionIdstring | null
up to 64 chars
nullThe provider connection for replies: Anthropic, OpenAI or Gemini. A new bot uses the first one connected.
brain.modelstring
up to 120 chars
""The model id, picked from the connection's model list. A new bot gets the provider's recommended model (for Anthropic, claude-opus-5-5 when the key has it).
brain.effort'minimal' | 'low' | 'medium' | 'high'"low"How much reasoning models think. Claude: its effort setting (minimal counts as low; models without effort ignore it). OpenAI reasoning models: reasoning effort. Gemini 3 and later: thinking level (medium and high mean high, the others low).
brain.maxOutputTokensinteger
256 to 128000
4096The longest reply, in tokens. Replies spoken in voice are capped at 2048.
brain.maxToolRoundsinteger
1 to 10
5How many rounds of tool calls one reply may make before the agent must answer.
brain.temperaturenumber | null
0 to 2
nullSampling temperature, or null for the model's default. Models that don't take it (newer Claude models, OpenAI reasoning models) ignore it.
brain.compactAtTokensinteger
at least 8000
120000When a conversation's history (roughly estimated) grows past this many tokens, the older part is condensed into a summary that the model sees first, followed by the recent messages. The transcript keeps every message. See Concepts.

Voice ​

Talking with the agent. See Voice. Admin panel: the bot's Voice tab.

SettingTypeDefault
voice.enabledbooleanfalseTurn voice on. The microphone button appears once the chosen engine is fully set up.
voice.mode'realtime' | 'cascade' | 'elevenlabs_agent'"realtime"realtime (OpenAI Realtime or Gemini Live, depending on the connection), cascade (speech to text, then the brain, then text to speech) or elevenlabs_agent (ElevenLabs Agents).
voice.realtime.connectionIdstring | null
up to 64 chars
nullAn OpenAI or Gemini connection.
voice.realtime.modelstring
up to 120 chars
""A realtime model from that connection.
voice.realtime.voicestring
up to 120 chars
""The voice.
voice.realtime.turnDetection'semantic_vad' | 'server_vad'"semantic_vad"OpenAI only. semantic_vad waits until the visitor has finished their thought; server_vad answers after a pause.
voice.realtime.eagerness'low' | 'medium' | 'high' | 'auto'"auto"OpenAI only, with semantic_vad: how quickly it answers.
voice.cascade.stt.connectionIdstring | null
up to 64 chars
nullSpeech to text: an OpenAI or ElevenLabs connection.
voice.cascade.stt.modelstring
up to 120 chars
""Empty uses gpt-4o-mini-transcribe (OpenAI) or scribe_v2_realtime (ElevenLabs).
voice.cascade.stt.languagestring
up to 35 chars
""A language hint for transcription (its first two letters are used). Empty uses identity.language when the policy is fixed, else the provider detects it.
voice.cascade.tts.connectionIdstring | null
up to 64 chars
nullText to speech: an ElevenLabs, OpenAI or Gemini connection.
voice.cascade.tts.modelstring
up to 120 chars
""Empty uses eleven_flash_v2_5 (ElevenLabs), gpt-4o-mini-tts (OpenAI) or gemini-3.8-flash-lite-tts (Gemini).
voice.cascade.tts.voicestring
up to 120 chars
""The voice id.
voice.cascade.tts.speednumber
0.5 to 2
1Speaking speed. OpenAI and ElevenLabs only.
voice.cascade.tts.stylestring
up to 500 chars
""How to speak, in words, e.g. "warm and unhurried". OpenAI (as instructions) and Gemini only; ElevenLabs ignores it.
voice.elevenlabsAgent.connectionIdstring | null
up to 64 chars
nullAn ElevenLabs connection. The server creates an ElevenLabs agent for the bot and updates it when these settings change.
voice.elevenlabsAgent.voicestring
up to 120 chars
""The ElevenLabs voice id.
voice.elevenlabsAgent.ttsModelstring
up to 120 chars
""Empty uses eleven_flash_v2_5.
voice.elevenlabsAgent.llmstring
up to 120 chars
""The model ElevenLabs runs the agent with (an ElevenLabs LLM id). Empty uses ElevenLabs' default.
voice.bargeInbooleantrueThe visitor can interrupt the agent by talking over it. Push-to-talk always interrupts.
voice.pushToTalk'off' | 'allowed' | 'only'"allowed"off; allowed (hands-free by default; your page can start push-to-talk with startVoice({ mode: 'ptt' })); or only (the microphone button starts push-to-talk).
voice.maxSessionMinutesnumber
1 to 120
15A voice conversation ends after this many minutes (the chat carries on in text).
voice.idleSecondsnumber
15 to 1800
120It also ends after this many seconds with no one speaking.

Vision ​

Images and the camera. See Vision and webcam. Admin panel: the bot's Vision tab.

SettingTypeDefault
vision.uploads.enabledbooleantrueVisitors can attach images (only if the brain can see images).
vision.uploads.maxPerMessageinteger
1 to 10
4Images per message.
vision.uploads.maxMBnumber
1 to 25
10The largest image, in MB. The chat shrinks photos to 1568 pixels before sending them.
vision.webcam.enabledbooleanfalseOffer the camera button (only if the brain can see images).
vision.webcam.mode'continuous' | 'per_turn' | 'on_demand'"per_turn"per_turn: the latest frame goes with each message. continuous: a live view for engines that take video (Gemini Live), otherwise like per_turn. on_demand: only when the agent uses look_at_camera. (In a voice conversation on ElevenLabs Agents, which can't take pictures, the camera works on demand.)
vision.webcam.maxFpsnumber
0.1 to 2
1The most frames a second the chat sends (continuous is held to 1, per_turn to 0.5).
vision.webcam.maxWidthinteger
160 to 1280
640The widest frame, in pixels.
vision.webcam.consentTextstring
up to 1000 chars
"Turn on your camera so {{agent.name}} can see what you show it. Video is not recorded."What the camera prompt says before the browser asks for permission. It can use {{agent.name}}.
vision.webcam.privacyUrlstring
up to 2048 chars
""A privacy page linked from the camera prompt.
vision.webcam.persistFramesbooleanfalseKeep camera frames with the conversation. Off, they are deleted within about two hours of the conversation ending.
vision.webcam.shareWithHumanAgentsbooleanfalseLet your team see camera frames in transcripts.
vision.proxy.connectionIdstring | null
up to 64 chars
nullFor voice engines that can't see (ElevenLabs Agents): the connection whose model describes camera pictures in words. Empty uses the brain.
vision.proxy.modelstring
up to 120 chars
""That model.

Face ​

The animated face. Admin panel: the bot's Face tab.

SettingTypeDefault
face.configobject{"preset":"cyan"}The face engine's settings (look, colours, motion), as edited in the Face tab. preset picks a colour scheme.
face.skin{ kind: 'catalogue'; id: string } | { kind: 'custom'; assetId: string } | null{"kind":"catalogue","id":"mei"}A face from the catalogue ({ kind: "catalogue", id }), one made from a photo in the admin panel ({ kind: "custom", assetId }), or null for none.
face.defaultMoodstring | null
up to 40 chars
"content"The mood the face starts in.
face.expressionsbooleantrueLet the agent change the face's expression: mood tags in text replies, the express tool in voice.

Appearance ​

Layout, launcher and look. Pages can override some of these with boot options. See Layouts and launchers. Admin panel: the bot's Appearance & embed tab.

SettingTypeDefault
appearance.layout'panel' | 'drawer' | 'floating' | 'inline'"panel"panel (a window by the launcher), drawer (full height on one side), floating (the face over the page, with captions and a small message box) or inline (inside your page).
appearance.launcher.type'bubble' | 'tab' | 'none'"bubble"bubble (a round button), tab (a labelled tab on an edge) or none (open it from your own button).
appearance.launcher.position'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'"bottom-right"Bubble: the corner.
appearance.launcher.edge'right' | 'left' | 'bottom'"right"Tab: the edge.
appearance.launcher.align'start' | 'center' | 'end'"end"Tab: where along the edge.
appearance.launcher.labelstring
up to 40 chars
"Chat with us"Tab: its text.
appearance.launcher.icon'face' | 'chat' | 'avatar'"face"face: the agent's face picture, breathing gently on the bubble (still under reduced motion). avatar: the same picture, still. chat: a chat icon.
appearance.launcher.offset.xnumber
0 to 400
20Distance from the side, in pixels.
appearance.launcher.offset.ynumber
0 to 400
20Distance from the top or bottom, in pixels.
appearance.launcher.sizenumber
40 to 96
60The bubble's diameter, in pixels.
appearance.launcher.hideOnMobilebooleanfalseHide the launcher on phones.
appearance.theme.mode'light' | 'dark' | 'auto'"auto"light, dark, or auto (the visitor's system setting).
appearance.theme.accentstring
matches ^#[0-9a-fA-F]{6}$
"#6366f1"The accent colour (#rrggbb). Text on it is black or white, whichever reads better.
appearance.theme.radiusnumber
0 to 28
16Corner radius, in pixels.
appearance.theme.font'system' | 'inter' | 'serif' | 'mono'"system"system (the device's UI font), inter (Inter when the device has it, else the UI font), serif or mono.
appearance.panel.widthnumber
320 to 560
400Panel layout: width in pixels.
appearance.panel.heightnumber
400 to 900
680Panel layout: height in pixels (never taller than the window).
appearance.drawer.widthnumber
320 to 640
420Drawer layout: width in pixels.
appearance.drawer.side'auto' | 'left' | 'right'"auto"left, right, or auto (the launcher's side).
appearance.drawer.modalbooleanfalseDim the page behind the drawer and stop it scrolling.
appearance.floating.widthnumber
220 to 480
300Floating layout: width in pixels.
appearance.floating.heightnumber
260 to 640
420Floating layout: height in pixels.
appearance.floating.composerbooleantrueFloating layout: show a small message box under the face.
appearance.mobile.fullscreenbooleantrueOn phones, the open chat fills the screen.
appearance.face.showbooleantrueShow the face in the panel, drawer and inline layouts (visitors can still hide it).
appearance.face.size'small' | 'medium' | 'large'"medium"How much room the face takes.
appearance.face.textReplies'still' | 'mime' | 'speak'"mime"mime: the mouth moves silently along with typed replies. still: it doesn't move. speak: typed replies are read aloud, with the lips in sync, in the voice set under voice.cascade.tts (voice conversations don't need to be on). Visitors get a sound button to turn it off, and browsers only allow the sound after the visitor has typed or clicked in the chat; until then a reply is mimed.
appearance.captionsbooleantrueFloating layout: show the agent's latest message under the face.
appearance.zIndexinteger
0 to 2147483647
2147483000The z-index of the launcher and window on your page.

Texts ​

The chat's own words. See Customising. Admin panel: the bot's Behaviour tab.

SettingTypeDefault
texts.titlestring
up to 80 chars
""The chat's title. Empty: the agent's name.
texts.subtitlestring
up to 120 chars
""The line under the title. Empty: the agent's role.
texts.placeholderstring
up to 120 chars
"Type a message..."The message box's placeholder.
texts.offlinestring
up to 500 chars
"We're away right now. Leave your details and we'll get back to you."Shown when the bot is outside its opening hours (and sent as the reply to messages then, with hours.scope: bot), and when no one is available for a hand-off. It can use {{agent.name}}.
texts.stringsRecord<string, string>{}Your own wording for any interface text, by key. See Interface strings.

Greeting ​

A small bubble by the launcher that invites visitors to chat (the "teaser"). Admin panel: the bot's Appearance & embed tab.

SettingTypeDefault
greeting.enabledbooleanfalseShow the greeting bubble.
greeting.textstring
up to 200 chars
"Hi there! Any questions? I can help."What it says. It can use {{agent.name}}.
greeting.delayMsinteger
0 to 120000
6000How long after the page loads, in milliseconds.
greeting.frequency'session' | 'visitor' | 'always'"session"session: once per browser tab. visitor: until the visitor closes it. always: on every page.
greeting.pages.includestring[]
up to 50 items, each up to 300 chars
[]Only on these paths (globs where * matches anything, e.g. /pricing*). Empty: every page.
greeting.pages.excludestring[]
up to 50 items, each up to 300 chars
[]Never on these paths.
greeting.mobilebooleanfalseAlso show it on phones.

Behaviour ​

Leads, hand-off, opening hours, feedback and how conversations last. Admin panel: the bot's Behaviour tab.

SettingTypeDefault
behavior.leadCapture.enabledbooleanfalseCollect contact details.
behavior.leadCapture.when'tool' | 'start' | 'before_handoff' | 'offline'"tool"When the lead form appears: tool (no form: the agent asks in the conversation and saves the details with capture_lead), start (a form before the first message), before_handoff (a form when a hand-off to a person starts), or offline (only in the offline flows: outside opening hours, or when no one is available for a hand-off, which show the form whatever this setting). The agent's capture_lead tool is there whenever lead capture is on.
behavior.leadCapture.fieldsArray<{ key: string; label: string; type: 'text' | 'email' | 'tel' | 'textarea' | 'select'; required: boolean; options?: string[] }>
up to 12 items
Name (text) and Email (email), both requiredThe fields to collect (up to 12).
behavior.leadCapture.fields[].keystring
matches ^[a-z][a-z0-9_]{0,31}$
requiredIts key in the saved lead: lowercase letters, digits and _.
behavior.leadCapture.fields[].labelstring
up to 80 chars
requiredIts label.
behavior.leadCapture.fields[].type'text' | 'email' | 'tel' | 'textarea' | 'select'"text"The input type.
behavior.leadCapture.fields[].requiredbooleanfalseWhether it must be filled in.
behavior.leadCapture.fields[].optionsstring[]
up to 20 items, each up to 80 chars
(not set)For select: the choices.
behavior.handoff.enabledbooleanfalseLet the agent, or the visitor (from the chat menu), ask for a person from your team.
behavior.handoff.acceptTimeoutSecinteger
15 to 3600
120How long to wait for someone to accept before telling the visitor no one is available.
behavior.handoff.offlineAction'lead_form' | 'message' | 'none'"lead_form"When no one is available (outside opening hours, or nobody from the team has the admin panel open): lead_form also shows the lead form; message and none only show the offline text.
behavior.hours.enabledbooleanfalseUse opening hours.
behavior.hours.timezonestring
up to 64 chars
"UTC"The zone the hours are in.
behavior.hours.weeklyArray<{ day: integer; open: string; close: string }>
up to 21 items
Monday to Friday, 09:00 to 17:00Open periods (up to 21).
behavior.hours.weekly[].dayinteger
0 to 6
required0 is Sunday, 6 is Saturday.
behavior.hours.weekly[].openstring
matches ^\d\d:\d\d$
requiredOpening time, HH:MM.
behavior.hours.weekly[].closestring
matches ^\d\d:\d\d$
requiredClosing time, HH:MM.
behavior.hours.holidaysstring[]
up to 100 items
[]Closed days, as YYYY-MM-DD.
behavior.hours.scope'handoff' | 'bot'"handoff"handoff: hours only decide when people can take over. bot: outside hours the AI is offline too: a typed message gets the offline text (at most once an hour) and the lead form (if lead capture is on), the model isn't called, and the face shows its offline state.
behavior.feedback.thumbsbooleantrueThumbs up and down on replies.
behavior.feedback.csatbooleantrueAsk for a 1 to 5 rating when a conversation ends.
behavior.persistence.resumeWindowHoursnumber
0 to 720
24A visitor who comes back within this many hours continues their conversation. 0: always start a new one.
behavior.persistence.showHistorybooleantrueShow a returning visitor the earlier messages of the conversation they continue. Off: their window starts clean, while the conversation (and what the agent remembers) carries on.
behavior.endAfterIdleMinutesnumber
1 to 1440
30Conversations with the AI are closed after this many minutes without a message, once no one has the chat open.
behavior.citationsbooleantrueShow the knowledge-base sources a reply used.
behavior.newConversationbooleantrueOffer "New conversation" in the chat menu.
behavior.transcriptDownloadbooleantrueOffer "Download transcript" in the chat menu.
behavior.poweredBybooleantrueShow "Powered by Wireface" at the bottom of the chat.

Security ​

Who may embed the bot, identity, rate limits and spending caps. Admin panel: the bot's Security tab.

SettingTypeDefault
security.allowedOriginsstring[]
up to 100 items, each up to 300 chars
[]The sites that may embed the bot: https://example.com, https://*.example.com (subdomains only), http://localhost:* (any port), example.com (http or https), or *. Empty: any site, which the admin panel warns about.
security.identity.mode'off' | 'optional' | 'required'"off"off: the page's user is ignored. optional: identities are used, and verified when they have a valid hash. required: every visitor needs a valid hash. See Identity verification.
security.rateLimits.messagesPerMinuteinteger
1 to 600
12Messages a visitor may send per minute.
security.rateLimits.conversationsPerIpPerHourinteger
1 to 10000
30New conversations with this bot from one IP address per hour; more get rate_limited. (Separately, every server allows 30 chat connections a minute per IP.)
security.rateLimits.uploadsPerHourinteger
0 to 1000
30Images a visitor may upload per hour.
security.maxMessageCharsinteger
100 to 20000
4000The longest message a visitor can send; the chat's message box stops there too.
security.maxTurnsPerConversationinteger
1 to 5000
200A conversation stops taking messages at about three times this many messages (session_limit).
security.caps.dailyUsdnumber | null
at least 0
nullStop answering when the bot's estimated spend today (UTC) reaches this many US dollars. Estimates use built-in list prices; unknown models count as free. null: no cap.
security.caps.dailyVoiceMinutesnumber | null
at least 0
nullMinutes of voice audio (both ways) per UTC day. Voice stops at the cap. null: no cap.
security.caps.dailyMessagesinteger | null
at least 0
nullThe agent's replies per UTC day. null: no cap.
security.caps.concurrentVoiceSessionsinteger
0 to 1000
5Voice conversations at once, for this bot on this server.

Knowledge ​

See Knowledge base. Admin panel: the bot's Knowledge tab.

SettingTypeDefault
knowledge.sourceIdsstring[]
up to 200 items, each up to 64 chars
[]The knowledge sources this bot uses.
knowledge.mode'auto' | 'tool' | 'both'"both"auto: before each text reply the best excerpts are added for the agent. tool: the agent searches with search_knowledge when it wants. both. Voice engines always search with the tool.
knowledge.topKinteger
1 to 20
5How many excerpts a search returns.

Tools ​

See Tools and MCP and Client tools. Admin panel: the bot's Tools tab.

SettingTypeDefault
tools.builtins.search_knowledgebooleantrueSearching the knowledge base (when the bot has sources).
tools.builtins.capture_leadbooleantrueSaving contact details (when lead capture is on).
tools.builtins.handoff_to_humanbooleantrueAsking for a person (when hand-off is on).
tools.builtins.end_conversationbooleantrueEnding the conversation after saying goodbye.
tools.builtins.expressbooleantrueFace expressions: mood tags in text replies, the express tool in voice.
tools.builtins.look_at_camerabooleantrueLooking through the visitor's camera (when the camera is on for this bot).
tools.httpArray<{ toolId: string; enabled: boolean }>
up to 100 items
[]HTTP tools this bot uses (they are defined once for the workspace).
tools.http[].toolIdstring
up to 64 chars
requiredThe HTTP tool.
tools.http[].enabledbooleantrueWhether this bot uses it.
tools.mcpArray<{ serverId: string; allow: '*' | string[]; confirmDestructive: boolean }>
up to 50 items
[]MCP servers this bot uses.
tools.mcp[].serverIdstring
up to 64 chars
requiredThe MCP server.
tools.mcp[].allow'*' | string[]"*"Which of its tools: * or a list of names.
tools.mcp[].confirmDestructivebooleantrueAsk the visitor before running this server's tools that are marked destructive (destructiveHint in their MCP annotations).
tools.client.enabledbooleanfalseLet the agent use tools your page registers. Off by default: page tools are ignored until you turn this on.
tools.client.allow'*' | string[][]Which page tools: a list of names, or *. The default, an empty list, allows none.
tools.client.timeoutMsinteger
1000 to 120000
15000How long the server waits for a page tool.
tools.toolTimeoutMsinteger
1000 to 120000
15000How long any tool call may take.
tools.maxResultCharsinteger
500 to 100000
8000Longer results from HTTP, MCP and page tools are cut to this length before the agent sees them.

Wireface Chat 0.1.0. These docs are served by your own server.