How to Route New Front Conversations into Klaviyo Lists by Topic
When a new conversation lands in Front, Spojit classifies it into an interest topic with an AI step, then creates or updates the contact as a Klaviyo profile and adds it to the matching Klaviyo list.
What This Integration Does
Customer messages arrive in Front with no clean structure: someone asks about wholesale pricing, another wants a product back in stock, a third is chasing a delivery. This workflow reads each new conversation, has the agent decide which interest topic it belongs to, and then drops the contact into the right Klaviyo list. The result is that your marketing segments stay populated automatically from real inbound intent, instead of someone manually tagging conversations and copying email addresses into Klaviyo each day.
The run model is event-driven. Front posts to a Webhook trigger the moment a conversation is created, so the workflow fires within seconds. The trigger payload identifies the conversation; a Connector node fetches the full conversation and contact details, an Agent mode step classifies the topic into a fixed set of values, and two more Connector steps write to Klaviyo. The workflow leaves behind one Klaviyo profile (created or matched by email) attached to one list. Re-runs are safe: Klaviyo treats create-profile by email as an upsert, and add-profiles-to-list on a profile already in a list is a no-op, so a duplicate webhook delivery does not create duplicate contacts.
Prerequisites
- A Front connection (API key) added under Connections, with access to the inbox you want to watch. See the Front connector reference.
- A Klaviyo connection (API key) with permission to read lists and write profiles. See the Klaviyo connector reference.
- A signing connection for the webhook (scheme Custom works for Front). See Setting Up a Webhook Connection.
- The Klaviyo lists you want to route into already created in Klaviyo, plus a mapping of each topic value to its list ID (for example
wholesale,back-in-stock,general).
Step 1: Add a Webhook trigger for new Front conversations
Start a new workflow and set the trigger to Webhook. Spojit gives you a unique URL and returns 202 with an executionId to the caller. Select your signing connection so deliveries are verified by HMAC, then copy the URL into Front under your inbox's rules or app settings as the destination for a "conversation created" event. The parsed JSON body is available downstream as {{ input }}. Front's payload nests the conversation under the event, so the conversation identifier is typically at {{ input.conversation.id }} (confirm the exact path from a real delivery in the run logs).
If you would rather not rely on Front rules to send only new conversations, you can still subscribe broadly and add a Condition node later to drop event types you do not want.
Step 2: Fetch the full conversation from Front
Add a Connector node in Direct mode using the Front connector and the get-conversation tool. Map its conversation ID input to {{ input.conversation.id }}. This returns the subject, the latest message text, and the recipient handle so the AI step has real content to classify rather than just an ID. Store the output as conversation.
The conversation references a contact handle (usually an email address). If the email is not present on the conversation result, add a second Connector node with the Front get-contact tool to resolve the contact's email and name, and store it as contact. Use whichever of these gives you a reliable email value to send to Klaviyo.
Step 3: Classify the conversation into a topic with an Agent step
Add a Connector node in Agent mode. This is where the Agent-mode Connector node reads the message and decides the interest topic. In the prompt, paste the subject and body and instruct it to choose exactly one value from your fixed list. Turn on the Response Schema so the output is reliable JSON rather than prose. A workable prompt:
Classify this customer message into one interest topic.
Allowed topics: wholesale, back-in-stock, support, general.
Subject: {{ conversation.subject }}
Message: {{ conversation.last_message.text }}
Return only the topic and a one-line reason.
Set the Response Schema so the step always returns the same shape:
{
"type": "object",
"properties": {
"topic": { "type": "string", "enum": ["wholesale", "back-in-stock", "support", "general"] },
"reason": { "type": "string" }
},
"required": ["topic"]
}
Store the output as classification. Downstream you read the chosen value as {{ classification.topic }}. The enum guarantees the value matches one of your Klaviyo lists, which is what keeps the next steps deterministic. For more on this pattern, see How to Use Structured Output for Reliable AI Data Extraction and How to Choose Between Agent Mode and Direct Mode.
Step 4: Map the topic to a Klaviyo list ID
Add a Transform node to turn the topic string into the Klaviyo list ID you will add the profile to. Build a small lookup keyed on {{ classification.topic }} and emit the corresponding list ID, with a fallback to your general list so nothing is dropped:
{
"listId": {
"wholesale": "ListIdWholesale",
"back-in-stock": "ListIdBackInStock",
"support": "ListIdSupport",
"general": "ListIdGeneral"
}["{{ classification.topic }}"] || "ListIdGeneral"
}
Store the output as routing so the list ID is available as {{ routing.listId }}. If you prefer not to hard-code IDs, run a one-off Connector node with the Klaviyo list-lists tool to read each list's ID by name, then paste those values into your Transform mapping.
Step 5: Create or update the Klaviyo profile
Add a Connector node in Direct mode using the Klaviyo connector and the create-profile tool. Map the email to the contact's address (for example {{ contact.email }} or the handle from the conversation) and pass the name if you have it. Klaviyo matches on email, so this both creates new profiles and updates existing ones; store the output as profile to capture the profile ID. You can also store the classification reason as a custom profile property so your marketing team can see why the contact was routed.
If you only ever expect existing customers, you can swap to get-profile first and branch with a Condition, but create-profile by email is the simpler upsert and is safe to re-run.
Step 6: Add the profile to the matching list
Add a final Connector node in Direct mode using the Klaviyo add-profiles-to-list tool. Map the list input to {{ routing.listId }} and the profiles input to the ID returned by the previous step, {{ profile.id }} (most Klaviyo APIs accept an array, so pass ["{{ profile.id }}"] if the field expects a list). On success, the contact now sits in the topic-specific list and any Klaviyo flow attached to that list takes over from there.
Optionally add a Connector node with the Front add-tag tool to tag the original conversation with the topic, giving your support agents the same classification inside Front. You can also add a Send Email node to notify your marketing inbox when a high-value topic such as wholesale comes in.
Tips
- Keep the topic
enumin the Response Schema and the keys in your Transform mapping identical. If they drift, a valid AI answer can fall through to the general list silently. - Use Direct mode for every Klaviyo and Front write so those calls cost no AI credits; reserve Agent mode for the single classification step that genuinely needs judgment.
- Ask Miraxa to scaffold the skeleton for you, for example: "Add a Klaviyo Connector node in Direct mode using add-profiles-to-list and connect it after the create-profile node." Then fine-tune the field mappings in the properties panel.
- Store the classification
reasonas a Klaviyo profile property so a human can audit why each contact landed in a given list.
Common Pitfalls
- Wrong payload path. Front nests data differently per event type. Inspect a real delivery in the execution logs and confirm where the conversation ID and contact email actually live before wiring
{{ input }}references. - Missing email. A conversation can arrive before a contact email is resolved. If
create-profilehas no email it cannot upsert reliably; add the Frontget-contactstep or a Condition to skip records with no usable address. - Webhook replays. Front may resend an event. Because both Klaviyo steps are idempotent by email this is usually harmless, but if you also send notifications, guard those with a Condition to avoid duplicate alerts.
- List ID versus list name.
add-profiles-to-listexpects the list ID, not its display name. Pull IDs once withlist-listsand store them in your Transform mapping.
Testing
Before pointing live Front traffic at the workflow, test on a small scope. Send one real test conversation into your Front inbox from an address you control, or replay a captured payload, and watch the run in the execution logs. Confirm the get-conversation output has the expected subject and body, that {{ classification.topic }} is one of your allowed values, and that the Transform produced the correct {{ routing.listId }}. Check in Klaviyo that exactly one profile was created or updated and added to the right list. Run the same payload a second time to verify no duplicate profile appears, then enable the workflow.