docs
/
AI skills

Build a CRM Blueprint

Turn a Blueprint's design into the real system — each block built with the app that delivers it, each wire made real, and every record linked back to its block — stopping for a yes before anything goes out to people or costs money.

A Blueprint is a design until it is built. Building it means making each block real with the app that already does that job, then linking the block to the record it became (blueprint_link). Nothing on the canvas is a second version of an app.

Ask first

  • Which blueprint — its id (the person has it open, or find_records on blueprint).
  • Blank blocks — each holds only an instruction. If an instruction does not say enough to build from (which pipeline, which stage, what to send), ask; don't guess.
  • Nothing else: the design says what to build.

Steps

1. CRM Blueprints: read the design

blueprint_view { id }. Note every block whose state is design or changed, every blank block, and every wire with no record.

Fill blank blocks first: for each, choose the block type from blueprint_catalogue that does what its instruction says, then blueprint_edit → update_block with its type, label and settings. Tell the person what each blank became.

2. Get the build plan

blueprint_build_plan { id } lists every block still to build, in order: what it becomes, its app, its skills page, and for each wire the exact setting that makes it real, with the ids already filled in. Work from it — don't search the API or read schemas for what the plan already says. Load a block's skills page only for what the plan leaves open (e.g. the wording of an email).

2. Build the blocks — in this order, each with its own app

Build what others point at first, so their ids exist when wires need them:

  1. Pipeline — the Lead acquisition page, steps 1–3: the pipeline with the design's stages (won and lost), scoring and assignment rules.
  2. Customer group — as in Newsletter setup.
  3. Website form — the collection and the form, Lead acquisition steps 4–5.
  4. Lead Finder list — a prospect_list with the design's steps, Find leads. Do not run it.
  5. Follow-up — an automation with status: "draft", New-lead follow-up.
  6. Broadcast — a draft, Email campaign draft.

After each: blueprint_link { id, blockId, datatype, recordId } — the record must be the block's kind (a follow-up is an automation). If the answer says it cannot run until fixed (a call step with no script, a missing sender…), fix that record with its own tools and link it again — never leave a block that cannot run. A block whose settings hold copyOf was copied from a built blueprint: make the same thing again (read that record for what it was). A changed block: update its existing record (the same app's update), then link again. If a block cannot be built, blueprint_link { …, state: "failed", note: "<why>" } and carry on with the others. If a person must act first (connect an account, verify a sender), state: "design" with that in note.

Check: blueprint_view again — every block you built is built and shows its record's content.

3. Make the wires real

Each wire becomes the link its two apps already support:

WireWhat makes it real
Website form → a pipeline stagean automation (draft) whose trigger is the form's answers — a form bound to a collection: database_change on that collection, operation: "created"; a form without one: form_submitted with the form's formId — and whose step create_lead has that pipelineId and stageId. Then blueprint_link { wireId, datatype: "automation", recordId }
Lead Finder list → a pipeline stageits move step's pipelineId / stageId
A pipeline stage → Follow-upthe follow-up automation's trigger: pipeline_stage_changed with { pipelineId, stageId } — it runs each time a lead enters that stage (new leads arriving there included)
Customer group → Broadcastthe broadcast's selectedLists: [<group id>]
Email template → Broadcastthe broadcast's emailConfig.templateId: <template sk or name>
Email template → Follow-upthe follow-up's send_email step templateIds: [<template sk>]
Broadcast "clicked through" → Web pagethe page's link in the email; to act on the click, a follow-up with trigger email_clicked { emailId: <broadcast sk>, linkUrl: <part of the page's address> }
Broadcast "Opened" / "Clicked a link" → Follow-upthe follow-up's trigger: email_opened or email_clicked with emailId: <broadcast sk> (and linkUrl: <part of the link> for one link)
Web page "A known visitor viewed it" → Follow-upthe follow-up's trigger: page_visited with pageUrl: "/<the page's address>"
Follow-up → a pipeline stagea move_pipeline_stage step in the follow-up with stageName: <the stage's id or name> (and pipelineId) — e.g. after a call answered and agreed
Campaign → Web pagethe campaign's landingPage: the page's full address on the site
Retargeting audience → Campaignthe campaign's audienceIds: [<audience sk>]
Follow-up → Reservation definitionthe follow-up's make_call step with reservationDefinitionId: <definition sk> and a reason that says to offer a time and book it
Reservation definition "Booked" → Follow-uptrigger database_change { datatype: "reservation", operation: "created", whereField: "data.reservationDefinitionId", whereValue: <definition sk> }
Reservation definition "Attended" / "Missed" / "Cancelled" → Follow-uptrigger database_change { datatype: "reservation", operation: "updated", changedField: "data.status", changedTo: "used" / "no_show" / "cancelled", whereField: "data.reservationDefinitionId", whereValue: <definition sk> }
"…unless they booked again" inside a follow-upa record_exists condition { datatype: "reservation", match: { "data.customer.email": "{{data.customer.email}}", "data.reservationDefinitionId": <definition sk> }, createdAfter: "{{record.createdate}}", thenStepId, elseStepId } — a booking keeps the person under data.customer ({{data.customer.phone}}, {{data.customer.email}}, {{data.customer.name}})
"Ask them to confirm they'll be there" after Bookedsend_sms asking them to reply CONFIRM (not YES — YES, START and STOP are carrier keywords that subscribe or unsubscribe the number) → wait_for_reply { messageType: "sms", maxWait, maxWaitUnit, replyKeywords: "confirm", timeoutAction: "continue" } → if_then { condition: { field: "reply.text", operator: "exists" } }: then update_reservation { reservationId: "{{record.sk}}", status: "confirmed" }; else wait_until_date { targetDate: "{{data.startTime}}", offset: -2, offsetUnit: "hours" } → record_exists { datatype: "reservation", match: { "sk": "{{record.sk}}", "data.status": "new" } } (still unconfirmed) → make_call whose reason asks if they will be there and gives the booking number {{data.name}} and email, so the AI can confirm it
Web page → Retargeting audiencecreate_website_audience { name, include: ["<the page's address, e.g. /pricing>"], exclude: ["<the page that means they converted, e.g. /thank-you>"], retentionDays, platforms }, then blueprint_link { blockId, datatype: "custom_audience", recordId }. The answer says what was made on Meta and on Google Ads; anything not made (not connected, no ad account, no Meta Pixel on the site) goes in the block's note — the person fixes it in Ads › Connections or Site settings › Tracking.
Lead Finder list → Broadcastthe broadcast's selectedLists: [<list id>]

Check: blueprint_view — the links it reads from the records match the wires drawn.

4. Show it

Open the blueprint (CRM Blueprints, the blueprint) — every block shows its record and numbers.

Stop: list what is switched off or a draft and waits for a yes — each follow-up automation (it sends, calls or texts real people once on), each broadcast (a person sends it). Turn an automation on (call_appengine POST /automation/start/<sk>; set_automation_status alone doesn't connect its trigger) only after a yes for that automation.

When it's done

Tell the person: what was built (block by block, with its app), which wires are real, what failed and why, and what waits for their yes.

Don'ts

  • Don't invent what the business offers. Pages, emails, texts and ads state only what the person wrote in the blueprint or what the business's own content says: its pages, products, services and knowledge base. No made-up offers, prices, discounts, guarantees or numbers. Where something is missing, leave a clear placeholder ([Your offer]) and tell the person what to add.

  • Don't guess a form's address. Link a form only with its link from blueprint_build_plan (site.forms); link a page with the site's base address plus the page's address.

  • "Book a call", "Book now" and any other booking button opens the booking calendar, not a form: use the booking block's link from blueprint_build_plan (site.bookings). Visitors pick a time there and are booked straight away.

  • Don't build a block any way but its own app's actions; never write a pipeline, a lead or a form's answers as raw records.

  • Don't link a record that was not really created.

  • Don't send, publish, run a Lead Finder search or switch anything on without a yes.