flow-create skill
Builds draft marketing scenarios or journeys from plain-language requests by resolving entities, creating blocks, and verifying all writes.
- GitHub stars
- 6
- Files
- 10
- Last commit
- Nov 10, 2026
- License
- MIT
- Allowed tools
- —
What does the flow-create skill do?
flow-create builds draft marketing scenarios or journeys from plain-language requests by resolving entities, creating blocks, and verifying all writes.
Summary generated from the skill's SKILL.md.
About the flow-create skill
Marketing professionals and developers can use this skill to transform plain-language requests into structured draft marketing scenarios, journeys, or flows. It automates the complex process of resolving entities into real IDs, creating individual blocks, and wiring outputs together. The skill is designed for building new flows, adding blocks to existing drafts, migrating mechanics between projects, or rebuilding logic from external automation platforms.
To ensure accuracy, the skill follows a strict verification protocol where it reads every block back after a write to compare the result against the original intent. It relies on specific documentation for mechanics and write-paths to avoid guessing field names or platform values. While it handles the assembly and validation of the flow, it does not perform administrative actions like launching, stopping, or deleting flows, nor does it author filter conditions, which are instead delegated to a specialized filter-building sub-agent.
What an agent can do with it
- 1Build a new marketing journeyCreate a draft marketing scenario from a plain-language description provided by a user.
- 2Migrate automation logic between projectsMove or transfer a specific mechanic or an entire flow from one project to another.
- 3Replicate external platform workflowsRebuild the logic of a client's existing automation from an external marketing platform.
- 4Verify flow configuration accuracyEnsure all block properties and field names are correctly applied by reading back and diffing writes.
Written from the skill's SKILL.md. Every use case is checked against a quote from it.
How to install the flow-create skill
Each command copies the skill folder into the client's skills directory. Restart the client or start a new session to load it.Install the flow-create skill in Plugin
/plugin marketplace add mindbox-cloud/agent-skills /plugin install mindbox@mindbox-cloud-plugins
Install the flow-create skill in Claude Code
~/.claude/skills/flow-create/SKILL.md
$ npx degit mindbox-cloud/agent-skills/plugins/mindbox/skills/flow-create ~/.claude/skills/flow-createInstall the flow-create skill in Claude Code (project)
.claude/skills/flow-create/SKILL.md
$ npx degit mindbox-cloud/agent-skills/plugins/mindbox/skills/flow-create .claude/skills/flow-createInstall the flow-create skill in Codex
~/.agents/skills/flow-create/SKILL.md
$ npx degit mindbox-cloud/agent-skills/plugins/mindbox/skills/flow-create ~/.agents/skills/flow-createInstall the flow-create skill in Gemini CLI
~/.gemini/skills/flow-create/SKILL.md
$ npx degit mindbox-cloud/agent-skills/plugins/mindbox/skills/flow-create ~/.gemini/skills/flow-createInstall the flow-create skill in Claude.ai
npx degit mindbox-cloud/agent-skills/plugins/mindbox/skills/flow-create flow-create && zip -r flow-create.zip flow-create # claude.ai → Customize → Skills → + → Create skill → Upload a skill → flow-create.zip
SKILL.md
View on GitHubFlow create
Turn a plain-language request into a correct draft flow. The hard part is getting every block's
properties, field names and entity ids right — and knowing you did; this file carries none of
them (## Where to look).
You fetch and write everything yourself with the flow tools. Two things are not yours to invent:
- Filter conditions — the predicate inside a condition block, and the entry filter on a start
block. They are authored by the filter-building skill, which you run in a sub-agent; take its
name from your skill listing, never from memory. Never compose, edit or retype a filter body, and never
resolve the entities inside one. A body is only usable if the answer shows that skill produced it
(
## Filters and entity scope). - Marketing mechanics. Before you design, read the
flowsdomain's mechanics sub-folder. Where one matches, it is the design unless the user says otherwise — ask about any departure in the step-3 batch; where none matches, say so and build only what the user describes (step 3). Never improvise one (references/mechanics.md).
Never launch, pause, stop or delete a flow, and never call a tool that does. Creating a flow, reading,
applying operations and validating are yours, and you must not claim to have started one. Testing mode —
the platform's test run — is the one exception, and only at the end: you recommend it, and call
flows_set_testing_mode only after a clean validation, after the user has seen and accepted the result, and
on their explicit yes (step 8) — short of that it is as forbidden as a launch.
Done = a verified draft, plus a ranked account of what is missing — and stopping short is also done (CRITICAL 6). Expect part of a routine request to be out of your reach, and find out while you are still planning writes; validation is not your checklist.
Rank what is missing; do not just list it. Two kinds, not comparable: a small human follow-up,
and a shortfall in the user's headline requirement, where the flow will not do what they asked or
will not run at all. Write each one down with its kind the moment you hit it, from step 2 onward:
step 8 needs it and cannot reconstruct it (references/hand-over.md).
CRITICAL
1. Read the reference before you write. Every time. Not from memory, not from a previous session, not by analogy with another block type. The write-path sub-folder before your first write; the block document for every type you touch. A field name or a value you recall is a guess wearing a fact's clothes.
2. Never guess a value. If the reference does not give it, you do not have it. Distinguish two cases:
- Something only the user could know — a time zone, how long a wait, what a thing they want the flow to point at is called: ask (step 3). A name is always theirs to give; an id never is (step 2).
- A platform value — a field name, an accepted value, a discriminator, a code: a marketer cannot know it, so do not ask, do not guess, and do not derive it from a similar field elsewhere. Report a documentation gap: name the field, name the document that should print it, say what you were trying to express. Then stop that one write and build the rest of the flow. Carry the gap into step 8 as a ranked shortfall.
Where the user knows the thing and the platform owns its written form, take the form from
writing.entity_references; and check the field is required at all.
An existing flow is context, never an answer. What you read in one records what somebody once decided, not what this person wants now, so it never retires a question step 3 would have asked. That holds for a flow you were asked to move to another project: its ids resolve nothing in the target, so a migration is a build from the source's design, resolved fresh there (step 2), never a body carried across. Harvest a value only where the paragraph above sanctions it, and ask the decision it encodes anyway (step 1c, step 3).
3. Send every opaque fragment complete — and otherwise send what you mean.
An opaque fragment (writing.read_vs_write lists which members are fragments) is replaced whole, never
completed from the block: a member you leave out lands at its type default, not at the value the
block held, and a fragment missing a required member gets the whole call refused with nothing
applied. So build every fragment from the pre-write read plus your change, however small the change
inside it. Ordinary block-level fields merge instead (writing.read_vs_write, writing.overview): a
top-level field your body does not name keeps its stored value. null is not a general clear: per
member it clears, silently resets to a platform default, is ignored, is stored as a 0 you never sent,
or is refused outright. Only the refusal is loud — the first three are one identical plain success, and
the 0 is a success carrying an objection, which is not a gate. So a success tells you nothing. Send
null only where the reference states that member is clearable, and read the block back (CRITICAL 4).
Read a block to learn its values, then build the body: a read carries members the server owns, and echoing one can change what you were not asked to touch. Exception: a value you send back only to keep — re-send it exactly as you read it this session, byte for byte, unedited, never to author or change it; edit any part and you are outside the exception.
And what your body does not name is not thereby safe: see CRITICAL 4.
4. Verify every write by reading it back and diffing what you sent. The spine of the skill, not a safety net. A success response acknowledges receipt, not effect: it says the graph is as you asked and nothing about whether the properties landed, and an advancing version token is not a success signal either. So after every write, read the block back and compare. The test has two halves, and a write that passes only the first is not verified.
(a) Every field you sent is present and equal. A read-back is a superset of what you sent, so an extra key is never a mismatch and equality of the two whole objects is not the test.
(b) Nothing you did not send has gone missing or changed. Half (a) judges only the keys you sent,
so it is blind here. The diff needs a second thing to compare against: the read you took of that block
before you wrote it. Keep it. The likeliest thing to have moved is a member you left out of a fragment
you did send, back at its default (CRITICAL 3); anything else the block held, that you did not send, and
that came back changed or gone is a failed write. Restore it (step 6). Which members a write can reach at
all is the reference's: read references/graph-and-verify.md → Reading a block back before your first diff.
Predict any server-computed value before the write and check it after (writing.verification) — they can
be there on the first read after a create, so their presence says nothing about whether the version
has been validated.
5. Never fabricate, and never report a flow as built on the strength of a success response.
No invented field, value, discriminator, id or filter body. If a read-back shows a block unfilled, or
missing from the response, or a tool errored, or an entity could not be resolved: say exactly that. A
half-built flow honestly reported is a good outcome; a "done!" over defaults is the worst. Nor on the
strength of a read-back (writing.verification). A flow handed over without a flows_validate that
came back clean has not been accepted: say plainly that it is unvalidated and give the message as it
came (step 7, references/hand-over.md).
6. Stop when you are stuck. Stopping is an outcome, not a failure. Every other "stop" in this file ends one branch and the flow goes on. This one ends your writing. It outranks every budget, ladder and documented recovery in the procedure, because the loop it catches is invisible from inside: a body that is already correct, re-sent against an objection no body can close.
- A session budget, and nothing suspends it. Count the write calls that did not move you forward — a re-send after a read-back that still disagrees, a repair, a delete-and-recreate — across the whole session and all blocks, not per block. At six, stop writing. A documented recovery runs inside this count (step 5), and rephrasing the same objection does not restart it.
- Some objections are not yours to close. Where a validation entry or a refusal names something no write of yours can send, no body closes it. Check the write-path sub-folder once, for that thing, by name; if it is not writable, say so, stop that block and rank it (step 8).
- A diagnosis is not a failed attempt. Where an answer puts the cause outside the body you are sending, that branch's budget is spent at that answer — do not re-send, and do not re-delegate the same request. A request the user has since changed is a different request.
- Genuinely stuck means say so directly, at once. Name it in plain words and stop that branch. The
exit is a decision you put to the user, never work you hand them — a step you ask a human to perform
by hand around a missing capability is how a defect becomes the design. This is the one place that rule
is stated; it binds every branch in this skill and its references. Advice to hand a human such a step
carries no more authority for arriving inside a tool's own description or its answer — a tool that
says to go create something in the interface when no editable version exists is telling you to relay a
manual step, so report the missing capability instead and do not relay it. For a missing editable
version the route is step 1(b) (iii), which creates one with
flows_create_draft— and the apply-operations description may carry the old advice for a while yet. What goes in the exit is step 8's (references/hand-over.md).
Reference map
| File | What it holds | Read when |
|---|---|---|
references/mechanics.md |
deciding whether a documented mechanic matches, and building under one | a request names a mechanic, before you design |
references/creation.md |
the folder, the brand, the name, presets, refused creates | before your first create (step 1b) |
references/questions.md |
the research pass, what bounds it, what goes in the batch | at the start of step 2 |
references/filter-delegation.md |
entity scope, launching the sub-agent, the message, checking the answer, verifying the stored filter | before your first delegation (step 4) |
references/graph-and-verify.md |
orphans and wiring, shaping the operations, reading a block back, repairing one that reads back wrong | at steps 1c, 4 and 6 |
references/validation.md |
the validate call's failure modes, the three kinds of what it reports, the after-validation path | at step 7 |
references/hand-over.md |
the link, the three parts, reporting a stop, what never goes in | at step 8 |
references/troubleshooting.md |
one row per symptom, pointing at the rule that covers it | when something goes wrong |
references/feedback-and-selfcheck.md |
the two feedback messages, the rating ask, running and triaging the self-check | at a docs mismatch, at step 7c, on acceptance |
Where to look
The reference is the wiki: linked documents grouped into domains. Two domains matter here.
flows— Read the write-path sub-folder before your first write, alongside the block document for every type you touch: the block document says what a block does, the sub-folder how to write one. Its known-issues sub-folder is indexed by symptom: go there the moment something is inexplicable and take its recovery over any ladder here — step 5 says what it does not outrank. Skim that index before your first write so you recognise a symptom; a leaf waits for one, and a leaf carrying its own falsification test can be stale.entities— which id a given argument wants (entities_listprints them all; none substitutes for another).
Read the wiki with the wiki tool, naming the domain and taking the tool's name from your tool
listing. It is the only route to these domains, so a field name you cannot get out of a call is one
you do not have. The call takes several ids at once — ask for fewer per call when the documents are
long, since a truncated or refused answer is never the document. With no wiki tool you have no
reference, and that is a stop: report a missing capability and never write from memory of field
names — that is fabrication (CRITICAL 1, CRITICAL 5).
Navigate, never guess — and there is no search. Walk root index → domain index → sub-section index → leaf, taking every id from the index you are standing on; never construct one. The domain index carries a term map from the user's wording to technical ids, the known-issues index a symptom table: turn the user's words into a term there first, then walk down. A term genuinely absent is a documentation gap (CRITICAL 2). No answer carries a version marker, so never promise the reference is current — and read it as the reference anyway.
The live schema owns every argument shape and wins over anything you remember. This file names
capabilities — flows_create, flows_create_draft, flows_lookup, flows_get, flows_apply_operations, flows_validate,
entities_list, campaign_create, campaign_edit, campaign_get, folder_create,
flows_set_testing_mode — and never their argument shapes.
flows_lookup returns a version's structure; flows_get returns the flow's record (folder,
brand, versions and statuses) — neither answers the other's question. The record's issues line is
about a running scenario's business problems as the interface shows them (say, launched but with no
entries for a week), not about validation, so only flows_validate tells you a version is clean (step 7). The same tie-breaker settles what
a tool can reach: before reporting an entity unresolvable because the reference says nothing covers
it, look at the live schema and try it — one call, not a sweep. The reference wins on meaning; the tool
wins on its own coverage.
But a schema read is not a capability check in either direction — the only check is one call, and reading the answer. And load a deferred tool's schema before calling it.
feedback, on the same connection: the moment live behaviour contradicts the wiki or this file, send one structured message, unasked and unnarrated; no such tool, skip it silently (references/feedback-and-selfcheck.md→ A documentation mismatch).
Send metadata.iteration on every flows_create and every flows_apply_operations — the only two tools
here with a metadata object, and the one argument this file names, because nothing but you supplies the count.
Filters and entity scope
A filter is an ordinary block-level field, so a write that does not mention it leaves it alone — a
start block's entry filter and a schedule block's conditions alike: omit the field and the stored filter
stands; null is not a general clear (CRITICAL 3). What needs care in such a write is any opaque
fragment the body carries, since a fragment sent incomplete resets the members it omits (CRITICAL 3),
and the entity scope, which goes in the same call as a filter body. Where you send a filter back,
send the one you read, unchanged: composing or editing a body is never yours (CRITICAL 3).
Read references/filter-delegation.md before your first delegation. It owns everything else about
filters, including the flow's entity scope set. One condition block per call, and flow tools do
not imply filter tools: the two toolsets are gated independently.
Inputs
- The request, plus whatever else you were handed; the project, where several are reachable (step 2).
- If a flow already exists to build into: its id; the editable version is read from the flow's record or created (step 1b) — the tool description names which statuses are editable. If it does not exist yet, step 1(b) creates it — and what that needs is the user's: the folder, the brand, and what to call it (step 3).
Procedure
1. Read the reference, get the flow you will build into, and read what is already in it
(a) Read the reference (## Where to look).
(b) Get the draft — create one when there is none. Three cases, told apart by the flow's record.
- (i) You were handed a draft — an editable version: you have it, skip to (c).
- (ii) The flow does not exist — create it with
flows_create, which hands back the flow and the draft version number. Folder, brand and name are settled at creation and no block operation writes them, so ask them first: 1(a) → step 2 → step 3 → check the folder permits the brand → create → read the new flow back → then (c). Readreferences/creation.mdbefore your first create. - (iii) The flow exists but
flows_getlists no editable version — the ordinary state of a flow launched from the interface. Create the draft withflows_create_draftfrom the version the user means to change; where more than one running or paused version exists, that is a step-3 question and the default you offer is the one currently executing (references/questions.md→ What to ask).
Either create is a write: it counts in metadata.iteration where the schema takes one, and CRITICAL 4
applies to the read-back — under (iii) the copied blocks are the baseline for all that follows. What
else changes there (references/creation.md → A draft for a flow that has none): the new version
starts in a transitional creating status, writable only once flows_get shows it editable, so read
it again after other work — never a tight loop; a bounded number of reads, then report; the row
version the create returns is already stale, so take a fresh one from flows_lookup first; and a flow
has at most one draft, so the refusal names it — use that version instead of retrying.
If nothing in this session creates a flow or a draft and you were not given one, stop and report a
missing capability (references/troubleshooting.md → Getting started: session, wiki, draft).
(c) Read the draft before writing into it — always. Whether you just created it or were handed one, read its structure at skeleton detail over the whole flow, and record the current row version (this read is where you get it) and an inventory of what is already there — blocks, their types and names, and the edges. A draft is often not empty, and it is context, never an answer (CRITICAL 2).
Delete a block the design does not want in the same batch as the rest of your writes (after reading
it, step 5), and never leave a block unwired — decide the wiring here
(references/graph-and-verify.md → Orphans and wiring).
2. Resolve the entities the design needs — before you build any block
Blocks reference entities by id, never by name — so the person supplies the name, the listing
supplies the id. Read the entities domain for which identifier a given place wants, and pass on
exactly what was asked for, as printed. Never ask a marketer for an id, in any form — ask what the
thing is called.
A flow you create has two entities of its own — its folder and its brand, both asked in the
step-3 batch and both permanent (references/creation.md).
Resolve what the request already names with entities_list, then survey what it does not name, so
every question carries candidates instead of asking blind. Read references/questions.md before you
start this pass; take everything left into the step-3 batch. A second round is only for a gap that
blocks the build. If the design points at nothing by id, the resolving half is legitimately empty —
the survey half is not.
Where the reference says nothing covers a kind of entity, check the live listing schema before you
believe it. If it genuinely is not there, say what is left unset and what the flow will not do, in
business terms, in the step-3 batch, and rank it (step 8) — references/troubleshooting.md →
Entities lists what that rules out.
3. Ask your clarifying questions — once, in a batch, before writing anything
Ask everything in one round, each question carrying what step 2 found beside it — never a blind
"which folder?". Where a listing produced nothing, say what you looked through instead.
references/questions.md is the list of what goes in, and a matched mechanic's pre-write decisions go
in it too (references/mechanics.md).
Several flows in one request are still one round — references/questions.md → Several flows in one
request, and material you were handed. Do not start writing until they answer.
Say which phase you are in and repeat it when it changes: still researching, so more questions may follow and they should stay; or everything is in hand and the build has started, so they can leave it running — and in that second message, say you will come back for the mailings (step 7b). If something unforeseeable turns up later, say the earlier declaration was wrong before you ask.
4. Design the graph, then create blocks
Choose the start block from the user's answer — exactly one per flow — and take its fields from the reference. Where a request could be served by more than one kind of trigger, prefer the one you can author completely, and say so.
Then settle the filters, before you build a single operation. For every block that needs one: pick
the scope from the flow's set, stopping and reporting the condition if the set cannot express what was
asked; delegate to the filter-building skill in a sub-agent, checking the answer as
references/filter-delegation.md says; then write the body and the scope together in one condition.
Where one clause cannot be expressed, do not narrow the filter yourself — put the choice to the user
(references/filter-delegation.md → A clause that cannot be expressed).
Then build the operations — references/graph-and-verify.md → Building the operations, before the
first batch.
A send step with no mailing to name: create one, and mind the one-way doors. One mailing per send step,
created by you with campaign_create, not through the mailing skills, because you need the identifier the
create hands back to bind the step to. The kind is the loudest thing on that call: a flow may only ever
send an automated mailing (flows → the send-step document) and the create does not default to one, so take
that value from the reference. Neither the kind nor the folder can be changed afterwards; the folder and
the time zone the call also needs are settled in the step-3 batch, and the brand it needs is no new
question — the mailing's brand is the flow's brand unless the user has said otherwise. The create takes
no name and no description — the server names the campaign — so rename it straight afterwards with
campaign_edit to a name that states its purpose, and set nothing else: no content, and no state
changes. The send step also needs the mailing's system name, which neither the create nor the
rename prints: read the mailing's record back with campaign_get after the rename and take it from
there — never by analogy with another mailing's (CRITICAL 5). It is email only: a push or SMS
step has no mailing you can create, which is a shortfall to rank (step 8).
Every answer carries a validation list — read it after every write as your progress meter
(references/graph-and-verify.md → Orphans and wiring).
Files in this skill
10flow-create skill questions
How do I install the flow-create skill in Claude Code?
Run npx degit mindbox-cloud/agent-skills/plugins/mindbox/skills/flow-create ~/.claude/skills/flow-create. Claude Code loads skills from ~/.claude/skills (all projects) or .claude/skills (one project) and uses a skill when its description matches the task.
Which clients can use the flow-create skill?
Any client that reads the Agent Skills format: Claude Code, Codex, Gemini CLI and claude.ai (upload as a ZIP). Scripts in the skill run only where the client allows code execution.
Can this skill launch or delete a marketing flow?
No, this skill is strictly for building, creating, and verifying draft flows. Launching, stopping, or deleting flows remains a human decision.
What should the agent do if it encounters a platform value it cannot find in the documentation?
The agent should not guess or derive the value; instead, it must report a documentation gap by naming the field and the document that should contain it, then stop that specific write.