Skip to content

hahzterry/settle

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Settle

An autonomous agent that collects its own overdue invoices — and knows when to stop.

Settle runs accounts-receivable follow-up for a small business: it chases overdue invoices by email, SMS, or voice call, picks the cheapest channel that is likely to work for each debtor, pays for its own usage (Twilio, ElevenLabs, LLM inference) out of a live ledger, and takes a real success commission through Stripe. When chasing a debtor costs more than it is expected to recover, it downgrades the channel on its own instead of burning margin.

Built solo in about a week for Hermes Agent — Accelerated Business, a hackathon by NVIDIA x Stripe x Nous Research (June 2026).

What it does

  • Scans a seeded ledger for overdue invoices and ranks debtors by expected recovery.
  • Computes unit economics per channel — amount x P(pay | channel, days overdue) - channel cost — from empirical outcome data, not a hardcoded heuristic, and picks the best channel or skips outreach entirely if none are profitable.
  • Sends email/SMS and places real voice calls (Twilio + ElevenLabs), always opening with an AI disclosure and an opt-out, and only to consenting, B2B debtors.
  • Verifies every outbound message (consent present, disclosure present, correct amount) before it goes out.
  • Takes payment through Stripe in live mode, reconciles the webhook against the invoice, and streams every spend/earn event to a live P&L dashboard over SSE.
  • Routes its own outbound network calls through an egress allowlist, so it can only reach the handful of services it is supposed to talk to.

How the loop closes

overdue invoices --> [scan] --> [prioritize: recovery vs. channel cost]
                                          |
                        profitable -------+------- not profitable
                            |                            |
                      [send / call]                [email only]
                            |                (loss avoided, on record)
                            v
                  debtor pays via Stripe (live)
                            |
                            v
                   webhook --> ledger (+recovered, +commission)
                            |
                            v
                 P&L updates live, funds the next collection

Architecture

Layer Role
Agent core (Hermes) Runs the loop; loads on-demand skills (skills/*.md) for each step
Decision skill Computes per-channel unit economics from empirical attempt data; the only place a channel gets chosen or skipped
Webhook + dashboard sidecar (FastAPI, app/sidecar.py) Verifies Stripe signatures, updates the ledger, pushes live updates over SSE, serves TwiML audio for calls
Sandbox (policy.yaml + security/) Egress allowlist enforced by a Docker/squid proxy on an isolated network — the agent's container has no default route out except through it
Storage SQLite: invoices, debtors (consent/opt-out), ledger (earn/spend), attempts (historical outcomes used to estimate pay probability)

The sandbox is a fallback for NemoClaw (unavailable during the hackathon window): a real network-layer boundary, not a mock — see security/README.md for how the allow/deny contract in policy.yaml becomes an enforced squid config, and why host-level (not verb-level) enforcement is the honest limit for HTTPS traffic.

Stack

Python 3.11, FastAPI + SSE, SQLite, Stripe (live mode, Connect/Checkout), Twilio, ElevenLabs, Resend, NVIDIA Nemotron (via NIM) for the one-sentence decision justification, Docker + squid for the egress sandbox.

Quick start

git clone <THIS_REPO> settle && cd settle
python3 -m venv .venv && .venv/bin/pip install fastapi uvicorn stripe

cat > .env <<ENV
STRIPE_SECRET_KEY=<YOUR_STRIPE_LIVE_KEY>
STRIPE_WEBHOOK_SECRET=<YOUR_STRIPE_WEBHOOK_SECRET>
TWILIO_ACCOUNT_SID=<YOUR_TWILIO_SID>
TWILIO_AUTH_TOKEN=<YOUR_TWILIO_TOKEN>
ELEVENLABS_API_KEY=<YOUR_ELEVENLABS_KEY>
RESEND_API_KEY=<YOUR_RESEND_KEY>
NVIDIA_API_KEY=<YOUR_NVIDIA_NIM_KEY>
ENV

sqlite3 app/settle.db < app/schema.sql
.venv/bin/uvicorn sidecar:app --app-dir app --host 0.0.0.0 --port 8444

Point a Stripe live webhook (payment_intent.succeeded, charge.succeeded) at https://<YOUR_DOMAIN>/webhook, then run scripts/settle-decide.py to seed a downgrade scenario and see the decision engine work end to end.

Why this is legally shippable

Settle only chases a business's own invoices, only with prior consent, always discloses that it is an AI assistant, and always offers an opt-out. That keeps it out of FDCPA/TCPA territory, which governs third-party consumer debt collection — this is B2B, first-party, consent-based follow-up.

More docs

ARCHITECTURE.md - BUILD-PLAN.md - SETUP.md - RISKS.md - security/README.md


Built with Claude Code.

About

Settle — autonomous accounts-receivable agent (Stripe/Twilio/voice). Chases overdue B2B invoices, takes a success fee via Stripe Connect. Built in ~1 week for the Hermes Agent hackathon (NVIDIA x Stripe x Nous Research).

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Python 59.7%
  • HTML 24.6%
  • Shell 15.7%