Self-Healing Billing Agent

Build an autonomous agent that reacts to Stripe payment failures with Kite — retries, customer notifications, and human escalation.

# Self-Healing Billing Agent

This guide walks through building an autonomous agent that listens to Stripe payment failures and automatically retries, notifies customers, and escalates to a human after repeated failures.

What we're building

An agent that:

1. Receives payment_intent.payment_failed events from Stripe via Kite 2. Automatically retries the payment after a delay 3. Sends a customer notification on the first failure 4. Escalates to a human support queue after three consecutive failures

Prerequisites

  • Kite installed and authenticated
  • A Stripe account with a test webhook endpoint
  • Node.js 20+ or Python 3.11+

Step 1 — Create the Stripe endpoint

bash
kite endpoints create --source stripe

Add the relay URL to your Stripe dashboard under Developers → Webhooks. Subscribe to payment_intent.payment_failed. Paste the signing secret when prompted in the dashboard.

Step 2 — Start streaming

bash
kite proxy --source stripe --target http://localhost:3001/webhook

Step 3 — Write the agent handler

typescript
import express from "express";

const app = express();
app.use(express.json());

const failureCount = new Map<string, number>();

app.post("/webhook", async (req, res) => {
  const event = req.body;

  if (event.type !== "com.stripe.payment_intent.payment_failed") {
    return res.sendStatus(200);
  }

  const { id: paymentIntentId, customer } = event.data;
  const failures = (failureCount.get(paymentIntentId) ?? 0) + 1;
  failureCount.set(paymentIntentId, failures);

  if (failures === 1) {
    await notifyCustomer(customer, "We had trouble charging your card. We'll retry shortly.");
    await scheduleRetry(paymentIntentId, 30 * 60 * 1000); // 30 min
  } else if (failures === 2) {
    await notifyCustomer(customer, "Second payment attempt failed. Please update your payment method.");
    await scheduleRetry(paymentIntentId, 24 * 60 * 60 * 1000); // 24 hours
  } else {
    await escalateToSupport({ paymentIntentId, customer, failures });
    failureCount.delete(paymentIntentId);
  }

  res.sendStatus(200);
});

app.listen(3001);

Step 4 — Run the agent

Trigger a test payment failure from the Stripe dashboard. Within milliseconds, your agent receives the CloudEvent and takes action — no polling, no exposed servers.

Taking it further

  • Replace the in-memory Map with a database for persistence across restarts
  • Use kite listen --sink openclaw to feed events into an OpenClaw agent loop
  • Add kite listen github in the same session to handle multiple sources

This pattern — a Kite listener feeding a local agent — is how we recommend building reactive, event-driven autonomous agents.