Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Paytm Build for India AI Hackathon — Delhi Edition · Track 2: AI-Powered Financial Journeys
Team1 — Arun Kumar, Vivek Goswami
A real-time decision layer that decides, at the moment of payment, whether to surface
pre-approved credit — and which product — so the customer never has to separately discover,
apply for and wait on a loan.
The novel piece is not the checkout screen. It is an engine that can explain every decision it
makes, including the ones where it stays silent.查看完整 README ↗Paytm Build for India AI Hackathon — Delhi Edition · Track 2: AI-Powered Financial Journeys Team1 — Arun Kumar, Vivek Goswami
A real-time decision layer that decides, at the moment of payment, whether to surface pre-approved credit — and which product — so the customer never has to separately discover, apply for and wait on a loan.
The novel piece is not the checkout screen. It is an engine that can explain every decision it makes, including the ones where it stays silent.
npm install
npm run dev # http://localhost:3000
npm test # 32 engine tests, ~150ms
npm run scenarios # prints every demo scenario with its reasoning
Nothing needs configuring. Without any API keys the app runs end to end on template copy and the
direct API path; keys upgrade those two slots in place. See .env.example.
| Built here | The decision engine, the memory/feature layer, the audit trail, the checkout UI, the orchestration wiring |
| Mocked | Credit issuance, KYC, OTP, the partner-bank approval call — Paytm and its partner banks (SBI / HDFC / IDFC First / Suryoday) run this in production already |
| Synthetic | Every user, merchant and transaction. Eligibility is a simplified stand-in for Paytm's real underwriting, not an attempt to reproduce it |
Synthetic does not mean arbitrary. Each persona has a seeded transaction ledger, and every behavioural signal is re-derived from those rows — see below.
checkout screen
└─> n8n webhook ──> POST /api/decide ──> IF showNudge ──> POST /api/nudge-text
(3s timeout, (Sarvam, with
auto-fallback) template fallback)
└─> POST /api/decide [fallback path, identical result]
lib/
memory/ ledger.ts seeded transaction history per persona
features.ts detects salary + recurring obligations from the rows
signal.ts features -> eligibility signal, with a breakdown
engine/ gates.ts 14 hard blocks, ordered, short-circuiting
score.ts 4 weighted relevance factors
product.ts Postpaid vs card, deterministic
emi.ts tenures and exact-rounding schedules
decide.ts orchestrates the above
nudge/ sarvam.ts generation, validation, cache, fallback
templates.ts contextual copy in hi / en / ta / bn
The engine is a pure function. It reads no clock, no database and no environment — the caller supplies the timestamp and the nudge history. Three consequences:
The pitch rests on "the system already knows." That claim is backed rather than asserted:
affordabilityCapacity, which is what the affordability gate checks.So three of the fourteen gates are grounded in derived behaviour rather than a hardcoded flag. Open the demo drawer → "What the system already knows" to see the ledger, the detections and the resulting signal side by side.
Ordered, short-circuiting; the first failure decides the outcome and no score overrides it.
CATEGORY_PROHIBITED · MERCHANT_NOT_ENABLED · AMOUNT_FLOOR · AMOUNT_CEILING ·
CATEGORY_RELEVANCE · OPTED_OUT · COLD_START · NOT_ELIGIBLE · BANK_COOLOFF ·
FREQUENCY_CAP · NO_PRODUCT · ALREADY_ACTIVE · INSUFFICIENT_LIMIT · AFFORDABILITY
Two worth calling out. CATEGORY_PROHIBITED blocks person-to-person transfers, wallet
top-ups, gambling and crypto outright — routing borrowed money into a cash-equivalent is what
lending rules exist to prevent. AFFORDABILITY declines users who pass eligibility but whose
existing commitments leave no room; it is the gate that says we are not optimising for disbursal.
All three endpoints are plain HTTP and callable from n8n.
POST /api/decide// request — merchantId, or merchantCategory for merchants outside the catalogue
{ "userId": "u_rohit", "merchantId": "m_kroma", "amount": 50000 }
// response
{
"showNudge": true,
"product": "postpaid",
"score": 90,
"amount": 50000,
"blockedBy": null,
"offer": {
"partner": "Paytm Postpaid",
"limit": 100000,
"tenures": [
{ "months": 3, "emi": 16667, "lastEmi": 16666, "noCost": true, "interest": 0 },
{ "months": 6, "emi": 8727, "lastEmi": 8727, "noCost": false, "interest": 2362 }
]
},
"decline": { "label": "No thanks, pay normally", "suppressDays": 7 },
"trace": { "gates": [], "factors": [], "productRationale": "", "counterfactual": "", "summary": "" },
"eligibilitySignal": 86,
"eligibilityBreakdown": []
}
A withheld nudge returns the same shape with showNudge: false, a blockedBy code and a
human-readable blockedReason. No-nudge is a first-class response, not an error.
POST /api/nudge-textTakes terms the engine has already settled and returns one line of copy. Always succeeds —
source is sarvam, cache or template, and reason says why if it fell back.
GET /api/health · GET /api/profile?userId=Health is for the n8n healthcheck. Profile returns the derived features plus the ledger they came from.
Sarvam's job is phrasing, never deciding. The engine settles what to offer and on what terms; Sarvam says it well in the user's language. A language model must never be able to talk a user into credit the engine did not approve.
Three protections wrap the call:
Set SARVAM_API_KEY to go live. Without it every response is a template and says so.
Import n8n/one-tap-credit.workflow.json, then replace https://REPLACE-ME.vercel.app in the two
HTTP Request nodes with your deployed URL. Copy the production webhook URL into
NEXT_PUBLIC_N8N_WEBHOOK_URL.
Transaction event (webhook)
└─> Decision engine POST /api/decide
└─> Eligible? IF showNudge
├─ true ─> Pick headline plan ─> Sarvam nudge copy ─> Attach copy ─> Respond
└─ false ─────────────────────────────────────────────────────────> Respond
n8n Cloud cannot reach localhost, so the app must be deployed before the orchestrated path
works. The checkout falls back to calling /api/decide directly after 3 seconds, and the demo
drawer shows which path actually served the response — so a dead network degrades silently
instead of breaking the demo.
If the import misbehaves, the workflow is six nodes and takes about five minutes to rebuild by hand from the diagram above.
Open the drawer by tapping the avatar on the home screen. Each row is one tap.
| # | Do this | What happens | The line to say |
|---|---|---|---|
| 1 | Rohit → Kroma Electronics, ₹50,000 | Nudge: Postpaid, 3 × ₹16,667, no cost | "The offer appears at the moment of paying, in Hindi, already priced." |
| 2 | Tap Why am I seeing this? | 14 checks, 4 score factors, 5 signal components | "Every decision is auditable. That's slide 11, shipped." |
| 3 | Keypad → change to ₹450 | Nudge disappears, engine strip shows AMOUNT_FLOOR | "It declines more often than it offers." |
| 4 | Merchant → Rahul Sharma (P2P), ₹35,000 | CATEGORY_PROHIBITED | "No amount and no eligibility signal unlocks this one." |
| 5 | Persona → Priya, ₹50,000 | AFFORDABILITY, signal 70 | "She passes eligibility. We decline anyway — ₹8,727/month against ₹7,951 of capacity." |
| 6 | Persona → Aman | COLD_START — 18 days, 8 transactions | "Cold start is on our risk slide. Here it is, handled." |
| 7 | Drawer → What the system already knows | Ledger rows, detected salary, detected EMIs | "This is where the eligibility number comes from. Nothing is hardcoded." |
| 8 | Back to Rohit ₹50,000 → Activate & Pay → confirm | Approval, schedule, success | "16,667 + 16,667 + 16,666 — it adds up to exactly ₹50,000." |
| 9 | Terminal: npm test | 32 passing in ~150ms | "And it's covered." |
Closing line: "The credit products already exist. The bank approvals already exist. What was missing was the decision layer that knows when to ask — and, more often, when not to."
npm test # 32 tests: every gate, product selection, EMI rounding, the audit trail
npm run scenarios
The EMI tests are worth a look — no-cost instalments must sum to the principal exactly, and the final payment must never be the largest one.