Skip to content

Agents

Build a flow

Build or change a Signalbox routing flow from a description in plain English. Use when someone asks to route, qualify, assign or book inbound leads, or to change how a flow works.

An agent reads this skill with get_skill and the name build-a-flow. It is also the MCP prompt build-a-flow, and part of the Claude Code plugin.

What follows is the skill as the agent reads it.

A flow decides what happens to a lead after a HubSpot form is submitted. You write it as one document, Signalbox checks it, you test it, and a person says when it goes live.

Ask only for what you cannot look up. You need:

  • Which leads go where. The tests (“companies under 11 people”, “existing customers”) and what each group gets.
  • Who gets them. The company’s existing owner, a queue, or a named rep.
  • What the visitor sees. A calendar, more questions, a message, or nothing.
  • What HubSpot gets. A deal, a task, a property, or nothing.

If the person gave all of this, do not ask again. Carry on.

Call these before you write anything. A flow holds ids, and you must not invent one.

  1. get_started: what is connected and what is missing. If HubSpot is not connected, stop and tell the person.
  2. list_node_types: the steps there are. Then get_node_type for each type you mean to use: its settings, their shapes and its exits.
  3. list_fields: the fields a condition can test.
  4. list_queues, list_reps, list_meeting_types: the ids your settings will hold. For a deal, list_hubspot with what = pipelines.

If the flow needs a queue or a meeting type that does not exist, make it first with save_queue or save_meeting_type (Build level), and tell the person you did.

Start from create_flow with a name. It returns the three steps every flow begins with: trigger, clean, lookup. Then send the whole document with save_flow_draft.

Rules for the document:

  • Keep trigger -> clean -> lookup first, linked by next. Add your steps after lookup.
  • Give each node a short id of its own (fit, q1, cal). Leave x and y out: Signalbox places the nodes.
  • An edge is {"f": from node, "e": exit, "t": to node}. Every exit of every step needs an edge. When nothing more should happen, link the exit to an end node.
  • An If / else has one branch with the id yes, and the exits yes and no. For three or more groups use a Branch.
  • A calendar needs a rep first: put a queue, owner or person step on every path to it.
  • Steps marked slow (AI classify, Send webhook) go after the last thing the visitor sees.
  • Use the revision create_flow or get_flow gave you as fromRevision.

A small example: companies under 11 people get a message; the rest go to a queue and see a calendar.

{
"nodes": [
{"id": "t", "type": "trigger"},
{"id": "cl", "type": "clean"},
{"id": "lk", "type": "lookup"},
{"id": "size", "type": "ifelse", "label": "Under 11 people?",
"branches": [{"id": "yes", "name": "Yes", "match": "all",
"conds": [{"f": "sopro.headcount", "op": "is less than", "v": "11"}]}]},
{"id": "msg", "type": "message", "settings": {"message": "Thanks. We will be in touch."}},
{"id": "q", "type": "queue", "settings": {"queueId": "<a queue id from list_queues>"}},
{"id": "cal", "type": "calendar", "settings": {"meetingTypeId": "<a meeting type id>", "slots": "rep"}},
{"id": "done", "type": "end"}
],
"edges": [
{"f": "t", "e": "next", "t": "cl"},
{"f": "cl", "e": "next", "t": "lk"},
{"f": "lk", "e": "next", "t": "size"},
{"f": "size", "e": "yes", "t": "msg"},
{"f": "size", "e": "no", "t": "q"},
{"f": "msg", "e": "next", "t": "done"},
{"f": "q", "e": "next", "t": "cal"},
{"f": "cal", "e": "booked", "t": "done"},
{"f": "cal", "e": "notBooked", "t": "done"},
{"f": "cal", "e": "cancelled", "t": "done"}
]
}

A blank field fails every positive test. A company Sopro Data does not know has no headcount, so it takes the no exit above. Say so to the person when it matters, and add an is blank test if they want those leads handled apart.

Every save returns issues and an outline.

  • Fix every issue with severity error. Each has a fix that says what to change. Save again. Repeat until canPublish is true.
  • Read each warning and tell the person about any that matter.
  • Read the outline. It is the flow in words. If it does not say what the person asked for, the flow is wrong.

Call dry_run_flow once for each group of leads the person described, with sample form values. Nothing is written. Check that path goes down the branch you expect.

  • With a real company email, the company lookup and the HubSpot read are real.
  • A dry run stops at the first step that waits for the visitor (a calendar, questions). That is expected.

If a sample goes the wrong way, read the step’s evidence, fix the draft and test again.

Show them the outline, what each sample lead did, any warnings, and the link to the flow in the editor.

Do not publish until they say yes. Publishing changes what real visitors get. When they say yes:

  1. publish_flow (Publish level).
  2. If the flow should run for a form that has no flow, ask which form, then set_form_flow. Check the form’s routingOn; turn it on with set_form_routing only if they agree.

If your level is too low, the refusal says so. Tell the person the draft is ready and give them the link: they can publish it themselves or connect you again at a higher level.

Call get_flow. Change that document: keep every node you are not changing exactly as it is, with its x and y. Leave x and y off new nodes only if you are happy for the whole flow to be laid out again; otherwise give new nodes a position near their neighbours. A setting shown as [hidden] is a secret: send it back as it is and the stored value is kept. Save with the revision you read. Then check, test and ask as above.