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:
- Queries customer transaction data from your database
- Analyzes revenue trends using statistical regression
- Identifies customers with declining engagement
- Uses AI to generate personalized retention recommendations
- 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
| Tool | Purpose |
|---|---|
query | Execute PRQL queries against your data sources |
json | Transform and filter data |
regression | Statistical trend analysis |
llm | AI-powered recommendation generation |
markdown_table_formatter | Format data as readable tables |
email | Send 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:
- Change the analysis window: Edit the date filter from 6 months to 3 months
- Adjust the decline threshold: Change from 20% to 15%
- Update email recipients: Add additional team members
- 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
- Click "Run Now" to execute manually
- Watch real-time progress via the execution panel
- Review each node's output
- 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
- Navigate to your agent in the dashboard
- Click "Run Now"
- Watch execution progress in real-time
- 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 08- At hour 8 (8 AM)*- Every day of month*- Every monthMON- 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:
- Support ticket analysis: Flag customers with increased support requests
- Login frequency: Track declining platform usage
- NPS scores: Incorporate customer satisfaction data
- 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:
- Design a workflow with multiple tools working together
- Use the conversational builder to create agents through natural language
- Refine in the visual editor by adjusting node configurations
- Configure scheduling and monitoring for automated execution
- 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:
- Agent Builder - API reference
- Workflow Builder - Real-time execution
- AI Infrastructure Overview - System overview
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]"
}
}
}