Skip to content

An open-source churn prediction agent that reads every morning

An AI churn prediction agent reads usage, support and billing signals and posts the accounts worth calling each morning. Kortix is the open-source CompanyOS: your agents, their skills, your company memory, and every connector in one git repo you own, with the agents working on real cloud computers. The habit matters more than the model.

The trigger the change request adds to kortix.yaml

kortix.yamlSource
triggers:
  - slug: daily-churn-scan
    name: Daily churn-risk scan
    on:
      cron: "0 0 6 * * *"
    run:
      agent: churn-risk
      prompt: Load the churn-signals skill and run one complete churn-risk scan.
The daily scan as the churn-risk setup writes it: one cron line, one agent, one prompt.

The scan runs whether or not anyone remembers

An AI churn prediction agent is worth running for its schedule at least as much as for its model. Churn work fails on ordinary weeks. A team buys scores, someone opens a dashboard near a renewal, and an account that went quiet two months earlier has already left. The ranking was probably right, and nobody was looking at it.

A churn prediction agent is a scheduled agent that reads product usage, support and billing records, scores every account against written rules, and posts the accounts worth a call. In the churn-risk setup on Kortix, those records sit in Postgres, Plain and Stripe. The rules are files in the agent's repository, so the scoring can be read and edited by the people who own the accounts. The schedule is a cron line, set to 06:00 UTC every day, and it fires whether or not anyone has opened a laptop.

The model does not get better because it runs daily. A good statistical model can rank accounts better than five written rules can. What the schedule changes is who carries the remembering. The scan runs unattended, and the list lands in the channel the team reads anyway. Work then starts from a list that arrived on its own, rather than from someone's memory of a quarterly review.

What it reads, and the only thing it writes

The churn-risk setup reads three systems and writes to a fourth. Product usage comes from Postgres, support threads from Plain, payment state and renewal dates from Stripe. The ranked list goes to a Slack channel where customer success already works. A team swaps in whatever systems hold the same records, because the agent reaches them through connectors instead of a bespoke pipeline.

Access runs one way. The connectors into Postgres, Plain and Stripe are read-only, and the single output of a run is the Slack post. The agent never writes to Postgres, Plain or Stripe, never replies to a support thread and never contacts a customer. A person on customer success decides what happens to each account, which keeps a wrong score a wasted call rather than an incident.

Setting it up takes one prompt and four connections

Setup starts with a prompt pasted into a new session of a Kortix project. It asks for three files, an agent, a scoring skill and a daily trigger, plus a change request that holds all of them. Nothing runs until a person reads that change request and merges it. This is the prompt:

Set up a daily churn-risk agent in this project.

1. Create the agent agents/churn-risk.md. Its job is to score every account for churn risk and post a ranked list. It may use the Postgres, Stripe and Slack connectors and the Plain API key. It only reads Postgres, Plain and Stripe.

2. Create the skill skills/churn-signals/SKILL.md with these rules:
   - Usage is declining when core activity drops 20% or more against the prior 30 days, and dormant after 14 days with almost no activity.
   - Support friction is rising when thread volume climbs above the account's history or threads stay unresolved. Cancellation language counts as escalated.
   - Billing is at risk after a missed or failed payment. A renewal is imminent within 30 days.
   - No single signal is high risk on its own. Rank accounts with declining usage, rising support friction and an imminent renewal or failed payment first.
   - Give every listed account a reason and one next step. Never write to Postgres, Plain or Stripe, and never contact a customer.

3. Add a cron trigger daily-churn-scan to kortix.yaml. It runs the churn-risk agent every day at 06:00 UTC with the prompt "Load the churn-signals skill and run one complete churn-risk scan."

4. Tell me which of these connectors are not connected yet.

5. Open a change request with all of it. Do not merge it.

Then four connections get made in the project: Postgres, Plain, Stripe and Slack, with the Plain key stored as a secret. The order of those connections matters less than the review. Run the scan once by hand, with the agent and a short prompt that asks for one read-only pass. Compare its ranking with what the team already knows about a handful of accounts. When the list holds up, the cron line carries it from there.

The rules are files a person reviews before the first run

The skill named in that prompt holds the thresholds as plain text: usage down 20% or more against the prior 30 days, dormant after 14 days with almost no activity, cancellation language counted as escalated, a renewal inside 30 days. Those numbers are the whole scoring system, and they sit in a file the account team can open and argue with.

The ranking rule in the skill is just as plain. No single signal makes an account high risk, and the accounts where declining usage, rising support friction and an imminent renewal or a failed payment line up go first. Every listed account carries a reason and one next step, and the agent never writes to a customer system.

The first run happens because a person read those files in a change request and merged it, not because a schedule decided to start. A threshold that turns out wrong is changed the same way. The agent edits the skill on its session branch, and the diff arrives as a change request. The next 06:00 run uses the approved version. A gate on a connector call is a separate setting. Approval gates you set. Off until you set them.

The safety answer, in specifics

The scan reads across every customer system, so its access is scoped before the first run. The connectors into Postgres, Plain and Stripe are read-only. Connector credentials are brokered server-side and never enter the machine. One isolated sandbox per session. Each session has its own isolated machine and branch. The scoring rules, the agent file and the per-system permissions are files in the repository. A change to any of them arrives as a reviewed change request rather than a settings screen edit.

None of that makes the output correct. A person still decides what happens to each account on the list, and the read-only boundary is what keeps the decision reversible.

What it cannot do

The agent does not contact customers, does not change a subscription, and does not close or reply to a support thread. It surfaces the accounts your rules already consider risky, in one place, every morning. If a threshold is wrong, the list is wrong in the same way every day. That is the useful failure. A consistent mistake shows up within a week of posts and is easy to fix in the skill file. A team that never reads the list gets a channel full of ignored messages, and the scan will keep posting them.

It also cannot tell a team why an account is leaving. Usage down 34% and a renewal in 30 days describe a state. The next step in the post is a suggestion written from the same rules. The conversation is still the work.

What one morning's post looks like

Each run ends as a single Slack message. This is an illustrative run of the setup's own example, not a customer result and not a benchmark:

Flagged 8 accounts. 2 are highest risk: usage down 34% in 30 days, an escalated support thread, and a renewal in the next 30 days. For both, the suggested next step is a renewal conversation this week.

Two accounts out of eight lead the list, and each arrives with the signals that put it there. Every other account on the list carries a reason as well, which is what makes the ranking arguable. A line that says which three signals fired gives the owner something to confirm or dispute. That dispute is how a threshold gets fixed. The skill makes the reason and the next step mandatory for every listed account, so all eight in that example run arrive with the detail the two at the top get.

Questions before the first run

Including the one about handing an agent customer data.

Can AI predict churn?
Yes, as a short-horizon list of accounts to check. A churn prediction agent reads usage, support and billing signals, ranks the accounts where several agree, and leaves the decision to a person, so the output is a set of calls rather than a certainty.
Do I need a data scientist to set this up?
No. You paste a setup prompt into a session, connect Postgres, Plain, Stripe and Slack, and review the change request it opens. The scoring rules are plain text in the repository, so anyone on the team can read a threshold and argue with it.
Is it safe to let an agent read customer data?
Yes, when the access is read-only and scoped. The connectors into Postgres, Plain and Stripe are read-only, connector credentials are brokered server-side and never enter the machine, and each run happens in its own isolated sandbox. A person decides what happens to each account.