🪙 SOLVENT
An AI agent that runs as a profitable, self-funding business.
It sells research briefs. It collects payment on Stripe. It spends its own revenue to provision the compute it needs. And it refuses any job that doesn't clear a margin.
The Big Idea
Most agents can spend money. Almost none can run as a business.
SOLVENT closes the full loop:
Client pays Stripe → Agent earns revenue → Agent fulfils the work
→ Agent pays its own vendor bills → P&L booked → balance sheet grows
Every job is profit-gated before it starts. Unprofitable work is declined without touching Stripe. Vendor payments are screened by a NemoClaw-style policy sandbox. The agent literally cannot spend more than it earns.
🚀 Quick Start
Zero dependencies. No API keys. Works right now.
git clone https://github.com/ianalloway/solvent-agent.git
cd solvent-agent
python3 run_demo.py
The agent will run a full batch of 4 analyst jobs — complete with margin gating, Stripe payment simulation, NVIDIA Nemotron fulfillment, guardrail screening, and live P&L — in about 30 seconds.
Install as a package (optional)
The core runs on the standard library alone, so a bare install pulls in
nothing extra and gives you a solvent command:
pip install -e . # editable install from a checkout
# PyPI / pipx publish pending — not on PyPI yet:
# pip install git+https://github.com/ianalloway/solvent-agent.git
solvent # run the demo
solvent finance # financial report (income, runway, forecast)
solvent --help # list all commands
solvent --version
Third-party features are opt-in extras — install only what you need:
pip install -e ".[stripe]" # real Stripe test-mode payment links
pip install -e ".[serve]" # FastAPI webhooks + hosted briefs
pip install -e ".[telegram]" # Telegram bot channel
pip install -e ".[qr]" # scannable QR codes for OpenClaw pairing
pip install -e ".[dev]" # pytest, for running the test suite
pip install -e ".[all]" # everything
When run from a source checkout, runtime data stays under <repo>/data. When
installed elsewhere, SOLVENT writes to ~/.solvent instead of into
site-packages — override either with SOLVENT_HOME=/path/to/dir.
First run: A short onboarding wizard asks you to choose a model, interaction mode, and whether to enable Stripe test mode. Preferences are saved to
.solvent/config.jsonand never committed.
📊 The Demo
After a run, open the live treasury dashboard:
open treasury_dashboard.html # macOS
A typical offline demo batch (illustrative numbers from the simulated run — not production revenue):
| Metric | Demo value |
|---|---|
| Revenue | ~$223 |
| Operating spend | ~$13 |
| Net profit | high-margin demo loop |
| Jobs declined | 1 (below margin floor) |
⚙️ How It Works
inbound job
│
▼
┌─────────────┐ margin < floor? ┌───────────┐
│ MARGIN GATE│ ─────────────────▶ │ DECLINE │
│ (pricing) │ └───────────┘
└─────┬───────┘ accept
▼
┌─────────────┐ EARN
│ STRIPE │ ── Payment Link → poll/webhook until paid ──▶ + revenue
└─────┬───────┘ (records cs_... + pi_... on ledger)
▼
┌─────────────┐ FULFIL
│ NEMOTRON │ ── Llama-3.1-Nemotron-Ultra produces the brief ──▶ resource usage
└─────┬───────┘
▼
┌─────────────┐ SPEND (every payment screened first)
│ GUARDRAILS │ ── NemoClaw policy: allowlist · caps · reserve · ROI
│ → STRIPE │ ── Issuing virtual card (test) or simulated spend ──▶ − expense
└─────┬───────┘
▼
BOOK P&L ──▶ treasury updated · dashboard refreshed
Revenue is always collected before cost is incurred, and no payment can violate policy. The business is safe by construction and profitable by rule.
🏗️ Architecture
| Layer | Technology | File |
|---|---|---|
| Analyst / reasoning | NVIDIA Nemotron (Llama-3.1-Nemotron-Ultra) | solvent/nemotron.py |
| Spend safety | NVIDIA NemoClaw-style policy sandbox | solvent/guardrails.py |
| Earn | Stripe Payment Links + Checkout Session polling | solvent/stripe_client.py |
| Spend | Stripe Issuing virtual cards (test mode) | solvent/stripe_client.py |
| Orchestration | Hermes / Nous tool-calling agent loop | solvent/agent.py |
| Memory | SQLite treasury + pricing ledger | solvent/treasury.py · solvent/pricing.py |
Key design choices:
- Structural profitability —
pricing.pycomputes unit cost before quoting. If margin < floor, the job never reaches Stripe. - Spend policy —
guardrails.pyenforces vendor allowlist, per-transaction cap, rolling 24h budget, minimum cash reserve, and no-negative-ROI rule. - Offline-first — without API keys the demo runs on deterministic stubs. Add
NVIDIA_API_KEY+STRIPE_API_KEY=sk_test_...to unlock live inference and real Payment Links. - Audit trail — every
cs_...checkout session ID andpi_...PaymentIntent ID is recorded on the ledger before fulfilment begins.
🎮 Running Modes
Batch demo (default — best for judges)
python3 run_demo.py
4 pre-loaded jobs. ~30 seconds. Shows margin gating, Stripe earn/spend, Nemotron fulfillment, and guardrails in action.
Interactive — your own jobs
python3 run_demo.py --interactive
Type a research topic and client budget at the prompt. The agent quotes, pays, fulfils, and books P&L for each one in real time. Keep going until you quit.
Add funds mid-session
python3 run_demo.py --seed 500 # start with $500 instead of $100
python3 run_demo.py --keep-balance # resume existing treasury balance
In interactive mode, type /fund 200 at the prompt to deposit $200 into the live treasury without restarting.
Programmatic
from solvent.agent import Solvent
from solvent.jobs import SAMPLE_JOBS
agent = Solvent(seed_cents=10_000) # reset treasury, seed $100
agent.handle_job(SAMPLE_JOBS[0]) # process one job
snap = agent.run(SAMPLE_JOBS[1:]) # process a list; returns snapshot
print(snap["balance_cents"], snap["margin_pct"])
Production mode (webhooks + async worker)
pip install -e ".[serve]"
export SOLVENT_DASHBOARD_TOKEN=$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')
python3 -m solvent serve --port 8787 # webhooks + job API + hosted briefs
python3 -m solvent worker # resume incomplete jobs, process queue
# Interactive voice dashboard (chat + live SSE updates):
open "http://127.0.0.1:8787/?token=$SOLVENT_DASHBOARD_TOKEN"
# Or dev convenience:
python3 run_demo.py --serve --no-onboard
The hosted dashboard at / includes a chat panel (type or use the mic with Web Speech API) and live treasury updates via Server-Sent Events (/api/events). Dashboard/control routes require SOLVENT_DASHBOARD_TOKEN via ?token=... or the X-Solvent-Dashboard-Token header before they expose status data or route chat through the Nemotron agent loop.
See docs/PRODUCTION.md for Stripe webhook setup, SMTP delivery, and reconciliation.
Operations
python3 -m solvent reconcile --since 7d # Stripe ↔ ledger drift check
python3 -m solvent finance # income statement, unit economics, runway
python3 -m solvent finance --json # machine-readable report
python3 -m solvent finance --reserve 50 # runway to a $50 cash-reserve floor
python3 -m solvent finance --period week # net P&L trend by day | week | month
python3 -m solvent finance --horizon 60 # forecast the balance 60 days out
finance (alias report) turns the treasury ledger into the numbers a
business steers by: revenue/cost/net-margin, average profit per job, a cash
runway — days of burn remaining, or cash-flow positive once the agent
funds itself — a net-P&L trend bucketed by day/week/month, and a
balance forecast (central projection with a best/worst band whose width
grows with daily volatility). The income statement, runway, trend, and
forecast also render as a Financial Statement panel in the HTML dashboard.
🔑 Make It Real
To use live Nemotron inference and real Stripe test-mode payment links:
pip install -e ".[stripe]"
export NVIDIA_API_KEY=nvapi-... # from build.nvidia.com
export STRIPE_API_KEY=sk_test_... # Stripe test mode only (live keys refused)
python3 run_demo.py
With both keys set:
- Briefs are written by NVIDIA Nemotron (Llama-3.1-Nemotron-Ultra).
- Each job creates a real Stripe Payment Link. Pay with test card
4242 4242 4242 4242. - SOLVENT polls the Checkout Session (
cs_...) untilpayment_status == paidbefore fulfilling — no instant confirm. - Optional: set
STRIPE_WEBHOOK_SECRETand forwardcheckout.session.completedevents viaStripeClient.process_webhook(). - Optional: enable Stripe Issuing on your test account to provision capped single-use virtual debit cards for each vendor payment.
Environment variables
| Variable | Purpose |
|---|---|
SOLVENT_HOME |
Where runtime data (treasury DB, reports, dashboard, logs) is stored. Defaults to the repo when run from a checkout, else ~/.solvent |
NVIDIA_API_KEY |
Live Nemotron inference (nvapi-...) |
STRIPE_API_KEY |
Stripe test key (sk_test_...) |
STRIPE_WEBHOOK_SECRET |
Optional webhook verification |
STRIPE_PAYMENT_POLL_TIMEOUT |
Seconds to wait for payment (default 120) |
STRIPE_PAYMENT_POLL_INTERVAL |
Poll interval in seconds (default 2) |
SOLVENT_FORCE_STRIPE_SIMULATE |
Force offline simulate mode even with a key |
SOLVENT_DASHBOARD_TOKEN |
Shared secret required for hosted dashboard/control routes |
TELEGRAM_BOT_TOKEN |
Telegram bot token from BotFather |
SOLVENT_TELEGRAM_DM_POLICY |
pairing · allowlist · open (default pairing) |
SOLVENT_TELEGRAM_ALLOW_FROM |
Comma-separated Telegram user IDs for allowlist mode |
SOLVENT_PORT |
Port for the serve API server (default 8787) |
SOLVENT_BASE_URL |
Base URL for hosted brief links and Stripe webhook callbacks |
NEMOTRON_MODEL |
Nemotron model override (default: nvidia/llama-3.1-nemotron-ultra-253b-v1) |
SOLVENT_DELIVERY_SECRET |
HMAC token secret for /briefs/{job_id}; at least 32 characters, high entropy |
SOLVENT_SKIP_ONBOARD |
Set to 1 to skip the first-run wizard |
SOLVENT_ALLOW_POLL |
When set to 1/true/yes, actively poll Stripe Checkout Sessions for payment status instead of awaiting webhook confirmation (default: off) |
SOLVENT_ASYNC |
Run job fulfillment asynchronously instead of blocking on payment polling (default: off / synchronous) |
SOLVENT_LIVE_SEARCH |
Enable live web search integration in the agent chat loop (default: off) |
SOLVENT_LOG_JSON |
Emit structured JSON log lines to stderr in addition to the log file (default: off) |
SOLVENT_UPDATE_CHECK |
Opt-in: run a background version-update hint on CLI startup when set to 1/true/yes |
SOLVENT_NO_UPDATE_CHECK |
Set to any value to suppress the background version-update hint |
SOLVENT_WORKSPACE |
Override path for the agent workspace directory (SOUL/BRAIN/AGENTS files) |
SOLVENT_WORKSPACE_MAX_CHARS |
Max characters loaded per workspace context file (default 8000) |
SOLVENT_WORKSPACE_TOTAL_MAX_CHARS |
Max total characters across all workspace context files (default 40000) |
SMTP_HOST |
SMTP server hostname. When empty (default), brief delivery is simulated — research briefs are written to the outbox directory instead of emailed. When set, briefs are emailed to the customer |
SMTP_PORT |
SMTP server port (default 587) |
SMTP_USER |
SMTP authentication username |
SMTP_PASS |
SMTP authentication password |
SMTP_FROM |
"From" address for outgoing brief emails (default: SMTP_USER, else agent@solvent.local) |
Product/Price objects are cached in .solvent/stripe_catalog.json so repeated runs reuse a single SOLVENT Research Brief product instead of cluttering your Stripe dashboard.
💬 Telegram (conversational channel)
Full chat on Telegram with OpenClaw-style pairing and Hermes-style tool/memory patterns. See docs/TELEGRAM.md.
pip install -e ".[telegram]"
export TELEGRAM_BOT_TOKEN=...
python -m solvent serve & # Stripe webhooks + checkout
python -m solvent worker & # fulfill jobs
python -m solvent telegram # long-poll bot
python -m solvent doctor # diagnostics
python -m solvent pairing list # pending DM codes
Users pair via /start, commission briefs in natural language, receive checkout links, and get push updates when jobs are paid and delivered.
Personality and operating rules come from the agent workspace (SOUL.md, BRAIN.md, AGENTS.md) — see docs/WORKSPACE.md.
🧪 Tests
pip install -e ".[dev]"
python3 -m pytest tests/ -v
Unit tests cover: pricing & margin gate · guardrail policy · treasury ledger · Stripe client (simulate + test mode) · config/onboarding.
📁 Repository Layout
solvent/
agent.py the orchestrator (earn → fulfil → spend → book)
stages.py idempotent stage machine (quote→paid→fulfill→deliver→spend)
treasury.py SQLite ledger / balance sheet
pricing.py the margin gate
guardrails.py NemoClaw-style spend policy
stripe_client.py two-sided Stripe layer (earn + spend)
nemotron.py NVIDIA Nemotron client (+ offline stub)
service.py the product: an on-demand research brief
jobs.py sample inbound work
dashboard.py renders the treasury to HTML + JSON
finance.py income statement · unit economics · runway · forecast
config.py onboarding wizard and config persistence
server.py FastAPI webhooks + job API + hosted briefs (serve)
worker.py async job processor + resume incomplete jobs
gateway.py channel router (Telegram → chat sessions)
chat.py conversational loop + business tools
memory.py Hermes-style session memory
doctor.py stack diagnostics
workspace.py SOUL/BRAIN/AGENTS prompt assembly
channels/ Telegram long-poll adapter
run_demo.py the full business loop (CLI entry point)
tests/ pytest suite
docs/ screenshots and supporting docs
🏆 Built For
Hermes Agent Accelerated Business Hackathon — NVIDIA × Stripe × Nous Research
The agent was designed to demonstrate:
- An agent that is economically self-aware — it has a treasury, prices against its own costs, and gates every action on projected profit
- A complete two-sided Stripe integration — earns via Payment Links, spends via Issuing virtual cards
- Provable spend safety — a NemoClaw-style policy sandbox that makes "give an agent a payment credential" a reasonable thing to do
- Live inference with NVIDIA Nemotron — the offline stub means the demo always works, even without API keys
🤝 Contributing
Issues, PRs, and ideas are very welcome. Some good starting points:
- Add more sample research topics in
solvent/jobs.py - Improve the Nemotron prompt template in
solvent/service.py - Add a new guardrail policy to
solvent/guardrails.py - Extend the dashboard with charts or new metrics in
solvent/dashboard.py
If SOLVENT gave you ideas, give it a ⭐
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file solvent_agent-0.1.0.tar.gz.
File metadata
- Download URL: solvent_agent-0.1.0.tar.gz
- Upload date:
- Size: 175.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c44f26d38bbd6480de9a23b24a158d65bd51226e3e16e89dde0e86cf7f19bfd
|
|
| MD5 |
2b017a06add8ad83c1c0bed3ba406645
|
|
| BLAKE2b-256 |
96e677395b58e6adf90d58715c33b9c06f77ace721737d7173b6aa6ab47836d2
|
Provenance
The following attestation bundles were made for solvent_agent-0.1.0.tar.gz:
Publisher:
publish.yml on ianalloway/solvent-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solvent_agent-0.1.0.tar.gz -
Subject digest:
0c44f26d38bbd6480de9a23b24a158d65bd51226e3e16e89dde0e86cf7f19bfd - Sigstore transparency entry: 2715078463
- Sigstore integration time:
-
Permalink:
ianalloway/solvent-agent@33cb136cfd04ab03279234d212f3838f5db400fa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ianalloway
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33cb136cfd04ab03279234d212f3838f5db400fa -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file solvent_agent-0.1.0-py3-none-any.whl.
File metadata
- Download URL: solvent_agent-0.1.0-py3-none-any.whl
- Upload date:
- Size: 133.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e6c18b789012e7b75e64afb68a2eb933e8eb29864a5e4288e6f03344129e113
|
|
| MD5 |
7ec6b6cc70838fde93e84574eb754031
|
|
| BLAKE2b-256 |
bd6e9617c890a1d4f812a839a6e12569918f30b95fd1c389112d29a0f189d705
|
Provenance
The following attestation bundles were made for solvent_agent-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ianalloway/solvent-agent
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solvent_agent-0.1.0-py3-none-any.whl -
Subject digest:
0e6c18b789012e7b75e64afb68a2eb933e8eb29864a5e4288e6f03344129e113 - Sigstore transparency entry: 2715078751
- Sigstore integration time:
-
Permalink:
ianalloway/solvent-agent@33cb136cfd04ab03279234d212f3838f5db400fa -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ianalloway
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33cb136cfd04ab03279234d212f3838f5db400fa -
Trigger Event:
workflow_dispatch
-
Statement type: