IN

instantly-observability

Set up comprehensive monitoring and alerting for your Instantly.ai campaigns to ensure high deliverability.

Install

mkdir -p .claude/skills/instantly-observability && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2403" && unzip -o skill.zip -d .claude/skills/instantly-observability && rm skill.zip

Installs to .claude/skills/instantly-observability

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Set up monitoring, alerting, and dashboards for Instantly.ai integrations.
74 charsno explicit “when” trigger
Intermediate

Key capabilities

  • Monitor Instantly.ai campaign health
  • Track account warmup performance
  • Monitor webhook delivery status
  • Set up automated alerts for critical events
  • Generate performance dashboards from Instantly data
  • Check for unhealthy or bounce-protected campaigns

How it works

This skill uses Instantly API v2 analytics and webhook events to perform health checks on campaigns, account warmups, and webhook delivery, then sends alerts based on defined thresholds.

Inputs & outputs

You give it
Instantly.ai API data and webhook event summaries
You get back
Health checks, alerts, and metrics for campaigns, accounts, and webhooks

When to use instantly-observability

  • Monitoring campaign status
  • Setting up deliverability alerts
  • Building dashboards for email analytics
  • Tracking webhook event health

About this skill

Instantly Observability

Overview

Build monitoring and alerting for Instantly integrations. Covers campaign health checks, account warmup monitoring, webhook delivery tracking, deliverability alerts, and performance dashboards. Uses Instantly API v2 analytics endpoints combined with webhook events for real-time awareness.

Prerequisites

  • Completed instantly-install-auth setup
  • API key with campaigns:read, accounts:read, and all:read scopes
  • Notification channel (Slack, email, PagerDuty, etc.)

Instructions

Step 1: Campaign Health Monitor

import { InstantlyClient } from "./src/instantly/client";

const client = new InstantlyClient();

interface HealthCheck {
  check: string;
  status: "ok" | "warning" | "critical";
  message: string;
}

async function campaignHealthCheck(): Promise<HealthCheck[]> {
  const checks: HealthCheck[] = [];
  const campaigns = await client.campaigns.list(100);

  for (const campaign of campaigns.filter((c) => c.status === 1)) { // Active only
    const analytics = await client.campaigns.analytics(campaign.id);
    const sent = analytics.emails_sent || 1;

    // Bounce rate check (critical if > 5%)
    const bounceRate = (analytics.emails_bounced / sent) * 100;
    if (bounceRate > 5) {
      checks.push({
        check: `bounce_rate:${campaign.name}`,
        status: "critical",
        message: `Bounce rate ${bounceRate.toFixed(1)}% exceeds 5% threshold. Campaign may be auto-paused.`,
      });
    } else if (bounceRate > 3) {
      checks.push({
        check: `bounce_rate:${campaign.name}`,
        status: "warning",
        message: `Bounce rate ${bounceRate.toFixed(1)}% approaching 5% threshold.`,
      });
    }

    // Reply rate check (warning if < 1%)
    const replyRate = (analytics.emails_replied / sent) * 100;
    if (replyRate < 1 && sent > 100) {
      checks.push({
        check: `reply_rate:${campaign.name}`,
        status: "warning",
        message: `Reply rate ${replyRate.toFixed(1)}% is below 1% after ${sent} sends. Review email copy.`,
      });
    }

    // Open rate check (warning if < 20%)
    const openRate = (analytics.emails_opened / sent) * 100;
    if (openRate < 20 && sent > 100) {
      checks.push({
        check: `open_rate:${campaign.name}`,
        status: "warning",
        message: `Open rate ${openRate.toFixed(1)}% below 20%. Check subject lines and deliverability.`,
      });
    }
  }

  // Campaign status checks
  const unhealthy = campaigns.filter((c) => c.status === -1);
  const bounceProtected = campaigns.filter((c) => c.status === -2);

  if (unhealthy.length > 0) {
    checks.push({
      check: "unhealthy_campaigns",
      status: "critical",
      message: `${unhealthy.length} campaign(s) in Accounts Unhealthy state: ${unhealthy.map((c) => c.name).join(", ")}`,
    });
  }

  if (bounceProtected.length > 0) {
    checks.push({
      check: "bounce_protected_campaigns",
      status: "critical",
      message: `${bounceProtected.length} campaign(s) paused by Bounce Protect: ${bounceProtected.map((c) => c.name).join(", ")}`,
    });
  }

  return checks;
}

Step 2: Account Warmup Monitor

async function warmupHealthCheck(): Promise<HealthCheck[]> {
  const checks: HealthCheck[] = [];
  const accounts = await client.accounts.list(100);
  const emails = accounts.map((a) => a.email);

  if (emails.length === 0) return checks;

  // Get warmup analytics
  const warmup = await client.accounts.warmupAnalytics(emails);

  for (const w of warmup as Array<{
    email: string;
    warmup_emails_sent: number;
    warmup_emails_landed_inbox: number;
    warmup_emails_landed_spam: number;
  }>) {
    const sent = w.warmup_emails_sent || 1;
    const inboxRate = (w.warmup_emails_landed_inbox / sent) * 100;
    const spamRate = (w.warmup_emails_landed_spam / sent) * 100;

    if (inboxRate < 80) {
      checks.push({
        check: `warmup_inbox_rate:${w.email}`,
        status: inboxRate < 60 ? "critical" : "warning",
        message: `${w.email} warmup inbox rate ${inboxRate.toFixed(1)}% (${inboxRate < 60 ? "critical" : "below 80%"})`,
      });
    }

    if (spamRate > 10) {
      checks.push({
        check: `warmup_spam_rate:${w.email}`,
        status: "critical",
        message: `${w.email} warmup spam rate ${spamRate.toFixed(1)}% — reputation issue`,
      });
    }
  }

  // Test vitals
  const vitals = await client.accounts.testVitals(emails) as Array<{
    email: string; smtp_status: string; imap_status: string;
  }>;

  const broken = vitals.filter((v) => v.smtp_status !== "ok" || v.imap_status !== "ok");
  if (broken.length > 0) {
    checks.push({
      check: "account_vitals",
      status: "critical",
      message: `${broken.length} account(s) with broken SMTP/IMAP: ${broken.map((v) => v.email).join(", ")}`,
    });
  }

  return checks;
}

Step 3: Webhook Delivery Monitor

async function webhookHealthCheck(): Promise<HealthCheck[]> {
  const checks: HealthCheck[] = [];

  const summary = await client.request<{
    total_delivered: number;
    total_failed: number;
    total_pending: number;
  }>("/webhook-events/summary");

  if (summary.total_failed > 0) {
    const failRate = (summary.total_failed / (summary.total_delivered + summary.total_failed)) * 100;
    checks.push({
      check: "webhook_delivery",
      status: failRate > 10 ? "critical" : "warning",
      message: `Webhook delivery: ${summary.total_delivered} delivered, ${summary.total_failed} failed (${failRate.toFixed(1)}% fail rate)`,
    });
  }

  // Check for paused webhooks
  const webhooks = await client.webhooks.list();
  const paused = webhooks.filter((w: any) => w.status === "paused");
  if (paused.length > 0) {
    checks.push({
      check: "webhooks_paused",
      status: "critical",
      message: `${paused.length} webhook(s) are paused — events are being dropped`,
    });
  }

  return checks;
}

Step 4: Alerting Pipeline

async function runHealthChecks() {
  console.log(`\n=== Instantly Health Check — ${new Date().toISOString()} ===\n`);

  const allChecks: HealthCheck[] = [
    ...await campaignHealthCheck(),
    ...await warmupHealthCheck(),
    ...await webhookHealthCheck(),
  ];

  // Log all checks
  for (const check of allChecks) {
    const icon = check.status === "ok" ? "OK" : check.status === "warning" ? "WARN" : "CRIT";
    console.log(`[${icon}] ${check.check}: ${check.message}`);
  }

  // Alert on critical/warning
  const critical = allChecks.filter((c) => c.status === "critical");
  const warnings = allChecks.filter((c) => c.status === "warning");

  if (critical.length > 0) {
    await sendAlert("critical", critical);
  }
  if (warnings.length > 0) {
    await sendAlert("warning", warnings);
  }

  console.log(`\nSummary: ${critical.length} critical, ${warnings.length} warnings, ${allChecks.length} total checks`);
}

async function sendAlert(severity: string, checks: HealthCheck[]) {
  // Slack notification
  const color = severity === "critical" ? "#FF0000" : "#FFA500";
  const text = checks.map((c) => `*${c.check}*: ${c.message}`).join("\n");

  await fetch(process.env.SLACK_WEBHOOK_URL!, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      attachments: [{
        color,
        title: `Instantly ${severity.toUpperCase()} Alert`,
        text,
        ts: Math.floor(Date.now() / 1000),
      }],
    }),
  });
}

Step 5: Scheduled Monitoring (Cron)

// Run health checks on a schedule
// Deploy as Cloud Run job, GitHub Action, or cron task

// package.json script:
// "monitor": "npx tsx scripts/health-check.ts"

// crontab: every 15 minutes
// */15 * * * * cd /app && npm run monitor >> /var/log/instantly-health.log 2>&1

// GitHub Actions schedule:
// on:
//   schedule:
//     - cron: '*/15 * * * *'

import cron from "node-cron";

cron.schedule("*/15 * * * *", async () => {
  try {
    await runHealthChecks();
  } catch (err) {
    console.error("Health check failed:", err);
    await sendAlert("critical", [{ check: "monitor", status: "critical", message: `Monitor itself failed: ${err}` }]);
  }
});

Dashboard Metrics Summary

MetricSourceAlert Threshold
Campaign bounce rateGET /campaigns/analytics>5% critical
Campaign reply rateGET /campaigns/analytics<1% warning
Campaign open rateGET /campaigns/analytics<20% warning
Warmup inbox ratePOST /accounts/warmup-analytics<80% warning, <60% critical
Account vitalsPOST /accounts/test/vitalsAny non-ok = critical
Webhook deliveryGET /webhook-events/summary>10% fail rate = critical
Unhealthy campaignsGET /campaignsstatus=-1 = critical
Bounce protected campaignsGET /campaignsstatus=-2 = critical

Error Handling

ErrorCauseSolution
Monitor itself rate-limitedToo-frequent checksIncrease interval to 15-30 min
Slack alert not deliveredInvalid webhook URLVerify SLACK_WEBHOOK_URL
Stale analytics dataInstantly updates delayAllow 1-hour data lag

Resources

  • Instantly Analytics API
  • Instantly Account API
  • Instantly Webhook Events

Next Steps

For incident response, see instantly-incident-runbook.

When not to use it

  • When the monitor itself is rate-limited
  • When Instantly updates data with a delay

Prerequisites

Completed `instantly-install-auth` setupAPI key with `campaigns:read`, `accounts:read`, and `all:read` scopesNotification channel (Slack, email, PagerDuty, etc.)

Limitations

  • Monitor itself can be rate-limited if checks are too frequent
  • Slack alerts require a valid webhook URL
  • Instantly data may have up to a 1-hour lag

How it compares

This skill provides automated, scheduled monitoring and alerting for Instantly.ai integrations, offering real-time awareness beyond manual checks of campaign performance.

Compared to similar skills

instantly-observability side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
instantly-observability (this skill)225dCautionIntermediate
langfuse76moNo flagsIntermediate
perplexity-observability125dNo flagsIntermediate
typescript-sdk25moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

More by jeremylongshore

View all by jeremylongshore

analyzing-logs

jeremylongshore

Analyze application logs to detect performance issues, identify error patterns, and improve stability by extracting key insights.

14123

ollama-setup

jeremylongshore

Configure auto-configure Ollama when user needs local LLM deployment, free AI alternatives, or wants to eliminate hosted API costs. Trigger phrases: "install ollama", "local AI", "free LLM", "self-hosted AI", "replace OpenAI", "no API costs". Use when appropriate context detected. Trigger with relevant phrases based on skill purpose.

1167

backtesting-trading-strategies

jeremylongshore

Backtest crypto and traditional trading strategies against historical data. Calculates performance metrics (Sharpe, Sortino, max drawdown), generates equity curves, and optimizes strategy parameters. Use when user wants to test a trading strategy, validate signals, or compare approaches. Trigger with phrases like "backtest strategy", "test trading strategy", "historical performance", "simulate trades", "optimize parameters", or "validate signals".

1071

generating-database-seed-data

jeremylongshore

Process this skill enables AI assistant to generate realistic test data and database seed scripts for development and testing environments. it uses faker libraries to create realistic data, maintains relational integrity, and allows configurable data volumes. u... Use when working with databases or data models. Trigger with phrases like 'database', 'query', or 'schema'.

1033

cursor-codebase-indexing

jeremylongshore

Execute set up and optimize Cursor codebase indexing. Triggers on "cursor index setup", "codebase indexing", "index codebase", "cursor semantic search". Use when working with cursor codebase indexing functionality. Trigger with phrases like "cursor codebase indexing", "cursor indexing", "cursor".

885

testing-mobile-apps

jeremylongshore

Execute mobile app testing on iOS and Android devices/simulators. Use when performing specialized testing. Trigger with phrases like "test mobile app", "run iOS tests", or "validate Android functionality".

810

You might also like

langfuse

davila7

Expert in Langfuse - the open-source LLM observability platform. Covers tracing, prompt management, evaluation, datasets, and integration with LangChain, LlamaIndex, and OpenAI. Essential for debugging, monitoring, and improving LLM applications in production. Use when: langfuse, llm observability, llm tracing, prompt management, llm evaluation.

743

perplexity-observability

jeremylongshore

Set up comprehensive observability for Perplexity integrations with metrics, traces, and alerts. Use when implementing monitoring for Perplexity operations, setting up dashboards, or configuring alerting for Perplexity integration health. Trigger with phrases like "perplexity monitoring", "perplexity metrics", "perplexity observability", "monitor perplexity", "perplexity alerts", "perplexity tracing".

10

typescript-sdk

comet-ml

TypeScript SDK patterns for Opik. Use when working in sdks/opik-typescript.

212

error-tracking

diet103

Add Sentry v8 error tracking and performance monitoring to your project services. Use this skill when adding error handling, creating new controllers, instrumenting cron jobs, or tracking database performance. ALL ERRORS MUST BE CAPTURED TO SENTRY - no exceptions.

14

azure-monitor-opentelemetry-ts

microsoft

Instrument applications with Azure Monitor and OpenTelemetry for JavaScript (@azure/monitor-opentelemetry). Use when adding distributed tracing, metrics, and logs to Node.js applications with Application Insights.

11

genkit-production-expert

jeremylongshore

Build production Firebase Genkit applications including RAG systems, multi-step flows, and tool calling for Node.js/Python/Go. Deploy to Firebase Functions or Cloud Run with AI monitoring. Use when asked to "create genkit flow" or "implement RAG". Trigger with relevant phrases based on skill purpose.

01

Search skills

Search the agent skills registry