Automation scenarios tools

🚧

Warning

Write tools change your live configuration. Just like changes made in the Marketing dashboard, actions your users or agents take with these tools can have a substantial impact on your campaigns, automations, and customer communications. There is no automatic rollback and activity logging is limited, so review every change and confirm the target before applying it.

search_scenarios

Searches the scenarios (automation flow campaigns) in a project, or fetches one by ID. Scenarios are multi-step flows with triggers, conditions, waits, and actions. Omit scenario_id to list all scenarios as summary records: name, status, tags, archived flag, and initiative assignment. The node graph is excluded from the list — pass scenario_id, or use the lighter-weight search_scenario_nodes, to explore it.

List mode also narrows the set for you. Filter by archived, status, tags, trigger_types, creation window (created_after and created_before), only_mine, system_scenarios, or paused_by_bloomreach, and page through the results with offset and limit.

Pass scenario_id to fetch the complete scenario definition, including the trigger, every node in the flow graph (waits, conditions, actions, A/B splits), the connections array of graph edges, and metadata. Email and SMS design payloads are stripped from nodes by default to keep responses manageable. Set include_node_designs to true to include them, though design blobs can be 70 KB or more per node.

Detail mode is the most reliable way to learn the connection edge schema before you write a scenario. Read the connections array from a scenario that already works, then mirror that shape in create_scenario or update_scenario. Note that customer_filter is read-only here and effectively always null: audience scoping lives on a Condition node inside the graph, not on the scenario itself.

Request parameters

NameTypeRequired?Description
project_idstrYesThe project ID returned by list_projects.
scenario_idstr | nullNoThe scenario ID. Omit to list all; provide to fetch one.
include_node_designsboolNoWhen fetching a single scenario, include the full email or SMS design payload in action nodes. Ignored when scenario_id is omitted. Defaults to false.
archivedbool | nullNoFalse, the default, returns only live scenarios, matching the UI default. True returns only archived scenarios. Pass null to return both.
statusstr | nullNoFilter by lifecycle status: draft, active, inactive, paused, or finishing. Applied client-side. Omit for every status.
created_afterfloat | nullNoReturn only scenarios created at or after this Unix timestamp.
created_beforefloat | nullNoReturn only scenarios created at or before this Unix timestamp.
only_mineboolNoReturn only scenarios created by the calling user. Defaults to false.
tagslist | nullNoReturn only scenarios carrying every tag listed, for example ['onboarding', 'email']. Applied client-side.
system_scenariosbool | nullNoTrue returns only Bloomreach system and template scenarios, False leaves them out. Pass null to return both.
paused_by_bloomreachbool | nullNoTrue returns only scenarios paused by Bloomreach, False leaves them out. Pass null to return both.
trigger_typeslist | nullNoReturn scenarios whose trigger matches any of the types listed: now, repeated, onevent, onapi, onapi-interest, ondateattribute, oncatalog, or planned. Applied client-side.
offsetintNoThe number of records to skip, for pagination. Defaults to 0.
limitintNoThe maximum number of records to return. Defaults to 200, with a maximum of 1000.

Response parameters

The tool returns a ScenariosResponse when scenario_id is omitted, or a ScenarioResponse when it's provided.

The ScenariosResponse object has the following parameters:

ParameterTypeDescription
successboolWhether the request succeeded.
datalist[ScenarioSummary]The scenario summaries.
offsetintThe offset used for this request. Defaults to 0.
limitintThe maximum number of records returned for this request. Defaults to 200.
archived_items_existsbool | nullWhether the project holds any archived scenarios. Populated only when archived is false, the default.
errorstr | nullError message if the request failed.

The ScenarioSummary object has the following fields:

FieldTypeDescription
idstrThe scenario's unique ID.
namestrThe scenario's display name.
statusstrOne of draft, active, inactive, finishing, or finished.
archivedboolWhether the scenario has been archived.
tagslist[str]User-defined tags.
initiative_idstr | nullThe initiative this scenario belongs to, if any.
is_global_objectbool | nullWhether the scenario is a global, shared object.
createdany | nullUnix timestamp of when the scenario was created.
created_by_display_namestr | nullDisplay name of the creator.
editedany | nullUnix timestamp of the last edit.
edited_by_display_namestr | nullDisplay name of the last editor.

When scenario_id is provided, the tool returns a ScenarioResponse object with the following parameters:

ParameterTypeDescription
successboolWhether the request succeeded.
dataScenario | nullThe full scenario definition.
errorstr | nullError message if the request failed.

The Scenario object adds the following fields on top of the summary record:

FieldTypeDescription
triggerany | nullThe entry trigger: an event, a schedule, or an API call.
nodeslist[any]The scenario node graph. Each node is one step in the flow — a wait, an action, a condition, an A/B split, and so on.
connectionslist[any]The graph edges. Each entry is {"source": {"node_id", "connector_index"}, "destination": {"node_id", "connector_index"}}. A destination connector_index is usually 0, the input port. On a condition source, 1 is the match branch and 2 is the don't-match branch. On an ab-split source, outputs start at 1.
customer_filterany | nullRead-only, and effectively always null. Audience scoping belongs on a Condition node, not here.
max_customersint | nullThe maximum number of customers allowed in the scenario at one time.

search_scenario_nodes

Explores the node graph of a single scenario at two levels of detail. Omit node_id to get a lightweight map of the whole flow: every node's ID, type, and name, the full connections array of edges, and the entry trigger. Pass node_id to get one node's complete configuration, along with its incoming_connections and outgoing_connections. The usual sequence is a map first, then a detail call on whichever node you need to inspect.

The scenario is fetched once and cached for 10 seconds, so sequential calls against the same scenario share a single underlying request. In detail mode, a node ID that doesn't exist comes back as success of false with the reason in error rather than raising.

The design payload on action nodes (email or SMS templates) is omitted by default, because a single design can run to 70 KB or more. Set include_design to true if you need the template content. It applies to detail mode only and is ignored when you omit node_id.

This tool is discover-only: it isn't part of the default tool list your AI application receives when it connects. If your MCP client supports tool discovery, look the tool up that way — a search_tools-style lookup followed by an invocation — before calling it. Clients that only work from the initial tool list may not be able to reach it.

Request parameters

NameTypeRequired?Description
project_idstrYesThe project ID returned by list_projects.
scenario_idstrYesThe scenario ID returned by search_scenarios.
node_idint | nullNoThe numeric node ID. Omit to map every node in the scenario; provide to fetch one node's full configuration.
include_designboolNoIn detail mode, include the design field on action nodes. Ignored when node_id is omitted. Defaults to false.

Response parameters

The tool returns a ScenarioNodesResponse when node_id is omitted, or a ScenarioNodeResponse when it's provided.

The ScenarioNodesResponse object has the following parameters:

ParameterTypeDescription
successboolWhether the request succeeded.
scenario_idstrThe scenario's ID.
scenario_namestrThe scenario's display name.
nodeslist[ScenarioNodeSummary]A lightweight list of nodes: ID, type, and name, each with its own incoming and outgoing connections.
connectionslist[any]The graph edges. Each entry is {"source": {"node_id", "connector_index"}, "destination": {"node_id", "connector_index"}}. A destination connector_index is usually 0, the input port. On a condition source, 1 is the match branch and 2 is the don't-match branch. On an ab-split source, outputs start at 1.
triggeranyThe entry trigger configuration for the scenario.
errorstr | nullError message if the request failed.

The ScenarioNodeSummary object has the following fields:

FieldTypeDescription
idintThe numeric node ID, unique within the scenario.
typestrThe node type, for example send-email-action, condition, wait-action, or ab-split.
namestr | nullAn optional display label set by the scenario author.
incoming_connectionslist[any]The edges arriving at this node from parent nodes. Empty for entry-point trigger nodes.
outgoing_connectionslist[any]The edges leaving this node toward child nodes. On branching nodes, connector_index identifies which branch, numbered from 1.

When node_id is provided, the tool returns a ScenarioNodeResponse object with the following parameters:

ParameterTypeDescription
successboolWhether the request succeeded.
scenario_idstrThe scenario this node belongs to.
nodeany | nullThe full node configuration. The shape varies by node type.
incoming_connectionslist[any]The edges arriving at this node from parent nodes. Empty for entry-point nodes.
outgoing_connectionslist[any]The edges leaving this node toward child nodes. On branching nodes, connector_index identifies which branch, numbered from 1. Empty for terminal nodes.
errorstr | nullError message if the request failed or the node was not found.

create_scenario

Creates a new scenario (automation flow). The scenario is always created as a draft — it does not run until it is activated in the Marketing UI. On success, the tool returns the ID of the new scenario.

The payload requires a name, a nodes list with at minimum one trigger node, a connections list of edges between nodes (empty for a trigger-only scenario), and a last_node_id set to the highest node ID present in nodes. A trigger node's type can be on-event-trigger, on-api-trigger, on-date-attribute-trigger, repeated-trigger, planned-trigger, or now-trigger, and each type has its own required sub-fields.

Every edge in connections must use one exact shape: a source and a destination, each an object holding a node_id and a connector_index. Nothing else works. The backend returns an HTTP 400 for {source, target}, {from, to}, {source_id, target_id}, and a bare [src, tgt] array. To see the shape on a live scenario, call search_scenarios with a scenario_id and read its connections.

Index 0 is a node's input port everywhere except on a trigger, where it's the trigger's single output. So a destination is nearly always 0, and a source is 0 only when the source is a trigger. Anywhere else, 0 as a source fails with Source connector doesn't exist. On a condition source, 1 is the match branch and 2 is the don't-match branch. On an ab-split source, outputs start at 1 for the first variant. A wait-action source uses 1. Most action nodes, send-email-action among them, use 1 for success and 2 for failure.

Keep customer_filter off the scenario top level. The scenario model has no top-level customer_filter field, so the backend used to drop the key without complaint and save the scenario as send-to-everyone. The tool now rejects a top-level customer_filter before it calls the backend. Audience scoping belongs on a Condition node, as a customer_filter on a node whose type is condition, since that's the one place the backend stores and evaluates one. Condition-node filters are shape-checked up front, which catches the frequent slips: equal to is a number operator and strings need equals, attribute.type is property rather than customer_property, and every operand needs {"type": "constant", "value": ...} rather than a bare value.

Recurring schedules have their own rules. repeated-trigger and on-date-attribute-trigger share a backend model, so both need a timezone plus times, or minutes when repeat is hourly. The real field names are repeat, days, times, timezone, from_date, and to_date. times holds a list of {hour, minute} objects rather than a string such as 09:00, and weekly days are numbered 1 to 7. There's no yearly repeat and no every-N-intervals frequency. The names repeat_type, repeat_frequency, repeat_on_days, start_date, end_date, and repeat_at_time never existed on the backend, which dropped them and saved a plain daily schedule, so the tool rejects them along with a missing times or timezone.

Failures return success: false with the detail in error. Pre-flight checks report every problem they find in a single message. A backend rejection arrives as HTTP <status>: <field>: <message>, for example HTTP 400: nodes.0.days: Day 0 is out of range 1 - 7, which tells you the node and field to fix.

Request parameters

NameTypeRequired?Description
project_idstrYesThe project ID returned by list_projects.
payloaddictYesThe scenario definition. Requires name, nodes, connections, and last_node_id. Each edge in connections must be {'source': {'node_id': int, 'connector_index': int}, 'destination': {'node_id': int, 'connector_index': int}}.

Response parameters

The tool returns a WriteResponse object with the following parameters:

ParameterTypeDescription
successboolWhether the operation succeeded.
idstr | nullThe ID of the newly created scenario.
errorstr | nullThe pre-flight message, or the HTTP status and the backend's field-level validation detail, if the operation failed.

update_scenario

Replaces the full definition of an existing scenario with the payload you provide (PUT semantics), so pass the complete scenario, not just the fields you want to change. The scenario must be in draft or inactive status — running scenarios cannot be modified, and status transitions such as activate and stop must be done through the Marketing UI.

To change fields on a single existing node without resending the whole scenario, use update_scenario_node instead. Reserve this tool for structural edits: adding or removing nodes, editing connections, or replacing the full definition.

Start by fetching the current definition with search_scenarios(scenario_id=...). Add include_node_designs=True when the scenario has email or SMS action nodes, because PUT semantics would otherwise drop the stripped design payloads and wipe your templates. Modify the fields you need, then pass the whole object here. Keep existing node IDs intact, since the backend matches nodes by ID and treats a changed ID as deleting the old node and creating a new one. Set last_node_id to the highest node ID in the nodes array, and update it whenever you add nodes.

Edges in connections use the same single accepted shape as create: a source and a destination, each with a node_id and a connector_index. A destination is nearly always 0, the input port. On a condition source, 1 is the match branch and 2 is the don't-match branch, and 0 is invalid as a source. On an ab-split source, outputs start at 1.

Two constraints catch people out on update in particular. A top-level customer_filter is rejected before any backend call, so if you fetched an audience-scoped scenario, leave its filter where you found it on the Condition node instead of lifting it to the top. And recurring triggers must use the real field names repeat, days, times, timezone, from_date, and to_date, since the legacy repeat_type, repeat_frequency, repeat_on_days, start_date, end_date, and repeat_at_time names are rejected up front.

Failures return success: false with the detail in error, either the combined pre-flight message or a backend rejection as HTTP <status>: <field>: <message>, for example HTTP 400: nodes.0.times: This field is required.

Request parameters

NameTypeRequired?Description
project_idstrYesThe project ID returned by list_projects.
scenario_idstrYesThe scenario ID returned by search_scenarios or create_scenario.
payloaddictYesThe full updated scenario definition, in the same shape as create. Fetch the current scenario with search_scenarios(scenario_id=...) first, then change only what you need.

Response parameters

The tool returns a WriteResponse object with the following parameters:

ParameterTypeDescription
successboolWhether the operation succeeded.
idstr | nullThe ID of the updated scenario.
errorstr | nullThe pre-flight message, or the HTTP status and the backend's field-level validation detail, if the operation failed.

update_scenario_node

Patches fields on one existing node inside a scenario, without round-tripping the full scenario graph. The tool re-reads the scenario on the server, shallow-merges your patch onto the node whose ID you name, then saves the scenario for you. Every other node, every connection, and every key on the target node you didn't mention are preserved, so you never have to resend a 70 KB email or SMS design blob just to change a subject line or a wait duration.

Its scope is one node's fields. Adding a node, removing a node, or editing connections is a structural change, and those still go through update_scenario. As with that tool, the scenario must be in draft or inactive status — running scenarios cannot be modified, and status transitions belong in the Marketing UI.

The merge is shallow. Top-level keys in patch replace those keys on the stored node, and keys you leave out stay as they are. Nested objects such as customer_filter, event, trigger, offset, and design are replaced wholesale rather than deep-merged, so a partial nested object would silently drop the keys you didn't include. The tool catches that case, rejects the patch, and previews exactly which nested keys would disappear. To change one field inside a nested object, fetch the node with search_scenario_nodes, edit your copy, and send the complete nested object back. If the deletion really is what you want, pass confirm_nested_deletes of true.

type, id, and version cannot be patched and are rejected up front, since changing them would break the node's identity. Use list_projects and search_scenarios if you don't have the project_id or scenario_id, and search_scenario_nodes to discover the node_id.

Request parameters

NameTypeRequired?Description
project_idstrYesThe project ID returned by list_projects.
scenario_idstrYesThe scenario ID returned by search_scenarios or create_scenario.
node_idintYesThe numeric node ID. Use search_scenario_nodes to discover node IDs.
patchdictYesThe fields to change on the node, merged shallowly. Leave out type, id, and version.
confirm_nested_deletesboolNoAllow a patch that drops keys from a nested object. Set it to true only once the preview has shown you the deletions and they're intentional. Defaults to false.

Response parameters

The tool returns a WriteResponse object with the following parameters:

ParameterTypeDescription
successboolWhether the operation succeeded.
idstr | nullThe ID of the scenario the node belongs to.
errorstr | nullThe pre-flight message, or the HTTP status and the backend's field-level validation detail, if the operation failed.

delete_scenario

Permanently deletes a scenario. The scenario must be in draft or inactive status — running scenarios cannot be deleted. This action is irreversible: the scenario and all its node configuration are removed, and there is no undo through this tool, so verify the target before you run it.

Find scenario IDs with search_scenarios. A refused delete, a running scenario for example, comes back as success: false with the HTTP status and the backend's message in error rather than a bare status code.

Request parameters

NameTypeRequired?Description
project_idstrYesThe project ID returned by list_projects.
scenario_idstrYesThe scenario ID returned by search_scenarios.

Response parameters

The tool returns a WriteResponse object with the following parameters:

ParameterTypeDescription
successboolWhether the operation succeeded.
idstr | nullNot present for deletes.
errorstr | nullThe HTTP status and the backend's message if the delete failed.


Did this page help you?

© Bloomreach, Inc. All rights reserved.