Graine AI

Sample workflows

Twelve ready-made outreach workflows to start from — call and try again, qualify leads, call at most 3 times a week across all agents, payment and renewal reminders, appointment and order confirmation, feedback, a CRM deal follow-up, and for people of your app ringing in the app, booking a call in their app and following up after a chat — what each does, the fields it reads, and how to start from one.

Every sample is a complete workflow that passes Check as soon as you choose the agent that places its calls. Start from one, then change it to fit: rename the steps, change the waits, add a path.

In the dashboard: Workflows → Outreach → New workflow, pick a sample, then choose the agent.

With an API key: create the workflow from the sample's id. The agent goes into every Call step:

curl -X POST https://api.graine.ai/v2/workflows \
  -H "Authorization: Bearer $GRAINE_API_KEY" -H "Content-Type: application/json" \
  -d '{"sample": "lead_qualification", "agent_id": "agt_0123"}'

GET /v2/workflow-samples lists every sample with its full definition.

Two things to set up first

A sample that reads from the call needs those fields in the agent's Custom Analysis, with the names it lists. And its Send to your system steps point at example.com addresses: replace them with your own before you publish.

The samples

Call and try again

Call each contact; when nobody answers or the call doesn't get through, try again 2 minutes, 30 minutes and 4 hours later.

StepKind
Contact entersStart
Call the contactCall
Try again laterTry again

Ends as: reached (success), unreached (failure).

Sample id: call_and_retry

Qualify new leads

Call a new lead while the enquiry is fresh, send hot leads to your CRM, and call warm ones again two days later.

Reads from the call: interest_level (text: hot, warm or cold), budget (number: their budget).

StepKind
Contact entersStart
Call the new leadCall
Try again laterTry again
How interested are they?Read call results
Send the lead to your CRMHTTP request
Give them two daysWait
Call againCall
Ready now?Read call results

Ends as: qualified (success), crm_failed (neutral), not_qualified (neutral), unreached (failure).

Sample id: lead_qualification

Call, at most 3 times a week across all agents

Before each call, check how many times this person was called in the last 7 days — by any of your agents, campaigns, workflows or the API — and stop at 3. Otherwise call, and try again 4 hours, a day and two days later.

Every try goes back to Check call history, so each one is counted again, and a call someone else's list placed meanwhile counts too. When the history can't be read just then, the run ends rather than call without knowing.

StepKind
Contact entersStart
Called 3 times this week?Check call history
Call the contactCall
Try again laterTry again

Ends as: reached (success), called_enough (neutral), history_unavailable (neutral), unreached (failure).

Sample id: capped_calls

Payment reminder with a promise to pay

Remind about a payment, record a promise to pay in your billing system, and call again on the due date.

Reads from the call: promised_to_pay (yes/no: they promised to pay), promised_amount (number: how much they promised).

StepKind
Contact entersStart
Remind about the paymentCall
Try again laterTry again
Did they promise to pay?Read call results
Record the promiseHTTP request
Wait for the due dateWait
Call on the due dateCall

Ends as: promise_recorded (success), not_recorded (neutral), no_promise (neutral), unreached (failure).

Sample id: payment_reminder

Confirm an appointment

Confirm a booking; when they need another time, ask your booking system and wait for the new one.

Reads from the call: confirmed (yes/no: they will come), wants_new_time (yes/no: they asked for another time).

StepKind
Contact entersStart
Confirm the appointmentCall
Try again laterTry again
Coming, or a new time?Read call results
Mark it confirmedHTTP request
Ask for a new timeHTTP request
Wait for the new bookingWait for your system

Ends as: confirmed (success), rescheduled (success), reschedule_pending (neutral), unclear (neutral), update_failed (neutral), unreached (failure).

Sample id: appointment_confirmation

Confirm an order before it ships

Call before dispatch; confirm or cancel the order in your store, and hold it when nobody answers or the call doesn't get through.

Reads from the call: order_confirmed (yes/no: they still want it).

StepKind
Contact entersStart
Confirm the orderCall
Try again laterTry again
Still want it?Read call results
Confirm in your storeHTTP request
Cancel in your storeHTTP request
Hold the orderHTTP request

Ends as: confirmed (success), cancelled_by_customer (neutral), unreachable (failure), unclear (neutral), sync_failed (neutral).

Sample id: order_confirmation

Renewal reminder on a set day

Wait until the day you choose for each contact, call about the renewal, and record the answer.

Reads from the call: will_renew (yes/no: they will renew).

StepKind
Contact entersStart
Wait for the call dayWait
Remind about the renewalCall
Try again laterTry again
Renewing?Read call results
Record the renewalHTTP request

Ends as: renewing (success), not_renewing (failure), undecided (neutral), crm_failed (neutral), unreached (failure).

Sample id: renewal_reminder

Ask for feedback

A day later, ask how it went; open a support ticket for a low rating.

Reads from the call: rating (number: 1 to 5), issue (text: what went wrong, if anything).

StepKind
Contact entersStart
Wait a dayWait
Ask for feedbackCall
Try again laterTry again
How did it go?Read call results
Open a support ticketHTTP request

Ends as: promoter (success), passive (neutral), needs_attention (neutral), no_response (failure).

Sample id: feedback_survey

Follow up until your CRM closes the deal

Open a deal for an interested contact and wait, up to two weeks, for your CRM to say it was won or lost; check in by phone if it says nothing.

Reads from the call: interested (yes/no: they want to hear more).

StepKind
Contact entersStart
Introduce the offerCall
Try again laterTry again
Interested?Read call results
Open a deal in your CRMHTTP request
Wait for the deal to closeWait for your system
Check inCall

Ends as: won (success), lost (failure), no_decision (neutral), not_interested (neutral), crm_failed (neutral), unreached (failure).

Sample id: deal_follow_up

Ring in the app, then try again

Ring each person in your app — now, or at the time you give for them — and when nobody answers, try again 2 minutes, 30 minutes and 4 hours later.

Each contact brings user_id, their ID in your app, and may bring preferred_time: without one the app rings now, and every try after the first rings when it comes.

StepKind
Contact entersStart
Ring them in the appCall, in their app
Try again laterTry again

Ends as: reached (success), unreached (failure).

Sample id: ring_in_app_and_retry

Book a call in their app

Book a call in each person's app for the time you give, then follow how it went: talked, declined or missed.

Each contact brings user_id and preferred_time. The call shows in the person's upcoming calls in your app until it rings.

StepKind
Contact entersStart
Book a call in their appCall, in their app

Ends as: talked (success), declined (neutral), missed (failure), not_rung (failure).

Sample id: book_in_app

After a chat, follow up

When a chat with someone your app identifies ends and they asked for a call, book it in their app for the time they said.

Reads from the chat: wants_call (yes/no: they asked to be called), preferred_time (text: when they want the call, as a date and time with its offset). Start it with Start when a call ends, with Chats counted: the run is for the person who chatted, and a time they didn't give rings now.

StepKind
Contact entersStart
Did they ask for a call?Read call results
Book the call they asked forCall, in their app

Ends as: called (success), unreached (neutral), not_rung (failure), no_call (neutral).

Sample id: chat_follow_up

A sample in full

The Qualify new leads sample, as the API returns it with an agent chosen:

{
  "entry_node_id": "start",
  "on_no_match": "not_qualified",
  "nodes": [
    {
      "id": "start",
      "type": "start",
      "name": "Contact enters",
      "config": {
        "fields": [
          {
            "name": "source",
            "type": "string"
          },
          {
            "name": "product",
            "type": "string"
          }
        ]
      },
      "cases": [
        {
          "when": {
            "always": true
          },
          "then": {
            "to": "call"
          }
        }
      ]
    },
    {
      "id": "call",
      "type": "agent",
      "name": "Call the new lead",
      "config": {
        "agent_id": "agt_0123",
        "timeout_s": 1800
      },
      "cases": [
        {
          "when": {
            "cmp": "==",
            "left": {
              "var": "call.status"
            },
            "right": {
              "const": "completed"
            }
          },
          "then": {
            "to": "facts"
          }
        },
        {
          "when": {
            "cmp": "in",
            "left": {
              "var": "call.status"
            },
            "right": {
              "const": [
                "busy",
                "no_answer",
                "voicemail",
                "failed"
              ]
            }
          },
          "then": {
            "to": "again"
          }
        }
      ],
      "on_no_match": "unreached"
    },
    {
      "id": "again",
      "type": "retry",
      "name": "Try again later",
      "config": {
        "target_node_id": "call",
        "attempts": [
          {
            "delay": {
              "minutes": 5
            }
          },
          {
            "delay": {
              "hours": 1
            }
          }
        ]
      },
      "cases": [
        {
          "when": {
            "always": true
          },
          "then": {
            "to": "unreached"
          }
        }
      ]
    },
    {
      "id": "facts",
      "type": "extraction",
      "name": "How interested are they?",
      "config": {
        "agent_node_id": "call",
        "selected": [
          "interest_level",
          "budget"
        ]
      },
      "cases": [
        {
          "when": {
            "cmp": "==",
            "left": {
              "var": "extraction.interest_level"
            },
            "right": {
              "const": "hot"
            }
          },
          "then": {
            "to": "crm",
            "effects": [
              {
                "set_value": {
                  "state.temperature": {
                    "const": "hot"
                  }
                }
              }
            ]
          }
        },
        {
          "when": {
            "cmp": "==",
            "left": {
              "var": "extraction.interest_level"
            },
            "right": {
              "const": "warm"
            }
          },
          "then": {
            "to": "nurture"
          }
        }
      ],
      "on_no_match": "not_qualified"
    },
    {
      "id": "crm",
      "type": "api",
      "name": "Send the lead to your CRM",
      "config": {
        "method": "POST",
        "url": "https://crm.example.com/api/leads",
        "body": {
          "phone": "{phone}",
          "name": "{name}",
          "budget": "{budget}",
          "source": "{source}"
        },
        "variables": {
          "phone": {
            "value": {
              "var": "entry.mobile_number"
            },
            "required": true
          },
          "name": {
            "value": {
              "var": "entry.name"
            }
          },
          "budget": {
            "value": {
              "var": "extraction.budget"
            },
            "type": "number"
          },
          "source": {
            "value": {
              "var": "entry.source"
            }
          }
        },
        "timeout_s": 20
      },
      "cases": [
        {
          "when": {
            "cmp": "<",
            "left": {
              "var": "response.status"
            },
            "right": {
              "const": 300
            }
          },
          "then": {
            "to": "qualified"
          }
        }
      ],
      "on_no_match": "crm_failed"
    },
    {
      "id": "nurture",
      "type": "time",
      "name": "Give them two days",
      "config": {
        "delay": {
          "days": 2
        },
        "to": "second_call"
      }
    },
    {
      "id": "second_call",
      "type": "agent",
      "name": "Call again",
      "config": {
        "agent_id": "agt_0123",
        "timeout_s": 1800
      },
      "cases": [
        {
          "when": {
            "cmp": "==",
            "left": {
              "var": "call.status"
            },
            "right": {
              "const": "completed"
            }
          },
          "then": {
            "to": "second_facts"
          }
        },
        {
          "when": {
            "cmp": "in",
            "left": {
              "var": "call.status"
            },
            "right": {
              "const": [
                "busy",
                "no_answer",
                "voicemail",
                "failed"
              ]
            }
          },
          "then": {
            "to": "not_qualified"
          }
        }
      ],
      "on_no_match": "not_qualified"
    },
    {
      "id": "second_facts",
      "type": "extraction",
      "name": "Ready now?",
      "config": {
        "agent_node_id": "second_call",
        "selected": [
          "interest_level"
        ]
      },
      "cases": [
        {
          "when": {
            "cmp": "==",
            "left": {
              "var": "extraction.interest_level"
            },
            "right": {
              "const": "hot"
            }
          },
          "then": {
            "to": "crm"
          }
        }
      ],
      "on_no_match": "not_qualified"
    },
    {
      "id": "qualified",
      "type": "end",
      "name": "Qualified",
      "config": {
        "label": "qualified",
        "outcome": "success"
      },
      "cases": []
    },
    {
      "id": "crm_failed",
      "type": "end",
      "name": "CRM did not take it",
      "config": {
        "label": "crm_failed",
        "outcome": "neutral"
      },
      "cases": []
    },
    {
      "id": "not_qualified",
      "type": "end",
      "name": "Not qualified",
      "config": {
        "label": "not_qualified",
        "outcome": "neutral"
      },
      "cases": []
    },
    {
      "id": "unreached",
      "type": "end",
      "name": "Could not reach",
      "config": {
        "label": "unreached",
        "outcome": "failure"
      },
      "cases": []
    }
  ]
}