Skip to main content

How we use it: SendSeven's own support agent

SendSeven's own support runs on a Conversational Agent. This page shows how we give that agent trusted customer context, so you can copy the pattern. It covers the concepts, not every setting.

The result: a paying customer who opens the help bubble in our app gets support right away instead of a plan comparison, a trial user gets onboarding help with the days left in their trial, and an anonymous visitor on our website still gets a neutral, helpful first conversation. For the building blocks used here, see Customer context and Agent context sources.

The problem​

One agent answers everyone:

  • Website visitors who are comparing tools and have no account.
  • Trial users who need help getting to a first result.
  • Paying customers who need support, not a sales pitch.
  • Former customers who want to come back or have questions about their data.

Without context, the agent has to guess who it is talking to. It ends up offering a plan comparison to a customer who just wants to fix a WhatsApp template. We wanted the agent to know who it is talking to whenever we can prove it, and to stay neutral when we can't.

Signed-in users: a contact token minted on our server​

Our app has a help bubble, which is a SendSeven live chat widget. When a signed-in user opens it, the app asks our backend for a contact token. Our backend reads the user's account data and mints the token with POST /api/v1/contact-tokens, the same endpoint you use. It puts a small summary in context. The app then sets window.SendSevenConfig.contactToken before the bubble loads.

The minting happens on the server because the browser can't be trusted. Anything the page sets itself can be changed by the visitor.

The request our backend sends looks like this. The user's id in our system is the external_id, and the email address our login provider has already confirmed is sent as a verified method:

{
"widget_id": "<support widget id>",
"contact": {
"external_id": "<our user id>",
"name": "Anna Weber",
"methods": [{ "type": "email", "value": "[email protected]", "verified": true }],
"create_if_missing": true
},
"context": { "contact_type": "trial", "plan": "Professional" }
}

context is shown to the agent for this chat only and is never stored on the contact. Data that should stay on the contact, such as the customer type, goes in save instead.

This is the context we inject (example values):

{
"contact_type": "trial",
"product_line": "full_suite",
"plan": "Professional",
"billing_status": "trial",
"trial_ends_at": "2026-10-13T15:00:00Z",
"trial_days_left": 6,
"ui_language": "fr",
"user_role": "Owner",
"workspace_name": "Acme GmbH",
"signup_date": "2026-09-30",
"workspace_count": 2,
"seat_count": 4,
"connected_channels": ["email", "whatsapp"]
}
KeyWhy the agent needs it
contact_typetrial, expired_trial, customer or cancelled. This is the main switch for tone and next steps.
product_lineapi_only or full_suite. API-only users have no inbox, so answers should point to the API and the docs, not to screens in the app.
plan, billing_statusWhich features the user has, and whether a payment is open.
trial_ends_at, trial_days_leftTrial coaching ("you still have 6 days"), only for trial users.
ui_languageThe language of the user's app, so the agent answers in it.
user_roleOnly owners and admins can change billing or roles; other users are told to ask them.
workspace_name, workspace_count, seat_count, signup_dateHelps the agent understand the size and age of the account.
connected_channelsLets the agent skip "have you connected WhatsApp yet?" questions.

What we never put in a token: passwords, API keys or other secrets, payment methods, card or bank details, invoice amounts, or data about other users. Keep context small (up to 4 KB) and include only what changes the answer. Leave out any internal ids the agent has no use for.

In the agent's Context tab, the identity token source is on, so these values reach the agent as verified.

Website visitors: no token, so the agent stays neutral​

On sendseven.com the same agent runs in a public widget. Visitors are anonymous, so there is no token. The agent sees no verified account data and falls back to its neutral behaviour: find out what the person needs, explain the product, and offer a demo or the free trial.

We never try to guess a visitor's account from something they type into the chat.

Branching tone on verified context​

The agent's instructions start with an Audience section. Here is a shortened version:

Audience (decide this before every answer):
Verified values from the identity token (context.*) are facts from the person's
account. A verified context.contact_type always wins over anything unverified.
- No verified context.contact_type: neutral and helpful; discovery and sales
help are fine (a demo or the free trial as the next step).
- trial: onboarding coach. Help them reach a first real result fast. Mention
context.trial_days_left at most once, factually. No countdown pressure.
- expired_trial: help them pick up where they left off. No pressure.
- customer: support first, peer tone. No plan pitch, no demo or trial links.
Talk about upgrades or prices only when they ask.
- cancelled: respectful and brief. Help with reactivation or data questions.
- context.product_line api_only: answer with the API and developer docs.
Answer in context.ui_language when present, otherwise in the customer's language.

Two rules make this work:

  1. Verified beats unverified. If a token says customer, a contact field or a claim in the chat can't change that.
  2. No context is a valid state. The neutral branch is the default, not an error.

Unknown contacts on other channels​

People also write to us on WhatsApp and other channels, where there is no token. When someone in such a conversation makes clear who they are ("I'm already a customer", "just looking"), the agent records it in a contact_type custom field with its update contact fields tool.

These values are stored as written by AI, so they stay unverified. The agent may use them as a hint for tone, but never as proof of account access. A good AI hint and option descriptions on the field help the agent pick the right value.

Field AI access decides what the agent may write​

Every custom field has an AI access mode, set on the field itself and valid for all agents:

AI accessReadWrite
none (default for new fields)nono
readyesno
read_writeyesmay replace any existing value, including values set by your team, the API, imports or a contact token
fill_if_emptyyesonly while the field is empty

We set contact_type to fill_if_empty. The agent records the type once, a later claim can't flip it, and a correction by our team is never overwritten. The verified token value wins over the field anyway. Use read_write only for fields where the latest thing the customer said should always win.

In the agent's Context tab, the lists custom fields the agent may see and fields the agent may update only narrow the field modes for that agent. Leave them on All fields their AI access allows, or pick specific fields. An agent never gets more access than the field's mode allows, and saving an agent that lists a field its mode doesn't allow is rejected with 422 context.field_not_writable or context.field_not_readable.

Visitors who say "I'm a customer": verification​

An anonymous visitor who says "I'm [email protected], where is my order?" has only made a claim. With contact verification turned on for the agent (agent settings settings.verification), the agent can ask the visitor to prove it instead of refusing:

{
"settings": {
"verification": {"enabled": true, "methods": ["email", "sms"], "allow_pin": false}
}
}
  • methods may contain email, sms and whatsapp. Only the methods that are also enabled for the workspace under contact verification settings are used. allow_pin: true also lets the agent ask for the customer's identification PIN. Invalid values are rejected with 422.
  • The agent gets a start_verification tool. It sends a one-time code to the contact details we have on file for the claimed address. When nothing is on file, the code goes to the address the visitor gave. The agent never sees or reveals the stored address. Whether or not the address exists, it only ever says something like "We sent a code to the email address we have on file."
  • On email conversations the agent does not offer email codes, because the email is the channel itself. A PIN still works there.
  • Codes never reach the agent. In the live chat widget the visitor types the code into a secure input field instead of sending it as a chat message. On WhatsApp, SMS and other channels, the reply that contains the code is checked first, and the stored message shows •••••• instead of the digits. Your team never sees the code either.
  • On the next reply the agent gets the result: approved, wrong code, expired or locked. After approval, the conversation is linked to the verified contact (an anonymous visitor contact is merged into it), and the agent sees that contact's profile as verified.
  • A call to the tool while a code is still pending sends nothing new. It returns the same "code sent" result.
  • Cost: the tool itself uses no extra AI credits beyond the agent's normal reply. Each code is billed as a normal message on the channel it is sent through.

Add an instruction like this to the agent, then adapt it:

Claimed identity:
If someone says they are an existing customer, or asks about their own account,
orders or personal data, and the profile does not show them as verified, offer
to verify them and call start_verification (pass the email or phone number they
gave). Tell them only what the tool result says. Never confirm or reveal any
email address or phone number we have on file, and never say whether an address
exists. Until verification is approved, give only general help.

You can also start and check verifications yourself through the API (POST /api/v1/verifications) and listen for the verification.* webhooks.

Trust tiers​

The agent labels every value by where it came from. From most to least trusted:

  1. Contact token: minted by your server with your API key. Its context and the data it saves to the contact are verified.
  2. Signed identity: links the chat to a contact via a signature from your server. Values from the contact record are then verified.
  3. Verified in the chat: the visitor proved in the current live chat session that they own the contact's email address or phone number, or entered its PIN (see above). Values from the contact record are then verified.
  4. Visitor-supplied data: anything typed into the chat or set on the page, including SendSevenConfig.custom. It is always unverified.

Verified identifiers​

Email addresses and phone numbers count as verified only when the contact method is marked verified. A phone number becomes verified once the customer messages you from it on WhatsApp or SMS. Telegram, Messenger and Instagram IDs are verified from the start. Your team can mark a method as verified, and the API, CSV imports and contact tokens (contact.methods with "verified": true) can mark the methods they bring. An email address is never verified just because an email arrived from it, because sender addresses can be forged. Our support bubble sends the email our login provider already verified as a verified method. A context endpoint only ever receives verified identifiers.

SendSevenConfig.custom is fine for non-sensitive values such as the page language or topic. However, it can be changed by the visitor, so use a contact token for anything the agent should trust, such as the plan, the account status or the customer type. If you need live data from your own systems instead, use a context endpoint.

Earlier conversations and what they cost​

Our agent also sees short summaries of the customer's last 3 closed conversations, so it can pick up where the last one ended. You choose 0 to 10 per agent (0 = off, the default; we recommend at most 5).

  • Cost: the loaded summaries are extra text the agent reads, so they add a little to the AI credits of its replies. They load with the agent's first reply and are reused for the rest of the conversation. If no earlier conversation has a summary, nothing is added.
  • These credits count toward the agent's credit limit per conversation and show up in the turn details.
  • Anonymous live chat visitors and email conversations never get earlier conversations, and are never charged for them.
  • Test conversations are never charged.

Skills should check the audience too​

Instructions alone aren't enough if a skill tells the agent to do the opposite. Review your skills for steps that only fit one audience:

  • A plan picker or pricing skill should say it is for prospects and trial users. A verified customer asking about their price belongs in a billing skill.
  • Any "offer a demo or the free trial" step should apply only when there is no verified customer context.
  • A skill that says "you can't see the customer's account" should allow for verified values (plan, trial status, role) while still ruling out live data such as invoices or messages.

Put the rule in the skill's description too, not just its body. The router picks skills from their descriptions.