How to build Customer Support automation with bem in 2 Hours
Embed multichannel support (Slack, email, web) into your product — no off-the-shelf systems needed
Off-the-shelf support platforms were built for 2010. They're bloated, hard to customize, and sit next to your product instead of inside it.
But what if you could build the exact support system your users need, fully integrated into your UI, Slack workspace, or even an internal dashboard, in two hours?
With bem and a few modern tools (like Supabase and Slack APIs), you can.
This post walks you through a real implementation of an AI-powered, schema-driven support system, from message parsing to triage to ticket assignment, powered by bem’s API.
Let’s build.
The Plan: Invisible Support Infrastructure
We’ll set up a custom support system that handles inbound questions from:
📬 Email (e.g. support@yourcompany.com)
💬 Slack (e.g. internal #customer-help channel)
🧑💻 Web app (feedback or help forms)
The system will:
Parse inbound support messages (no template needed)
Classify by type (bug, feature request, billing issue, etc.)
Extract key metadata (e.g. user ID, timestamp, urgency)
Hydrate data from your DB (e.g. pull user plan from Supabase)
Route to the right person/team
Post or email an internal summary with all the context included
And optionally: automatically log it in your CRM or issue tracker
Step 1: Define Your Support Schema
Start by defining the structure of a support intake. Here's a sample schema we’ll use in bem:
{
"type": "object",
"required": ["type", "description", "userID", "timestamp"],
"properties": {
"type": {
"type": "string",
"description": "Category of the support request",
"enum": ["bug", "feature_request", "billing", "other"]
},
"description": {
"type": "string",
"description": "User's original message or summary of the request"
},
"userID": {
"type": "string",
"description": "Unique user ID from your internal system"
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "Time the support request was received"
},
"urgency": {
"type": "string",
"enum": ["low", "medium", "high"],
"description": "Estimated urgency based on language analysis"
}
}
}
Step 2: Create a Pipeline in bem
Use the POST /v1-beta/pipelines
endpoint to create a transformation pipeline with this schema.
POST /v1-beta/pipelines
{
"name": "Support Intake Pipeline",
"outputSchemaName": "Support Intake",
"outputSchema": { ... } // insert the schema from above
}
You’ll receive a pipeline ID and a unique email address like:
eml_xxxxxx@pipeline.bem.ai
Anything you forward to this email gets parsed and transformed in real-time.
Step 3: Set Up Routing Logic
Now let’s build a router to handle classification and dispatch.
Create a router config using POST /v1-alpha/action-type-configs
with a few simple rules:
{
"actionType": "route",
"name": "Support Router",
"description": "Routes support tickets by type",
"routes": [
{
"name": "Bug Reports",
"regex": {
"patterns": ["crash", "error", "broken", "not working"]
},
"actionTypeConfigID": "<pipeline_id_for_bug_support>"
},
{
"name": "Billing",
"regex": {
"patterns": ["invoice", "payment", "charge", "receipt"]
},
"actionTypeConfigID": "<pipeline_id_for_billing>"
},
{
"name": "General",
"regex": {
"patterns": []
},
"actionTypeConfigID": "<pipeline_id_for_general_support>"
}
]
}
Connect this router to a shared email inbox or webhook endpoint.
Step 4: Hydrate Data from Supabase (or other data providers)
Now that we’ve extracted userID
, we want to enrich the ticket with more info — like plan tier, team size, usage, etc.
Spin up a basic Supabase function:
create function get_user_info(uuid text)
returns table (
user_id text,
email text,
plan text,
usage jsonb
)
language sql
as $$
select id, email, plan, usage
from users
where id = uuid;
$$;
Call this function from your backend or workflow orchestrator when a new support event is transformed.
There’s a million ways of doing this; optionally, use Chroma or Weaviate to do semantic search over the extracted data to match and hydrate with your own.
We’re releasing Data Hydration as a first-class feature in bem this quarter, so very soon you won’t even need to do this!
Step 5: Notify the Right Team
After hydration, use bem’s email action type to notify your team with enriched support data.
Create an email config:
{
"actionType": "email",
"name": "Send to Ops",
"fromEmail": "support@yourcompany.com",
"fromName": "Support Bot",
"toEmail": "ops@yourcompany.com",
"toName": "Support Team",
"subject": "New Support Request - {{type}} from {{userID}}",
"body": "<p>Urgency: {{urgency}}</p><p>{{description}}</p>"
}
Use POST /v1-alpha/actions
to trigger the message.
Optional: Log It to Your Internal Tools
Want to push this to:
Notion?
Linear?
Salesforce?
Zendesk (ironically)?
Just use the transformed output from bem to call their API in your workflow system (like n8n, Make, or plain Node.js).
Business ROI
Why not just use Intercom or Zendesk?
Because:
Your ops and support teams want precision and context, not another tab
You want to own your workflows and UI
Most SaaS support systems cost $10–100 per agent/month, and offer zero extensibility
In 2 Hours You Just Built:
A real-time, multi-channel intake system
AI-based triage and routing
DB-powered ticket enrichment
Internal team alerts
Optional CRM logging
All custom, all yours, and all extendable with a single API.
Bonus: Auto-Learn from Corrections
Your team edits a support tag? Just use the PATCH /v1-beta/transformations
endpoint to fine-tune future extractions.
You're not building a static system — you're building infrastructure that learns.
Build It Yourself
Want to see this live? Schedule a demo or ping our team. We can help you launch a production-grade support system — customized to your org — in less than a day.
This is what support looks like when it’s invisible, embedded, and built for your product.