Skip to main content
Version: Current

Agent & portals

agent:
name: Teranga # optional: Convoy never invents a name
persona: "a warm host who helps put the meal together"
tone: friendly # friendly | professional | playful
rules:
- "Never invent a dish: only what the menu returns."
emoji: false
model: gemini-2.5-flash # the agent's model
portals:
web: # the tenant's site, a portal of the agent
widget:
origins: [https://teranga.example.sn] # the only sites where the widget shows
theme: {primary: "#C8412B", secondary: "#F6EFE4", font: manrope}
brand_label: Teranga # and the labels, the avatar, the suggested prompts
site: {...} # the demo site's copy
pitch: {...} # the presentation page

mcp: {...} # the MCP server's name and instructions
keyeffect
agent.persona, tone, emojihow the agent introduces itself, on every door. persona and tone are required
agent.namethe agent's name, if the tenant gives it one; no surface shows it today
agent.modelthe model the agent runs on; gemini-2.5-flash by default
agent.rulesinstructions copied as they are, on every door: the widget as well as Claude or ChatGPT. Write them in the station's language, and name the station's skills, not a tool it does not expose.
agent.portals.web.widget.originsthe only sites where the widget can show, as origins (https://host[:port]). A value that is not an origin (a bare host, a path, *) is refused at load time. Without it, the widget shows on any site
agent.portals.web.widget.themethe colours (primary, secondary, accent_gradient) and the typeface (font: inter, jakarta, manrope, geist, dmsans; manrope by default). The colours go to the widget, the PWA and the MCP frames; the typeface to the widget only (the frames keep the host's). A colour that is not #rgb or #rrggbb, a typeface outside the list: refused at load
agent.portals.web.widget (the rest)the widget's words: brand_label, avatar_initial, avatar_url, fallback_title, empty_state_text, suggested_prompts; labels replaces Convoy texts
agent.portals.web.site, pitchthe copy of the demo site; pitch has only meeting_url (read by the MCP frames) and headline, headline_accent (the site's title when site gives none)
mcpthe MCP server's name; collection_name_override chooses the catalogue collection

An item's link to its page on the tenant's site is not a key of the portal: it is the role: link field of the skill that presents the item (Skills).

Today, the agent has three portals: the widget on the tenant's site, the PWA, and the Chrome extension. The others (Teams, Slack, WhatsApp) and proof of who is speaking come with the target (Agent & portals).

Instructions are not guards

A rule in agent.rules guides the agent; it does not prevent anything. Everything that must be guaranteed — a required address, a confirmation before ordering — is written in a select guard or in the submit guard, which Core applies whatever the model says.