Skip to main content

Tutorial: Building a Customer Health Monitoring Agent

This tutorial walks you through building a practical business automation agent that monitors customer health and proactively alerts your sales team to at-risk accounts.

What You'll Build

A Customer Health Monitoring Agent that:

  1. Queries customer transaction data from your database
  2. Analyzes revenue trends using statistical regression
  3. Identifies customers with declining engagement
  4. Uses AI to generate personalized retention recommendations
  5. Emails a weekly report to your sales team

Business Value: Early warning system enabling proactive retention efforts before customers churn.

Target Audience: Sales Operations, RevOps, Customer Success teams.

Prerequisites

  • Access to the Datafi platform
  • A data source with customer transaction data configured
  • Email service configured for notifications

Reference: Complete Agent Spec

This tutorial includes a fully built agent specification you can use to:

  • Compare your work - Verify your agent matches the expected structure
  • Import directly - Skip the builder and load via API for quick testing
  • Use as a template - Copy and modify for similar workflows

See the Appendix at the end of this tutorial for the complete JSON specification.

Part 1: Understanding the Workflow

Workflow Overview

Start


[Query] ── Fetch customer transaction data (last 6 months)


[JSON Transform] ── Group by customer, calculate monthly totals


[Regression] ── Analyze revenue trends per customer


[JSON Transform] ── Filter at-risk customers (>20% decline)


[Condition] ── Any at-risk customers found?

├── No → [End]

▼ Yes
[LLM] ── Generate retention recommendations


[Markdown Table] ── Format the report


[Email] ── Send to sales team


End

Tools Used

ToolPurpose
queryExecute PRQL queries against your data sources
jsonTransform and filter data
regressionStatistical trend analysis
llmAI-powered recommendation generation
markdown_table_formatterFormat data as readable tables
emailSend notifications

Node Types

  • Start: Entry point of the workflow
  • Action: Executes a tool (query, email, etc.)
  • Transform: Manipulates data (JSON operations)
  • Condition: Branches based on logic
  • End: Exit point of the workflow

Part 2: Using the Conversational Builder

The agent builder uses a conversational AI interface to help you create workflows through natural language.

Step 1: Start a New Session

Navigate to the Agent Builder and start a new session with your initial description:

"Create an agent that monitors customer health and alerts the sales team
when customers show declining engagement"

The AI will acknowledge your request and ask clarifying questions.

Step 2: Clarify Your Data Source

AI asks: "What data source contains your customer transaction history?"

Your response:

"Sales transactions from our database. The table is Sales.CustomerTransactions
with columns: customer_id, customer_name, transaction_date, and amount"

Step 3: Define At-Risk Criteria

AI asks: "How should I identify at-risk customers?"

Your response:

"Look for customers with a declining revenue trend over the past 6 months.
Specifically, flag those with 20% or more drop from their peak monthly revenue."

Step 4: Specify Actions

AI asks: "What should happen when at-risk customers are found?"

Your response:

"Use AI to generate personalized retention recommendations for each customer,
then email a summary report to [email protected]"

Step 5: Set the Schedule

AI asks: "How often should this agent run?"

Your response:

"Weekly on Monday mornings at 8 AM"

Step 6: Generate the Workflow

When the confidence indicator reaches the threshold (typically 80%+), click "Generate Workflow".

The system will create a graph-based workflow with nodes and edges that you can review and refine.

Part 3: Refining in the Visual Editor

After generation, the visual editor displays your workflow as a connected graph. Here's how to refine it:

Inspecting Nodes

Click on any node to view its configuration:

Query Node Example:

{
"tool": "query",
"inputs": {
"query": "from Sales.CustomerTransactions\nfilter transaction_date >= @start_date\nselect {customer_id, customer_name, transaction_date, amount}"
}
}

Adjusting Parameters

Common adjustments you might make:

  1. Change the analysis window: Edit the date filter from 6 months to 3 months
  2. Adjust the decline threshold: Change from 20% to 15%
  3. Update email recipients: Add additional team members
  4. Modify the LLM prompt: Customize the recommendation style

Adding Guard Rails

In the agent settings, configure safety limits:

{
"guards": {
"resourceLimits": {
"maxTokensPerRequest": 10000,
"maxApiCallsPerRun": 100,
"dailyTokenBudget": 50000
},
"constraints": [
"Never modify production data",
"PII must be masked in email outputs"
]
}
}

Testing Your Workflow

  1. Click "Run Now" to execute manually
  2. Watch real-time progress via the execution panel
  3. Review each node's output
  4. Check the email format and content

Part 4: Sample Code & Configuration

Sample PRQL Query

This query fetches customer transactions and calculates monthly aggregates:

from Sales.CustomerTransactions
filter transaction_date >= @2024-01-01
derive year_month = s"DATE_TRUNC('month', {transaction_date})"
group {customer_id, customer_name, year_month} (
aggregate {
monthly_total = sum amount,
transaction_count = count this
}
)
sort {customer_id, year_month}

JSON Transform: Group by Customer

After querying monthly data, group by customer for regression analysis:

{
"operation": "group",
"groupBy": ["customer_id"],
"collect": {
"customer_name": "first",
"monthly_data": "array"
}
}

Regression Analysis Input

The regression tool expects data in this format:

{
"data": [
{"month": 1, "revenue": 5000},
{"month": 2, "revenue": 4800},
{"month": 3, "revenue": 4200},
{"month": 4, "revenue": 3900},
{"month": 5, "revenue": 3500},
{"month": 6, "revenue": 3200}
],
"xColumn": "month",
"yColumn": "revenue"
}

Output:

{
"slope": -340,
"intercept": 5340,
"r_squared": 0.98,
"confidence_intervals": {
"slope_95": [-380, -300],
"intercept_95": [5100, 5580]
}
}

A negative slope indicates declining revenue.

LLM Prompt for Recommendations

Analyze this customer's transaction history and declining trend.

Customer: ${customer_name}
Peak Monthly Revenue: $${peak_mrr}
Current Monthly Revenue: $${current_mrr}
Decline: ${decline_percentage}%
Months of Decline: ${decline_months}

Based on this data, generate 2-3 specific, actionable retention
recommendations for the sales team to re-engage this customer.
Focus on practical steps that can be taken within the next 2 weeks.

Email Template

The markdown table formatter creates a report like this:

## Weekly At-Risk Customer Alert

**Report Date**: Monday, January 15, 2024
**At-Risk Customers Found**: 3

| Customer | Current MRR | Decline | Recommended Actions |
|----------|-------------|---------|---------------------|
| Acme Corp | $3,200 | -36% | Schedule executive check-in; Offer loyalty discount |
| Beta Inc | $1,800 | -25% | Review recent support tickets; Propose product training |
| Gamma LLC | $950 | -22% | Reach out about renewal; Highlight new features |

---
*Generated by Customer Health Monitoring Agent*

Part 5: Running and Monitoring

Manual Execution

  1. Navigate to your agent in the dashboard
  2. Click "Run Now"
  3. Watch execution progress in real-time
  4. View node-by-node output in the execution log

Scheduled Execution

Configure the schedule in the agent's lifecycle settings:

{
"lifecycle": {
"trigger": {
"type": "Schedule",
"config": {
"cron": "0 8 * * MON",
"timezone": "America/New_York"
}
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "Exponential",
"initialDelaySeconds": 60
}
}
}

Cron expression breakdown:

  • 0 - At minute 0
  • 8 - At hour 8 (8 AM)
  • * - Every day of month
  • * - Every month
  • MON - On Mondays

Monitoring Execution History

Track your agent's performance:

  • Run History: View past executions, success/failure status
  • Execution Logs: Detailed output from each node
  • Token Usage: Monitor LLM token consumption
  • Error Tracking: Identify and debug failures

Part 6: Next Steps

Customize for Your Data

Replace the placeholder table and column names with your actual schema:

-- Before (placeholder)
from Sales.CustomerTransactions

-- After (your data)
from Production.Orders
join Customers on (Orders.customer_id == Customers.id)

Add Human Approval

Insert a HumanInput node before the email step to review the report:

{
"type": "HumanInput",
"data": {
"label": "Review At-Risk Report",
"prompt": "Please review the at-risk customer report before sending to the sales team.",
"options": ["Approve and Send", "Edit Report", "Cancel"]
}
}

Expand Your Analysis

Add more sophisticated churn indicators:

  1. Support ticket analysis: Flag customers with increased support requests
  2. Login frequency: Track declining platform usage
  3. NPS scores: Incorporate customer satisfaction data
  4. Contract renewal dates: Prioritize customers approaching renewal

Build More Agents

Apply the same patterns to other business problems:

  • Lead Scoring Agent: Score and prioritize inbound leads
  • Revenue Forecasting Agent: Generate weekly revenue projections
  • Competitor Monitoring Agent: Track competitor pricing and features
  • Invoice Reconciliation Agent: Automate invoice matching and discrepancy detection

Summary

You've learned how to:

  1. Design a workflow with multiple tools working together
  2. Use the conversational builder to create agents through natural language
  3. Refine in the visual editor by adjusting node configurations
  4. Configure scheduling and monitoring for automated execution
  5. Customize for your specific data and business requirements

The Customer Health Monitoring Agent demonstrates a practical pattern: query data, analyze with statistics and AI, make decisions, and take action. This pattern applies to countless business automation scenarios.

For more information, see:


Appendix: Complete Agent Specification

Below is the complete agent specification for the Customer Health Monitoring Agent. Use this to compare your work or import directly via the addAgent API.

{
"identity": {
"name": "customer-health-monitor",
"version": "1.0.0",
"description": "Monitors customer transaction trends and alerts sales team to at-risk accounts with AI-generated retention recommendations",
"author": "Datafi",
"tags": ["sales", "customer-success", "churn-prevention", "analytics"],
"goals": [
"Identify customers with declining revenue trends",
"Generate actionable retention recommendations",
"Deliver weekly alerts to sales team"
],
"successCriteria": [
{
"metric": "at_risk_detection_rate",
"target": 0.9,
"measurement": "detected_churned / actual_churned"
},
{
"metric": "report_delivery",
"target": "100%",
"measurement": "reports_sent / reports_scheduled"
}
]
},
"capabilities": {
"tools": [
{ "name": "query", "permissions": { "operations": ["Read"] } },
{ "name": "json", "permissions": { "operations": ["Read"] } },
{ "name": "regression", "permissions": { "operations": ["Read"] } },
{ "name": "llm", "permissions": { "operations": ["Read"] } },
{ "name": "markdown_table_formatter", "permissions": { "operations": ["Read"] } },
{ "name": "email", "permissions": { "operations": ["Write"] } }
],
"skills": ["trend_analysis", "churn_prediction", "report_generation"],
"maxIterations": 25
},
"behavior": {
"personality": {
"tone": "professional",
"verbosity": "concise",
"jargonLevel": "business_appropriate"
},
"reasoningStrategy": {
"approach": "StepByStep",
"confidenceThreshold": 0.75
},
"memoryType": { "mode": "ShortTermOnly" }
},
"guards": {
"constraints": [
"Never modify production data",
"PII must be masked in email outputs",
"Only read from approved data sources"
],
"resourceLimits": {
"maxTokensPerRequest": 10000,
"maxApiCallsPerRun": 100,
"dailyTokenBudget": 50000
}
},
"lifecycle": {
"trigger": {
"type": "Schedule",
"config": {
"cron": "0 8 * * MON",
"timezone": "America/New_York"
}
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "Exponential",
"initialDelaySeconds": 60,
"retryOn": ["timeout", "rate_limit", "service_unavailable"]
}
},
"integration": {
"inputSchema": {
"type": "object",
"properties": {
"lookback_months": {
"type": "integer",
"default": 6,
"description": "Number of months to analyze"
},
"decline_threshold": {
"type": "number",
"default": 0.2,
"description": "Minimum decline percentage to flag (0.2 = 20%)"
},
"email_recipients": {
"type": "string",
"default": "[email protected]",
"description": "Email address for alerts"
}
}
},
"outputSchema": {
"type": "object",
"properties": {
"at_risk_count": { "type": "integer" },
"report_sent": { "type": "boolean" }
}
}
},
"monitoring": {
"loggingLevel": { "default": "Info" },
"metricsToTrack": [
{ "metric": "customers_analyzed", "type": "Counter" },
{ "metric": "at_risk_detected", "type": "Counter" },
{ "metric": "execution_duration_seconds", "type": "Histogram" }
],
"telemetryAttributes": {
"serviceName": "customer-health-monitor",
"team": "sales-ops"
}
},
"workflow": {
"nodes": [
{
"id": "start_1",
"type": "customNode",
"position": { "x": 100, "y": 100 },
"data": {
"id": "start_1",
"type": "Start",
"label": "Start",
"name": "Start",
"description": "Workflow entry point",
"outputAnchors": [{ "id": "start_1_out", "name": "output" }]
}
},
{
"id": "query_transactions",
"type": "customNode",
"position": { "x": 100, "y": 200 },
"data": {
"id": "query_transactions",
"type": "Action",
"label": "Query Customer Transactions",
"name": "query",
"description": "Fetch customer transaction data for the analysis period",
"inputs": {
"query": "from Sales.CustomerTransactions\nfilter transaction_date >= @start_date\nderive year_month = s\"DATE_TRUNC('month', {transaction_date})\"\ngroup {customer_id, customer_name, year_month} (\n aggregate {\n monthly_total = sum amount,\n transaction_count = count this\n }\n)\nsort {customer_id, year_month}"
},
"outputAnchors": [{ "id": "query_transactions_out", "name": "data" }]
}
},
{
"id": "group_by_customer",
"type": "customNode",
"position": { "x": 100, "y": 300 },
"data": {
"id": "group_by_customer",
"type": "Transform",
"label": "Group by Customer",
"name": "json",
"description": "Group monthly data by customer for trend analysis",
"inputs": {
"operation": "group",
"groupBy": ["customer_id"],
"collect": { "customer_name": "first", "monthly_data": "array" }
},
"outputAnchors": [{ "id": "group_by_customer_out", "name": "grouped_data" }]
}
},
{
"id": "analyze_trends",
"type": "customNode",
"position": { "x": 100, "y": 400 },
"data": {
"id": "analyze_trends",
"type": "Action",
"label": "Analyze Revenue Trends",
"name": "regression",
"description": "Perform linear regression on each customer's monthly revenue",
"inputs": {
"xColumn": "month_index",
"yColumn": "monthly_total",
"confidenceLevel": 0.95
},
"outputAnchors": [{ "id": "analyze_trends_out", "name": "trends" }]
}
},
{
"id": "filter_at_risk",
"type": "customNode",
"position": { "x": 100, "y": 500 },
"data": {
"id": "filter_at_risk",
"type": "Transform",
"label": "Filter At-Risk Customers",
"name": "json",
"description": "Filter customers with negative slope and >20% decline",
"inputs": {
"operation": "filter",
"expression": ".slope < 0 and .decline_percentage > 0.2"
},
"outputAnchors": [{ "id": "filter_at_risk_out", "name": "at_risk" }]
}
},
{
"id": "check_at_risk",
"type": "customNode",
"position": { "x": 100, "y": 600 },
"data": {
"id": "check_at_risk",
"type": "Condition",
"label": "Any At-Risk Customers?",
"name": "condition",
"description": "Check if any at-risk customers were found",
"inputs": { "expression": "length(${at_risk}) > 0" },
"outputAnchors": [
{ "id": "check_at_risk_true", "name": "true", "label": "Yes" },
{ "id": "check_at_risk_false", "name": "false", "label": "No" }
]
}
},
{
"id": "generate_recommendations",
"type": "customNode",
"position": { "x": 100, "y": 700 },
"data": {
"id": "generate_recommendations",
"type": "Action",
"label": "Generate Retention Recommendations",
"name": "llm",
"description": "Use AI to generate personalized retention recommendations",
"inputs": {
"messages": [
{
"role": "system",
"content": "You are a customer success expert. Generate specific, actionable retention recommendations based on customer data."
},
{
"role": "user",
"content": "Analyze these at-risk customers and provide 2-3 retention recommendations for each:\n\n${at_risk_json}\n\nFor each customer, consider their decline percentage and transaction history."
}
]
},
"outputAnchors": [{ "id": "generate_recommendations_out", "name": "recommendations" }]
}
},
{
"id": "format_report",
"type": "customNode",
"position": { "x": 100, "y": 800 },
"data": {
"id": "format_report",
"type": "Action",
"label": "Format Report",
"name": "markdown_table_formatter",
"description": "Format the at-risk customer data as a markdown table",
"inputs": {
"columns": ["customer_name", "current_mrr", "decline_percentage", "recommendations"],
"columnLabels": ["Customer", "Current MRR", "Decline", "Recommended Actions"],
"sortBy": "decline_percentage",
"sortOrder": "desc"
},
"outputAnchors": [{ "id": "format_report_out", "name": "report" }]
}
},
{
"id": "send_email",
"type": "customNode",
"position": { "x": 100, "y": 900 },
"data": {
"id": "send_email",
"type": "Action",
"label": "Send Alert Email",
"name": "email",
"description": "Send the at-risk customer report to the sales team",
"inputs": {
"to": "${email_recipients}",
"subject": "Weekly At-Risk Customer Alert - ${at_risk_count} customers need attention",
"html": "<h2>Weekly At-Risk Customer Alert</h2>\n<p><strong>Report Date:</strong> ${report_date}</p>\n<p><strong>At-Risk Customers Found:</strong> ${at_risk_count}</p>\n\n${report_table}\n\n<hr>\n<p><em>Generated by Customer Health Monitoring Agent</em></p>"
},
"outputAnchors": [{ "id": "send_email_out", "name": "sent" }]
}
},
{
"id": "end_success",
"type": "customNode",
"position": { "x": 100, "y": 1000 },
"data": {
"id": "end_success",
"type": "End",
"label": "End (Report Sent)",
"name": "End",
"description": "Workflow complete - report sent"
}
},
{
"id": "end_no_risk",
"type": "customNode",
"position": { "x": 300, "y": 700 },
"data": {
"id": "end_no_risk",
"type": "End",
"label": "End (No At-Risk Customers)",
"name": "End",
"description": "Workflow complete - no at-risk customers found"
}
}
],
"edges": [
{ "id": "e_start_query", "source": "start_1", "sourceHandle": "start_1_out", "target": "query_transactions" },
{ "id": "e_query_group", "source": "query_transactions", "sourceHandle": "query_transactions_out", "target": "group_by_customer" },
{ "id": "e_group_analyze", "source": "group_by_customer", "sourceHandle": "group_by_customer_out", "target": "analyze_trends" },
{ "id": "e_analyze_filter", "source": "analyze_trends", "sourceHandle": "analyze_trends_out", "target": "filter_at_risk" },
{ "id": "e_filter_check", "source": "filter_at_risk", "sourceHandle": "filter_at_risk_out", "target": "check_at_risk" },
{ "id": "e_check_recommend", "source": "check_at_risk", "sourceHandle": "check_at_risk_true", "target": "generate_recommendations", "data": { "edgeLabel": "Yes" } },
{ "id": "e_check_end_no_risk", "source": "check_at_risk", "sourceHandle": "check_at_risk_false", "target": "end_no_risk", "data": { "edgeLabel": "No" } },
{ "id": "e_recommend_format", "source": "generate_recommendations", "sourceHandle": "generate_recommendations_out", "target": "format_report" },
{ "id": "e_format_email", "source": "format_report", "sourceHandle": "format_report_out", "target": "send_email" },
{ "id": "e_email_end", "source": "send_email", "sourceHandle": "send_email_out", "target": "end_success" }
],
"errorHandling": "FailFast",
"variables": {
"start_date": "2024-01-01",
"decline_threshold": 0.2,
"email_recipients": "[email protected]"
}
}
}