How to integrate Klaviyo MCP with CrewAI

Framework Integration Gradient
Klaviyo Logo
CrewAI Logo
divider

Introduction

This guide walks you through connecting Klaviyo to CrewAI using the Composio tool router. By the end, you'll have a working Klaviyo agent that can add new subscribers to main email list, clone last week's campaign for reuse, estimate recipients for upcoming product launch, create back-in-stock alerts for a product through natural language commands.

This guide will help you understand how to give your CrewAI agent real control over a Klaviyo account through Composio's Klaviyo MCP server.

Before we dive in, let's take a quick look at the key ideas and tools involved.

TL;DR

Here's what you'll learn:
  • Get a Composio API key and configure your Klaviyo connection
  • Set up CrewAI with an MCP enabled agent
  • Create a Tool Router session or standalone MCP server for Klaviyo
  • Build a conversational loop where your agent can execute Klaviyo operations

What is CrewAI?

CrewAI is a powerful framework for building multi-agent AI systems. It provides primitives for defining agents with specific roles, creating tasks, and orchestrating workflows through crews.

Key features include:

  • Agent Roles: Define specialized agents with specific goals and backstories
  • Task Management: Create tasks with clear descriptions and expected outputs
  • Crew Orchestration: Combine agents and tasks into collaborative workflows
  • MCP Integration: Connect to external tools through Model Context Protocol

What is the Klaviyo MCP server, and what's possible with it?

The Klaviyo MCP server is an implementation of the Model Context Protocol that connects your AI agent and assistants like Claude, Cursor, etc directly to your Klaviyo account. It provides structured and secure access to your marketing campaigns, contact lists, and automation features, so your agent can perform actions like creating campaigns, managing subscribers, sending messages, and analyzing engagement—all on your behalf.

  • Automated campaign creation and sending: Instantly have your agent create new marketing campaigns, clone existing ones, and trigger campaign sends to targeted audiences.
  • Subscriber and list management: Add or update profiles in specific Klaviyo lists, subscribe contacts to marketing lists, and ensure your audience is always up to date.
  • Event and engagement tracking: Automatically record customer activities or bulk-create profile events to power segmentation and analytics.
  • Catalog and back-in-stock automation: Let your agent create product catalog categories, manage restock alerts, and help drive timely customer notifications about inventory.
  • Campaign recipient estimation and analytics: Start background jobs to estimate campaign reach and analyze how many recipients meet your targeting criteria before a send.

Supported Tools & Triggers

Tools
Add Profile to ListAdd profiles to a klaviyo list by profile ids or email addresses.
Assign campaign message templateCreates a non-reusable version of the template and assigns it to the message.
Bulk create client eventsUse the client-side endpoint with a public api key to track profile activity.
Bulk create eventsThis api endpoint creates or updates profiles by batching up to 1,000 events, with a 5mb payload limit.
Create back in stock subscriptionUse the server-side endpoint to subscribe to restock alerts, following the back in stock api guide.
Create campaignCreates a campaign given a set of parameters, then returns it.
Create campaign cloneClones an existing campaign, returning a new campaign based on the original with a new id and name.
Create Campaign Recipient Estimation JobStart an asynchronous task to estimate the number of recipients for a campaign.
Create campaign send jobTrigger a campaign to send asynchronously*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:write`
Create catalog categoryCreate a new catalog category.
Create catalog category relationships itemsCreate a new item relationship for the given category id.
Create catalog itemCreate a new catalog item.
Create catalog item relationships categoriesCreate a new catalog category relationship for the given item id.
Create catalog variantCreate a new variant for a related catalog item.
Create client back in stock subscriptionUse the endpoint for client-side back in stock notifications with a public api key.
Create client eventCreate client-side events to track profiles using a public api key, not for updating identifiers (server-side only).
Create client subscriptionEndpoint manages email/sms opt-ins using consent and requires public api key for client use.
Create couponCreates a new coupon.
Create coupon codeSynchronously creates a coupon code for the given coupon.
Create eventCreate or update a profile event with minimum identifiers and metric name.
Create listCreate a new list.
Create or update client profileUpdate user profiles without tracking using a public client-side api; use a private server-side api for identifier changes.
Create or update client push tokenThis endpoint for mobile sdks (ios & android) creates/updates push tokens using a public api key.
Create or Update ProfileCreate or update a profile in klaviyo with the given attributes.
Create or update push tokenMigrate or create push tokens with klaviyo's endpoint, utilizing their mobile sdks for ios & android.
Create profileCreate a new profile.
Create segmentCreate a segment.
Create tagSummary: instructions on creating a tag within an account's designated tag group with a maximum of 500 tags, with optional tag group specification.
Create tag groupCreate tag groups up to 50 per account, defaulting to non-exclusive unless specified.
Create tag relationships campaignsSummary: link a tag to campaigns, ensuring a limit of 100 tags per campaign.
Create tag relationships flowsAssign tags to flows using their ids in the request body, ensuring a flow is not linked to over 100 tags.
Create tag relationships listsSummary: a tag can be added to one or more lists, with a max of 100 tags per list.
Create tag relationships segmentsSummary: set tag associations with segments using the request body, limited to one tag per segment and up to 100 tags per segment.
Create templateSummary: custom html templates can be created unless an account reaches 1,000 template limit.
Create template cloneClone a template by its id, but cloning fails if account has 1,000+ templates.
Create template renderRender an email template with specific context and sparse fieldsets, then get html/plain text.
Create webhookCreate a new webhook*rate limits*:burst: `1/s`steady: `15/m` **scopes:** `webhooks:write`
Delete campaignDelete a campaign with the given campaign id.
Delete catalog categoryDelete a catalog category using the given category id.
Delete catalog category relationships itemsDelete item relationships for the given category id.
Delete catalog itemDelete a catalog item with the given item id.
Delete catalog item relationships categoriesDelete catalog category relationships for the given item id.
Delete catalog variantDelete a catalog item variant with the given variant id.
Delete couponDelete the coupon with the given coupon id.
Delete coupon codeDeletes a coupon code specified by the given identifier synchronously.
Delete flowDelete a flow with the given flow id.
Delete listDelete a list with the given list id.
Delete segmentDelete a segment with the given segment id.
Delete tagDelete the tag with the given tag id.
Delete tag groupDelete a specified tag group and its contents; associated resource links will be removed.
Delete tag relationships campaignsDisconnect a tag from campaigns using the campaign id(s) in the request body.
Delete tag relationships flowsRemove a tag's association with one or more flows.
Delete tag relationships listsRemove a tag's association with one or more lists.
Delete tag relationships segmentsUse the request body to de-associate a tag from specified segment ids.
Delete templateDelete a template with the given template id.
Delete webhookDelete a webhook with the given id.
Get accountRetrieve a single account object by its account id.
Get accountsUse a private api key to fetch an associated account's details like contact info, timezone, and currency, as well as validate the key.
Get bulk profile import jobGet a bulk profile import job with the given job id.
Get bulk profile import job errorsGet import errors for the bulk profile import job with the given id.
Get bulk profile import job listsGet list for the bulk profile import job with the given id.
Get bulk profile import job profilesGet profiles for the bulk profile import job with the given id.
Get bulk profile import job relationships listsGet list relationship for the bulk profile import job with the given id.
Get bulk profile import job relationships profilesGet profile relationships for the bulk profile import job with the given id.
Get bulk profile import jobsGet all bulk profile import jobs.
Get CampaignRetrieve a specific campaign by its id from klaviyo.
Get campaign campaign messagesReturn all messages that belong to the given campaign.
Get campaign messageReturns a specific message based on a required id.
Get campaign message campaignReturn the related campaign*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:read`
Get campaign message relationships campaignReturns the id of the related campaign*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:read`
Get campaign message relationships templateReturns the id of the related template*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:read` `templates:read`
Get campaign message templateReturn the related template*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:read` `templates:read`
Get campaign recipient estimationGet estimated recipients for a given campaign id using `create campaign recipient estimation job`.
Get campaign recipient estimation jobRetrieve the status of a recipient estimation job triggered with the `create campaign recipient estimation job` endpoint.
Get campaign relationships campaign messagesReturns the ids of all messages associated with the given campaign.
Get campaign relationships tagsReturns the ids of all tags associated with the given campaign.
Get CampaignsRetrieve campaigns from your klaviyo account.
Get campaign send jobGet a campaign send job*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:read`
Get campaign tagsReturn all tags that belong to the given campaign.
Get catalog categoriesRetrieve up to 100 account catalog categories, sortable by creation date.
Get catalog categoryGet a catalog category with the given category id.
Get catalog category itemsRetrieve up to 100 sorted items per request from a category using the category id.
Get catalog category relationships itemsGet all items in the given category id.
Get catalog itemGet a specific catalog item with the given item id.
Get catalog item categoriesRetrieve the catalog categories for an item by id, sorted by 'created' date, with a 100-category maximum per request.
Get catalog item relationships categoriesGet all catalog categories that a particular item is in.
Get catalog itemsRetrieve up to 100 sorted catalog items per account, with `$custom` integration and `$default` type.
Get catalog item variantsRetrieve up to 100 variants per request for a specific item id, sortable by creation date.
Get catalog variantGet a catalog item variant with the given variant id.
Get catalog variantsRetrieve up to 100 account variants per request, sortable by creation date.
Get couponGet a specific coupon with the given coupon id.
Get coupon codeReturns a coupon code specified by the given identifier.
Get coupon code bulk create jobGet a coupon code bulk create job with the given job id.
Get coupon code bulk create jobsGet all coupon code bulk create jobs.
Get coupon code relationships couponGets a list of coupon code relationships associated with the given coupon id*rate limits*:burst: `75/s`steady: `700/m` **scopes:** `coupon-codes:read`
Get coupon codesObtains coupon codes using necessary coupon or profile filters.
Get coupon codes for couponGets a list of coupon codes associated with the given coupon id*rate limits*:burst: `75/s`steady: `700/m` **scopes:** `coupon-codes:read`
Get coupon for coupon codeGet the coupon associated with a given coupon code id.
Get coupon relationships coupon codesGets the coupon relationship associated with the given coupon code id*rate limits*:burst: `75/s`steady: `700/m` **scopes:** `coupons:read`
Get couponsGet all coupons in an account.
Get create categories jobGet a catalog category bulk create job with the given job id.
Get create categories jobsGet all catalog category bulk create jobs.
Get create items jobGet a catalog item bulk create job with the given job id.
Get create items jobsGet all catalog item bulk create jobs.
Get create variants jobGet a catalog variant bulk create job with the given job id.
Get create variants jobsGet all catalog variant bulk create jobs.
Get delete categories jobGet a catalog category bulk delete job with the given job id.
Get delete categories jobsGet all catalog category bulk delete jobs.
Get delete items jobGet a catalog item bulk delete job with the given job id.
Get delete items jobsGet all catalog item bulk delete jobs.
Get delete variants jobGet a catalog variant bulk delete job with the given job id.
Get delete variants jobsGet all catalog variant bulk delete jobs.
Get eventGet an event with the given event id.
Get event metricGet the metric for an event with the given event id.
Get event profileGet the profile associated with an event with the given event id.
Get event relationships metricGet a list of related metrics for an event*rate limits*:burst: `350/s`steady: `3500/m` **scopes:** `events:read` `metrics:read`
Get event relationships profileGet profile [relationships](https://developers.
Get eventsGet all events in an account requests can be sorted by the following fields: `datetime`, `timestamp` returns a maximum of 200 events per page.
Get flowGet a flow with the given flow id.
Get flow actionGet a flow action from a flow with the given flow action id.
Get flow action for messageGet the flow action for a flow message with the given message id.
Get flow action messagesRetrieve up to 50 flow messages per request by action id, sortable by various fields, with ascending/descending options, and paginated using `page[size]` and `page[number]`.
Get flow action relationships flowGet the flow associated with the given action id.
Get flow action relationships messagesRetrieves up to 50 flow message relationships per request for a specified flow action id, with cursor pagination.
Get flow flow actionsGet all flow actions associated with the given flow id.
Get flow for flow actionGet the flow associated with the given action id.
Get flow messageGet the flow message of a flow with the given message id.
Get flow message relationships actionGet the [relationship](https://developers.
Get flow message relationships templateReturns the id of the related template*rate limits*:burst: `3/s`steady: `60/m` **scopes:** `templates:read`
Get flow message templateReturn the related template*rate limits*:burst: `3/s`steady: `60/m` **scopes:** `templates:read`
Get flow relationships flow actionsRetrieve all flow action relationships for a specific flow id, sortable by `id`, `status`, `created`, `updated`.
Get flow relationships tagsReturn the tag ids of all tags associated with the given flow.
Get flowsGet all flows in an account.
Get flow tagsReturn all tags associated with the given flow id.
Get formGet the form with the given id.
Get form for form versionGet the form associated with the given form version.
Get form id for form versionGet the id of the form associated with the given form version.
Get formsGet all forms in an account.
Get form versionGet the form version with the given id.
Get imageGet the image with the given image id.
Get imagesGet all images in an account.
Get listApi allows 75 req/sec and 700 req/min, but with 'profile count' param, it's 1 req/sec and 15 req/min.
Get list profilesRetrieve profiles in a list by id, filterable by email/phone/push token/join date, sortable by join date.
Get list relationships profilesGet profile membership [relationships](https://developers.
Get list relationships tagsReturns the tag ids of all tags associated with the given list.
Get ListsRetrieve marketing lists from your klaviyo account.
Get list tagsReturn all tags associated with the given list id.
Get metricGet a metric with the given metric id.
Get metricsGet all metrics in an account.
Get profileGet the profile with the given profile id.
Get profile listsGet list memberships for a profile with the given profile id.
Get profile relationships listsGet list memberships for a profile with the given profile id.
Get profile relationships segmentsGet segment membership relationships for a profile with the given profile id.
Get ProfilesRetrieve profiles from your klaviyo account.
Get profile segmentsGet segment memberships for a profile with the given profile id.
Get segmentFetch a segment by id with default rates of 75/s and 700/m, or with `additional-fields` at 1/s and 15/m.
Get segment profilesRetrieve profiles in a segment by id, filtering by email, phone, token, or join date, and sorting by join date.
Get segment relationships profilesGet all profile membership [relationships](https://developers.
Get segment relationships tagsIf `related resource` is `tags`, returns the tag ids of all tags associated with the given segment id.
Get segmentsFetch segments from an account with filters like `name`, `created`, and `updated`.
Get segment tagsReturn all tags associated with the given segment id.
Get tagRetrieve the tag with the given tag id.
Get tag groupRetrieve the tag group with the given tag group id.
Get tag group relationships tagsReturns the tag ids of all tags inside the given tag group.
Get tag groupsRetrieve up to 25 tag groups per account, sortable/filterable by specific attributes.
Get tag group tagsReturn the tags for a given tag group id.
Get tag relationships campaignsReturns the ids of all campaigns associated with the given tag.
Get tag relationships flowsReturns the ids of all flows associated with the given tag.
Get tag relationships listsReturns the ids of all lists associated with the given tag.
Get tag relationships segmentsReturns the ids of all segments associated with the given tag.
Get tag relationships tag groupReturns the id of the tag group related to the given tag.
Get tagsRetrieve up to 50 account tags at once, filterable/sortable by name or id, with cursor pagination.
Get tag tag groupReturns the tag group resource for a given tag id.
Get templateGet a template with the given template id.
Get templatesRetrieve account templates with sorting options (`id`, `name`, `created`, `updated`).
Get update categories jobGet a catalog category bulk update job with the given job id.
Get update categories jobsGet all catalog category bulk update jobs.
Get update items jobGet a catalog item bulk update job with the given job id.
Get update items jobsGet all catalog item bulk update jobs.
Get update variants jobGet a catalog variate bulk update job with the given job id.
Get update variants jobsGet all catalog variant bulk update jobs.
Get version ids for formGet the ids of the form versions for the given form.
Get versions for formGet the form versions for the given form.
Get webhookGet the webhook with the given id.
Get webhooksGet all webhooks in an account.
Get webhook topicGet the webhook topic with the given id.
Get webhook topicsGet all webhook topics in a klaviyo account.
Merge profilesQueue a task to merge one source profile into a destination profile using their ids.
Query campaign valuesReturns the requested campaign analytics values data*rate limits*:burst: `1/s`steady: `2/m`daily: `225/d` **scopes:** `campaigns:read`
Query flow seriesReturns the requested flow analytics series data*rate limits*:burst: `1/s`steady: `2/m`daily: `225/d` **scopes:** `flows:read`
Query flow valuesReturns the requested flow analytics values data*rate limits*:burst: `1/s`steady: `2/m`daily: `225/d` **scopes:** `flows:read`
Query metric aggregatesThe klaviyo endpoint fetches metric events, handling json requests for custom data queries, sorting, and filtering; offers grouping and time-based filters; requires adherence to rate limits (3 requests per second, 60 per minute) under 'metrics:read'.
Remove Profile from ListRemove profiles from a klaviyo list by profile ids or email addresses.
Request profile deletionTo delete a profile, use only one identifier: email, phone number, or id.
Spawn bulk profile import jobInitiate a job to create/update a batch of profiles, up to 10,000 with a max size of 5mb per request.
Spawn coupon code bulk create jobCreate a coupon-code-bulk-create-job to bulk create a list of coupon codes.
Spawn create categories jobCreate bulk job for up to 100 catalog categories with a 5mb size limit and a max of 500 concurrent jobs.
Spawn create items jobCreate batches of up to 100 catalog items with a 5mb size limit using the bulk job, which allows 500 concurrent jobs.
Spawn create variants jobInitiate a job to bulk create up to 100 catalog variants, with a 5mb payload size limit.
Spawn delete categories jobDelete multiple catalog categories in bulk, with a limit of 100 per request and a 5mb payload size.
Spawn delete items jobDelete batches of catalog items with a bulk job, max 100 items/request, 5mb size limit, and up to 500 concurrent jobs.
Spawn delete variants jobDelete multiple catalog variants with a bulk job, max 100 per request, 5mb size limit.
Spawn update categories jobCreate a job to bulk update up to 100 categories, with a 5mb size limit and a maximum of 500 concurrent jobs.
Spawn update items jobYou can bulk update up to 100 catalog items with a 5mb payload limit.
Spawn update variants jobCreate a job to bulk update up to 100 catalog variants with a 5mb payload limit.
Subscribe profilesThe api supports double opt-in for marketing, with 'historical import' bypassing consent.
Suppress profilesSuppress profiles by email, segment, or list id to stop email marketing, regardless of consent.
Unregister client push tokenThis endpoint unsubscribes a push token, for use with klaviyo's mobile sdks and a public api key.
Unsubscribe profilesOpt-out profiles from email or sms marketing.
Unsuppress profilesRemove 'user suppressed' blocks on profiles manually via email, segment, or list id.
Update CampaignUpdate a campaign with the specified attributes.
Update campaign messageUpdate a campaign message*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:write`
Update campaign send jobPermanently cancel the campaign, setting the status to canceled or revert the campaign, setting the status back to draft*rate limits*:burst: `10/s`steady: `150/m` **scopes:** `campaigns:write`
Update catalog categoryUpdate a catalog category with the given category id.
Update catalog category relationships itemsUpdate item relationships for the given category id.
Update catalog itemUpdate a catalog item with the given item id.
Update catalog item relationships categoriesUpdate catalog category relationships for the given item id.
Update catalog variantUpdate a catalog item variant with the given variant id.
Update coupon*rate limits*:burst: `3/s`steady: `60/m` **scopes:** `coupons:write`
Update coupon codeUpdates a coupon code specified by the given identifier synchronously.
Update flow statusUpdate the status of a flow with the given flow id, and all actions in that flow.
Update imageUpdate the image with the given image id.
Update listUpdate the name of a list with the given list id.
Update profileUpdate profiles with the provided id.
Update segmentUpdate a segment with the given segment id.
Update tagUpdate the tag with the given tag id.
Update tag groupUpdate the tag group with the given tag group id.
Update templateUpdate a template with the given template id.
Update webhookUpdate the webhook with the given id.
Upload image from fileUpload an image from a file.
Upload image from urlImport an image from a url or data uri.

What is the Composio tool router, and how does it fit here?

What is Tool Router?

Composio's Tool Router helps agents find the right tools for a task at runtime. You can plug in multiple toolkits (like Gmail, HubSpot, and GitHub), and the agent will identify the relevant app and action to complete multi-step workflows. This can reduce token usage and improve the reliability of tool calls. Read more here: Getting started with Tool Router

The tool router generates a secure MCP URL that your agents can access to perform actions.

How the Tool Router works

The Tool Router follows a three-phase workflow:

  1. Discovery: Searches for tools matching your task and returns relevant toolkits with their details.
  2. Authentication: Checks for active connections. If missing, creates an auth config and returns a connection URL via Auth Link.
  3. Execution: Executes the action using the authenticated connection.

Step-by-step Guide

Prerequisites

Before starting, make sure you have:
  • Python 3.9 or higher
  • A Composio account and API key
  • A Klaviyo connection authorized in Composio
  • An OpenAI API key for the CrewAI LLM
  • Basic familiarity with Python

Getting API Keys for OpenAI and Composio

OpenAI API Key
  • Go to the OpenAI dashboard and create an API key. You'll need credits to use the models, or you can connect to another model provider.
  • Keep the API key safe.
Composio API Key
  • Log in to the Composio dashboard.
  • Navigate to your API settings and generate a new API key.
  • Store this key securely as you'll need it for authentication.

Install dependencies

bash
pip install composio crewai crewai-tools python-dotenv
What's happening:
  • composio connects your agent to Klaviyo via MCP
  • crewai provides Agent, Task, Crew, and LLM primitives
  • crewai-tools includes MCP helpers
  • python-dotenv loads environment variables from .env

Set up environment variables

bash
COMPOSIO_API_KEY=your_composio_api_key_here
USER_ID=your_user_id_here
OPENAI_API_KEY=your_openai_api_key_here

Create a .env file in your project root.

What's happening:

  • COMPOSIO_API_KEY authenticates with Composio
  • USER_ID scopes the session to your account
  • OPENAI_API_KEY lets CrewAI use your chosen OpenAI model

Import dependencies

python
from crewai import Agent, Task, Crew, LLM
from crewai_tools import MCPServerAdapter  # optional import if you plan to adapt tools
from composio import Composio
from dotenv import load_dotenv
import os
from crewai.mcp import MCPServerHTTP

load_dotenv()
What's happening:
  • CrewAI classes define agents and tasks, and run the workflow
  • MCPServerHTTP connects the agent to an MCP endpoint
  • Composio will give you a short lived Klaviyo MCP URL

Create a Composio Tool Router session for Klaviyo

python
composio = Composio(api_key=os.getenv("COMPOSIO_API_KEY"))
session = composio.create(
    user_id=os.getenv("USER_ID"),
    toolkits=["klaviyo"],
)
url = session.mcp.url
What's happening:
  • You create a Klaviyo only session through Composio
  • Composio returns an MCP HTTP URL that exposes Klaviyo tools

Configure the LLM

python
llm = LLM(
    model="gpt-5-mini",
    api_key=os.getenv("OPENAI_API_KEY"),
)
What's happening:
  • CrewAI will call this LLM for planning and responses
  • You can swap in a different model if needed

Attach the MCP server and create the agent

python
toolkit_agent = Agent(
    role="Klaviyo Assistant",
    goal="Help users interact with Klaviyo through natural language commands",
    backstory=(
        "You are an expert assistant with access to Klaviyo tools. "
        "You can perform various Klaviyo operations on behalf of the user."
    ),
    mcps=[
        MCPServerHTTP(
            url=url,
            streamable=True,
            cache_tools_list=True,
            headers={"x-api-key": os.getenv("COMPOSIO_API_KEY")},
        ),
    ],
    llm=llm,
    verbose=True,
    max_iter=10,
)
What's happening:
  • MCPServerHTTP connects the agent to the Klaviyo MCP endpoint
  • cache_tools_list saves a tools catalog for faster subsequent runs
  • verbose helps you see what the agent is doing

Add a REPL loop with Task and Crew

python
print("Chat started! Type 'exit' or 'quit' to end.\n")
print("Try asking the agent to perform Klaviyo operations.\n")

conversation_context = ""

while True:
    user_input = input("You: ").strip()

    if user_input.lower() in ["exit", "quit", "bye"]:
        print("\nGoodbye!")
        break

    if not user_input:
        continue

    conversation_context += f"\nUser: {user_input}\n"
    print("\nAgent is thinking...\n")

    task = Task(
        description=(
            f"Based on the conversation history:\n{conversation_context}\n\n"
            f"Current user request: {user_input}\n\n"
            f"Please help the user with their Klaviyo related request."
        ),
        expected_output="A helpful response addressing the user's request",
        agent=toolkit_agent,
    )

    crew = Crew(
        agents=[toolkit_agent],
        tasks=[task],
        verbose=False,
    )

    result = crew.kickoff()
    response = str(result)

    conversation_context += f"Agent: {response}\n"
    print(f"Agent: {response}\n")
What's happening:
  • You build a simple chat loop and keep a running context
  • Each user turn becomes a Task handled by the same agent
  • Crew executes the task and returns a response

Run the application

python
if __name__ == "__main__":
    main()
What's happening:
  • Standard Python entry point so you can run python crewai_klaviyo_agent.py

Complete Code

Here's the complete code to get you started with Klaviyo and CrewAI:

python
# file: crewai_klaviyo_agent.py
from crewai import Agent, Task, Crew, LLM
from crewai_tools import MCPServerAdapter  # optional
from composio import Composio
from dotenv import load_dotenv
import os
from crewai.mcp import MCPServerHTTP

load_dotenv()

def main():
    # Initialize Composio and create a Klaviyo session
    composio = Composio(api_key=os.getenv("COMPOSIO_API_KEY"))
    session = composio.create(
        user_id=os.getenv("USER_ID"),
        toolkits=["klaviyo"],
    )
    url = session.mcp.url

    # Configure LLM
    llm = LLM(
        model="gpt-5-mini",
        api_key=os.getenv("OPENAI_API_KEY"),
    )

    # Create Klaviyo assistant agent
    toolkit_agent = Agent(
        role="Klaviyo Assistant",
        goal="Help users interact with Klaviyo through natural language commands",
        backstory=(
            "You are an expert assistant with access to Klaviyo tools. "
            "You can perform various Klaviyo operations on behalf of the user."
        ),
        mcps=[
            MCPServerHTTP(
                url=url,
                streamable=True,
                cache_tools_list=True,
                headers={"x-api-key": os.getenv("COMPOSIO_API_KEY")},
            ),
        ],
        llm=llm,
        verbose=True,
        max_iter=10,
    )

    print("Chat started! Type 'exit' or 'quit' to end the conversation.\n")
    print("Try asking the agent to perform Klaviyo operations.\n")

    conversation_context = ""

    while True:
        user_input = input("You: ").strip()

        if user_input.lower() in ["exit", "quit", "bye"]:
            print("\nGoodbye!")
            break

        if not user_input:
            continue

        conversation_context += f"\nUser: {user_input}\n"
        print("\nAgent is thinking...\n")

        task = Task(
            description=(
                f"Based on the conversation history:\n{conversation_context}\n\n"
                f"Current user request: {user_input}\n\n"
                f"Please help the user with their Klaviyo related request."
            ),
            expected_output="A helpful response addressing the user's request",
            agent=toolkit_agent,
        )

        crew = Crew(
            agents=[toolkit_agent],
            tasks=[task],
            verbose=False,
        )

        result = crew.kickoff()
        response = str(result)

        conversation_context += f"Agent: {response}\n"
        print(f"Agent: {response}\n")

if __name__ == "__main__":
    main()

Conclusion

You now have a CrewAI agent connected to Klaviyo through Composio's Tool Router. The agent can perform Klaviyo operations through natural language commands. Next steps:
  • Add role-specific instructions to customize agent behavior
  • Plug in more toolkits for multi-app workflows
  • Chain tasks for complex multi-step operations

How to build Klaviyo MCP Agent with another framework

FAQ

What are the differences in Tool Router MCP and Klaviyo MCP?

With a standalone Klaviyo MCP server, the agents and LLMs can only access a fixed set of Klaviyo tools tied to that server. However, with the Composio Tool Router, agents can dynamically load tools from Klaviyo and many other apps based on the task at hand, all through a single MCP endpoint.

Can I use Tool Router MCP with CrewAI?

Yes, you can. CrewAI fully supports MCP integration. You get structured tool calling, message history handling, and model orchestration while Tool Router takes care of discovering and serving the right Klaviyo tools.

Can I manage the permissions and scopes for Klaviyo while using Tool Router?

Yes, absolutely. You can configure which Klaviyo scopes and actions are allowed when connecting your account to Composio. You can also bring your own OAuth credentials or API configuration so you keep full control over what the agent can do.

How safe is my data with Composio Tool Router?

All sensitive data such as tokens, keys, and configuration is fully encrypted at rest and in transit. Composio is SOC 2 Type 2 compliant and follows strict security practices so your Klaviyo data and credentials are handled as safely as possible.

Used by agents from

Context
ASU
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai
Context
ASU
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai
Context
ASU
Letta
glean
HubSpot
Agent.ai
Altera
DataStax
Entelligence
Rolai

Never worry about agent reliability

We handle tool reliability, observability, and security so you never have to second-guess an agent action.