Spaces:
Runtime error
Runtime error
Avi-17 commited on
Commit Β·
2fb15fb
1
Parent(s): cfa5101
added blog
Browse files
CashFlow Arena: A Multi-Agent World Model for Enterprise Finance.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CashFlow Arena: A Multi-Agent World Model for Enterprise Finance
|
| 2 |
+
|
| 3 |
+
*How we taught an AI to manage liquidity, negotiate with vendors, and avoid the bankruptcy trap.*
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
## The timing gap
|
| 8 |
+
|
| 9 |
+
Business failure is often not a failure of product, but a failure of timing. From the collapse of retail giant Big Bazaar under debt pressure to the rapid burn of high-growth startups like Housing.com, the pattern is clear: companies fail when the timing gap between bills and receivables is managed poorly. Even companies like Jet Airways can mask a hollow cash-core with paper wealth until bankruptcy is inevitable.
|
| 10 |
+
|
| 11 |
+
CashFlow Arena addresses this gap by training a CFO-agent that manages liquidity as a dynamic, interactive decision-making task rather than a static reporting exercise.
|
| 12 |
+
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
## What we built
|
| 16 |
+
|
| 17 |
+
CashFlow Arena is a simulation in which an AI agent plays the CFO of a company across a sequence of business days. Each day, the CFO sees its current cash position, a stack of unpaid invoices, expected customer payments, available credit, and short memos from three specialist advisors. It must then decide β for each invoice β whether to pay in full, defer, partially settle, draw on credit, or negotiate.
|
| 18 |
+
|
| 19 |
+
Underpaying triggers compounding late fees. Overpaying drains the cash buffer needed to absorb shocks. The interesting part is that none of this is read from a spreadsheet. The CFO interacts with a *living* world model that generates events, applies them, ages obligations, and rolls the dice on whether customers actually pay on time.
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## The simulation environment
|
| 24 |
+
|
| 25 |
+
The environment follows the standard `reset / step / state` interface used in reinforcement learning, exposed via OpenEnv so any RL loop or remote client can drive it:
|
| 26 |
+
|
| 27 |
+
- **`reset(seed, difficulty, sim_window)`** initializes a fresh scenario β starting cash, credit limit, an initial invoice stack, expected receivables, and a hidden timeline of world events.
|
| 28 |
+
- **`step(action)`** applies one CFO decision (`pay`, `defer`, `partial`, `credit`, or `negotiate`) on a target invoice and returns the new observation.
|
| 29 |
+
- **`state`** returns the session metadata (episode id, step count) so any wrapper can track trajectories cleanly.
|
| 30 |
+
|
| 31 |
+
The state the CFO actually reasons over has these components:
|
| 32 |
+
|
| 33 |
+
- **Invoices** β vendor bills with amount, due date, late fee, and interest rate. Each day they age; once past due they incur fees and start compounding daily.
|
| 34 |
+
- **Receivables** β expected customer payments with an arrival day and a probability of actually showing up.
|
| 35 |
+
- **Credit** β a fixed credit line. The CFO can draw on it, but heavy use tanks the final score.
|
| 36 |
+
- **Vendor Profiles** β trust scores and negotiation flexibility, used by `negotiate` actions.
|
| 37 |
+
- **Advisor Memos** β structured notes from the three advisor agents.
|
| 38 |
+
- **World Events** β hidden, probabilistic shocks: equipment failure, tax audits, supplier price hikes, payment delays, fraud anomalies. The CFO doesn't see them in advance β only the Risk agent gets vague hints about market stress and upcoming threat level.
|
| 39 |
+
|
| 40 |
+
### Three difficulty modes
|
| 41 |
+
|
| 42 |
+
Every scenario is generated *dynamically* β no fixed test set, every run is a new game.
|
| 43 |
+
|
| 44 |
+
- **Easy** β comfortable cash buffer (βΉ40kββΉ50k), low interest, reliable receivables, generous deadlines.
|
| 45 |
+
- **Medium** β balanced pressure (βΉ25kββΉ35k cash), moderate interest, mixed reliability.
|
| 46 |
+
- **Hard** β tight runway (βΉ2kββΉ5k cash), short deadlines, high interest, unreliable receivables.
|
| 47 |
+
|
| 48 |
+
The generator runs a solvability check on every scenario to guarantee the agent isn't being thrown an impossible board. Hard mode is calibrated to be solvable but only with near-perfect timing β there's no slack to hide bad decisions.
|
| 49 |
+
|
| 50 |
+
---
|
| 51 |
+
|
| 52 |
+
## The multi-agent flow
|
| 53 |
+
|
| 54 |
+
Rather than asking one giant model to do everything, the CFO problem is split across four specialists:
|
| 55 |
+
|
| 56 |
+
- **Expenditure Agent** β reads the unpaid invoice stack and recommends a payment priority.
|
| 57 |
+
- **Revenue Agent** β projects expected inflows weighted by probability.
|
| 58 |
+
- **Risk Agent** β assesses debt-to-cash ratio, credit utilization, and threat hints from the world model.
|
| 59 |
+
- **CFO Agent** β reads all three memos, sees the full state and history, and produces the final action plan.
|
| 60 |
+
|
| 61 |
+

|
| 62 |
+
|
| 63 |
+
Each agent has its own system prompt with a structured JSON output schema. The three advisor outputs are inserted verbatim into the CFO's prompt as `ADVISOR MEMOS`. This compositional design lets us evolve each role independently, and gives us four distinct LLM calls to log, debug, and optimize.
|
| 64 |
+
|
| 65 |
+
---
|
| 66 |
+
|
| 67 |
+
## Two paths to a competent CFO
|
| 68 |
+
|
| 69 |
+
We pursued two complementary approaches:
|
| 70 |
+
|
| 71 |
+
### Approach 1 β SFT + RL
|
| 72 |
+
|
| 73 |
+
Train smaller models on demonstration data, then refine with reinforcement learning against the simulation's reward rubric. We collected expert trajectories using a rule-based "ideal CFO," fine-tuned via SFT, and ran RL on top to push beyond imitation.
|
| 74 |
+
|
| 75 |
+

|
| 76 |
+
|
| 77 |
+
**Pros:** cheap inference per call, no per-day API cost, the model develops policy intuitions you can deploy offline.
|
| 78 |
+
**Cons:** heavy training infrastructure, longer iteration cycles, and the SFT ceiling is bounded by how good the rule-based teacher is.
|
| 79 |
+
|
| 80 |
+
### Approach 2 β In-Context Learning (ICL)
|
| 81 |
+
|
| 82 |
+
Use a frontier-class model directly with carefully engineered prompts containing structured examples. No training, no GPUs, just clean prompt design and Groq's hosted `llama-3.1-8b-instant`.
|
| 83 |
+
|
| 84 |
+
**Pros:** zero training time, fast iteration, every reasoning step is plain text you can read.
|
| 85 |
+
**Cons:** per-call latency, per-call cost, and rate-limit ceilings cap throughput hard.
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
---
|
| 89 |
+
|
| 90 |
+
## The optimization story
|
| 91 |
+
|
| 92 |
+
### Cutting the LLM calls that didn't need to happen
|
| 93 |
+
|
| 94 |
+
A surprising number of days don't need a multi-agent reasoning chain at all. If there are no overdue invoices, fewer than three unpaid bills, and enough cash to cover everything, the answer is trivial: pay what's due soon, defer the rest. We added a **rule-based fast path** that skips all four LLM calls on those days. On easy and medium difficulty, this drops total LLM calls per simulation by 30β50%.
|
| 95 |
+
|
| 96 |
+
For the days that do need agents, we trimmed prompts aggressively. The advisor prompts originally asked the model to write a long `thought_process` field "first" β a chain-of-thought trick. The problem: the model would burn through its 256-token output budget writing CoT, then truncate the JSON, causing `json_validate_failed` errors. Dropping `thought_process` from the advisor schemas (it wasn't read downstream anyway) shrunk per-call prompts by ~55% and eliminated the truncation failures entirely.
|
| 97 |
+
|
| 98 |
+
### Parallelizing the advisors
|
| 99 |
+
|
| 100 |
+
The three advisors don't depend on each other. Running them sequentially with safety sleeps between calls was wasting ~6 seconds per complex day. Swapping to a `ThreadPoolExecutor(max_workers=3)` lets all three fire concurrently. Per-day wall-clock on complex days dropped from ~12s to ~4s.
|
| 101 |
+
|
| 102 |
+
### Why three API keys
|
| 103 |
+
|
| 104 |
+
Groq's free tier for `llama-3.1-8b-instant` enforces around 6,000 tokens per minute per organization. With four LLM calls per complex day, each consuming ~2,000 tokens, a 3-day simulation can easily blow past that ceiling β especially if the calls are bunched into the first 10 seconds of wall time.
|
| 105 |
+
|
| 106 |
+
Concurrent calls on a single key share the same TPM bucket, so parallelization alone doesn't help. The fix is **per-agent key isolation**: Expenditure β key 0, Revenue β key 1, Risk β key 2, CFO β reuses key 2 (it runs after the advisors finish, so no contention). This triples our effective TPM ceiling and keeps each agent's calls in a fresh budget.
|
| 107 |
+
|
| 108 |
+
A subtle gotcha worth flagging: rate limits are scoped per **organization**, not per key. Generating multiple keys from the same Groq account gets you nothing. The three keys must come from three separate accounts (different emails) to actually multiply capacity.
|
| 109 |
+
|
| 110 |
+
---
|
| 111 |
+
|
| 112 |
+
## Scoring the agent
|
| 113 |
+
|
| 114 |
+
Every simulation ends with a normalized score in [0, 1] across five dimensions:
|
| 115 |
+
|
| 116 |
+
- **Solvency** β did the company survive without a deeply negative balance?
|
| 117 |
+
- **Debt Clearance** β what fraction of invoices were fully paid?
|
| 118 |
+
- **Fiscal Discipline** β how well were late fees and interest avoided?
|
| 119 |
+
- **Credit Prudence** β was the credit line used sparingly?
|
| 120 |
+
- **Cash Management** β did the agent end with more cash than it started?
|
| 121 |
+
|
| 122 |
+
These produce a letter grade (AβF) and a per-dimension bar chart in the dashboard. The breakdown matters more than the headline number β an agent can ace solvency by hoarding cash and paying nobody, but it'll tank on debt clearance.
|
| 123 |
+
|
| 124 |
+
Per-step reward uses **OpenEnv's `Rubric` pattern** instead of a single monolithic reward function. Our `CashflowRubric` plugs into the env via `Environment.rubric` and composes several independently-weighted sub-rubrics (on-time payment bonus, late-fee penalty, credit-draw penalty, cash-buffer health). This avoids the classic monolithic-reward trap where one scalar accidentally rewards the wrong behavior, and lets us inspect *which* signal is driving learning per step β invaluable for tuning RL.
|
| 125 |
+
|
| 126 |
+
---
|
| 127 |
+
|
| 128 |
+
## Results
|
| 129 |
+
|
| 130 |
+
_with_baseline.png)
|
| 131 |
+
|
| 132 |
+
The SFT-trained CFO clears the rule-based baseline by a comfortable margin on medium and hard difficulty. The gain comes mostly from learning when *not* to pay β the baseline tends to over-pay early, leaving no buffer for unforeseen shocks.
|
| 133 |
+
|
| 134 |
+
_baseline.png)
|
| 135 |
+
|
| 136 |
+
Adding RL on top pushes the agent further, particularly on hard mode where world events make the difference between an A and a C. The RL-tuned CFO learns to draw on credit at exactly the right moments and to defer non-critical invoices in order to prevent bankruptcy.
|
| 137 |
+
|
| 138 |
+
---
|
| 139 |
+
|
| 140 |
+
## Why this matters
|
| 141 |
+
|
| 142 |
+
The CFO problem is a useful microcosm for a broader thesis: **production-grade financial decisions rarely depend on a single model output.** They depend on routing β who decides what, when, and with what context. CashFlow Arena makes that routing visible: each day produces an audit trail of which advisors fired, what they said, what the CFO concluded, and which world events shaped the result.
|
| 143 |
+
|
| 144 |
+
That same architecture β partial views, structured memos, a routing CFO, and a probabilistic world model β generalizes well beyond accounts payable. Underwriting, treasury management, supply chain risk, even ad-budget allocation share the same shape: a central decision-maker arbitrating between specialist views under partial information.
|
| 145 |
+
|
| 146 |
+
We're hopeful it generalizes. We're sure it taught us a lot about prompt budgets, rate-limit physics, and the difference between a model that works on day one and one that actually ships.
|
| 147 |
+
|
| 148 |
+
---
|
| 149 |
+
|
| 150 |
+
*Built with OpenEnv, Groq, and a healthy disrespect for free-tier TPM limits.*
|