Skip to main content

Building Custom Agents

This section walks through three real MSP automation scenarios in detail: a critical security response workflow, a new client onboarding sequence, and a monthly billing reconciliation agent. These examples show how to combine the six step types into agents that solve real business problems.


Walkthrough 1: Auto-Escalate Critical Security Alerts

Scenario: When Defend detects a critical-severity threat, your team needs to know within 60 seconds, the ticket needs to exist in PSA before anyone calls a client, and the device needs to be isolated if it's confirmed ransomware — but only after a human approves.

Agent name: Critical Security Response Trigger: defend:alert.fired Trigger filter: severity eq critical Category: Security

Step 1 — AI Reason: Analyze Threat (Premium, 100 credits)

Use Premium (GPT-4o) for this step — this is exactly the kind of high-stakes, complex reasoning that warrants it.

You are an MSP security analyst. A critical security alert just fired.

Alert description: {{event_payload.description}}
MITRE tactic: {{event_payload.mitre_tactic}}
Device: {{event_payload.device_id}}
Client: {{event_payload.client_id}}
Detection confidence: {{event_payload.detection_confidence}}

Client context:
{{client_context.security_posture_score}}
{{client_context.recent_incidents}}
{{client_context.device_inventory}}

Determine:
1. The actual blast radius (what systems are likely affected or at risk)
2. Whether this is likely ransomware, data exfiltration, lateral movement, or other
3. Immediate containment recommendation
4. Client communication recommendation (notify now, notify after containment, no notification needed)

Return JSON with: blast_radius, threat_type, isolate_device (boolean), client_message (string or null), ticket_subject, ticket_body (full technical detail for technician)

Output var: analysis

Step 2 — Product Action: Create PSA Ticket

{
"product": "psa",
"action": "create_ticket",
"params": {
"org_id": "{{org_id}}",
"client_id": "{{event_payload.client_id}}",
"subject": "{{analysis.ticket_subject}}",
"description": "{{analysis.ticket_body}}",
"priority": "p1",
"type": "security_incident",
"source": "defend_alert",
"source_id": "{{event_payload.alert_id}}"
},
"on_error": "continue"
}

Output var: ticket

Step 3 — Product Action: Isolate Device (conditional)

Add a Branch step first:

  • Condition: analysis.isolate_device === true
  • True branch → Product Action: isolate device
  • False branch → (empty — continue to next step)
{
"product": "defend",
"action": "isolate_device",
"params": {
"org_id": "{{org_id}}",
"device_id": "{{event_payload.device_id}}"
},
"on_error": "continue"
}

Step 4 — Notification: SMS to On-Call Technician

{
"channel": "sms",
"recipients": ["+15551234567"],
"body": "CRITICAL SECURITY ALERT\nClient: {{event_payload.client_id}}\nThreat: {{analysis.threat_type}}\nBlast radius: {{analysis.blast_radius}}\nDevice isolated: {{analysis.isolate_device}}\nTicket: {{ticket.id}}\n\nApproval required for next steps."
}

Step 5 — Approval Gate: Confirm Remediation

{
"message": "Security incident confirmed for {{event_payload.client_id}}. Threat: {{analysis.threat_type}}. Device {{event_payload.device_id}} has been isolated. Approve to proceed with full remediation workflow (forensics collection, reimage scheduling). Deny to hold and investigate manually.",
"notify_channel": "sms",
"notify_recipients": ["+15551234567"],
"timeout_hours": 2,
"on_timeout": "deny"
}

Step 6 — Product Action: Collect Forensics (if approved)

The approval gate pauses the execution. If approved, the workflow continues to forensics collection. If denied or timed out, the execution ends with the ticket open for manual handling.

{
"product": "defend",
"action": "collect_forensics",
"params": {
"org_id": "{{org_id}}",
"device_id": "{{event_payload.device_id}}"
},
"on_error": "continue"
}

Credit Cost

This agent costs 100 credits per critical alert (one Premium AI step). At 5 critical alerts per month, that's 500 credits. The value of catching one real incident makes this the highest-ROI agent in your stack.


Walkthrough 2: New Client Onboarding Automation

Scenario: When a CRM deal is marked won, kick off a full onboarding sequence across PSA, Portal, Legal, and Relay without anyone manually tracking the steps.

Agent name: New Client Onboarding Trigger: crm:deal.won Category: Onboarding

Step 1 — AI Reason: Draft Onboarding Plan (Standard, 20 credits)

A new client deal was just won. Generate an onboarding plan.

Client: {{event_payload.client_id}}
Deal value: {{event_payload.value}}
Products purchased: {{event_payload.products}}

Create a personalized welcome message for the client contact, and a brief internal technician briefing for the onboarding tech.

Return JSON with: welcome_email_subject, welcome_email_body, tech_briefing

Output var: onboarding

Step 2 — Product Action: Create PSA Onboarding Project

{
"product": "psa",
"action": "create_project",
"params": {
"org_id": "{{org_id}}",
"client_id": "{{event_payload.client_id}}",
"name": "Client Onboarding — {{event_payload.client_id}}",
"template": "standard_onboarding",
"deal_id": "{{event_payload.deal_id}}"
},
"on_error": "continue"
}

Step 3 — Product Action: Invite Client to Portal

{
"product": "portal",
"action": "invite_user",
"params": {
"org_id": "{{org_id}}",
"client_id": "{{event_payload.client_id}}",
"email": "{{event_payload.primary_contact_email}}",
"role": "client_admin"
},
"on_error": "continue"
}
{
"product": "legal",
"action": "send_policy",
"params": {
"org_id": "{{org_id}}",
"client_id": "{{event_payload.client_id}}",
"policy_type": "msa",
"recipient_email": "{{event_payload.primary_contact_email}}"
},
"on_error": "continue"
}

Step 5 — Relay: Send Welcome Email

{
"product": "relay",
"action": "send_email",
"params": {
"org_id": "{{org_id}}",
"to": "{{event_payload.primary_contact_email}}",
"subject": "{{onboarding.welcome_email_subject}}",
"body": "{{onboarding.welcome_email_body}}"
},
"on_error": "continue"
}

Step 6 — Notification: Brief Onboarding Technician

{
"channel": "push",
"recipients": ["{{assigned_onboarding_tech}}"],
"subject": "New client assigned: {{event_payload.client_id}}",
"body": "{{onboarding.tech_briefing}}\n\nPSA project created. Portal invitation sent. MSA sent via Legal. Please review and schedule kickoff call."
}

Result

Within 60 seconds of winning a deal: the client has a portal invitation, their MSA is in their inbox, a PSA onboarding project exists, and their assigned technician has a briefing and their next steps. No manual coordination required.


Walkthrough 3: Monthly Billing Reconciliation

Scenario: On the first of every month, run a reconciliation check across all clients — identify clients with overdue balances, flag any billing discrepancies between PSA contracts and Books invoices, and create PSA tasks for the billing team.

Agent name: Monthly Billing Reconciliation Trigger: Schedule — 0 9 1 * * (9 AM on the 1st of every month) Category: Finance

Step 1 — AI Reason: Analyze Billing Health (Standard, 20 credits)

Today is the first of the month. Review the billing status across all clients and identify issues requiring action.

Organization: {{org_id}}
Overdue invoices (from context): {{client_context.overdue_invoices}}
Expiring contracts (from context): {{client_context.expiring_contracts}}
Recent payment failures (from context): {{client_context.payment_failures}}

Generate:
1. A list of clients needing collection outreach (overdue > 15 days)
2. A list of contracts expiring within 60 days
3. Any billing anomalies (e.g., invoiced amounts vs. contracted amounts that don't match)
4. Recommended actions for each

Return JSON with: collection_clients (array), expiring_contracts (array), anomalies (array), summary

Output var: billing_review

Step 2 — Product Action: Create Billing Review Task in PSA

{
"product": "psa",
"action": "create_ticket",
"params": {
"org_id": "{{org_id}}",
"subject": "Monthly Billing Reconciliation — {{current_month}}",
"description": "{{billing_review.summary}}\n\nClients needing collection: {{billing_review.collection_clients}}\n\nExpiring contracts: {{billing_review.expiring_contracts}}\n\nAnomalies: {{billing_review.anomalies}}",
"priority": "p3",
"type": "request",
"assigned_team": "billing"
},
"on_error": "continue"
}

Step 3 — Branch: Any Collection Clients?

Condition: billing_review.collection_clients.length > 0

True branch: Send collection summary to billing team via email. False branch: Skip — no collection action needed.

Step 4 — Notification: Email Billing Team (true branch only)

{
"channel": "email",
"recipients": ["[email protected]"],
"subject": "Action Required: {{billing_review.collection_clients.length}} clients overdue",
"body": "Monthly billing review complete. The following clients have invoices overdue by 15+ days and need collection outreach:\n\n{{billing_review.collection_clients}}\n\nFull details in PSA ticket: {{ticket.id}}"
}

Result

On the first of every month, your billing team starts the day with a complete reconciliation summary already in PSA, with overdue clients flagged for collection. Twenty credits per month.


Tips for Effective Agent Building

Start simple. Build the notification-first version first (trigger → notification), confirm it fires correctly, then add AI and product action steps. Debugging a 2-step agent is much easier than a 6-step agent.

Use on_error: continue liberally. Product APIs can be temporarily unavailable. Design agents to degrade gracefully — log the error and continue — rather than fail hard. Reserve on_error: fail for steps where continuing without the result would cause downstream damage.

Test trigger filters carefully. A trigger filter that's too broad will fire your agent on every event; too narrow and it never fires. Use the Event Catalog to confirm the exact field values you'll see in production.

Client scope saves credits. If an agent only applies to clients with a specific product (e.g., a Defend-focused agent), scope it to the relevant client IDs. Don't run AI reasoning steps for clients where the output will never apply.

Keep AI prompts specific. Vague prompts produce vague outputs. Give the AI a clear role, specific context variables, and an explicit output schema. The more structure you provide, the more reliably useful the output will be.

Use Quick tier for routing, Standard for drafting, Premium/Expert for judgment calls. Don't pay 100 credits for a step that just needs to pick one of three categories. Save Premium and Expert for steps that require nuanced reasoning with real consequences.