Retrieves related information by nearest neighbour.
BanditDBWhat should I do?
Learns from decisions and their outcomes, one prediction-action-reward tuple at a time.
your app / agents
│
├── SQL ─────────────► postgres "what is true?"
├── embed + ANN ─────► vector store "what is similar?"
└── predict/reward ──► banditdb "what should I do?"
# arms: the offers BanditDB can choose between at checkoutcurl -X POST http://localhost:8080/campaign \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "checkout_offer",
"arms": ["discount", "free_shipping", "gift"],
"feature_dim": 4,
"pacing": { "resources": [{
"name": "discount_spend", "budget": 5000, "horizon": 50000,
"arm_costs": { "discount": 5.0 }
}] }
}'
# make BanditDB a native tool in Claude, Cursor, or any MCP hostclaude mcp add banditdb banditdb-mcp \
--env BANDITDB_URL=http://localhost:8080
# your agent can now define its own decisions:# create_campaign("checkout_offer",# arms=["discount", "free_shipping", "gift"],# feature_dim=4)
Budgets and costs
Spend your budget where it pays back most.
Tell BanditDB what each option costs and how much you can spend. It spreads the budget across the whole period and puts each dollar where it brings the most return.
1
Give each option a cost
A search click costs $1.20, a social click $0.60, an AI ad $2.50.
2
Set a budget
For example, $5,000 a day. You can set several budgets at once, like total spend plus a cap for one channel.
3
BanditDB sets the bar
Each dollar gets a price that rises when spend runs fast. A channel wins only if its return beats that price.
Splitting a $5,000 daily ad budget between Search, Social and AI ads
Example figures
Fixed split, no pacing: budget gone by 13:00BanditDB: spread across the day
MomentCostChannel picked
Morning · bargain hunters$0.60Social
Afternoon · comparing products$1.20Search
Evening · asking AI what to buy$2.50AI ads
The pricier AI ad is bought only where its expected return clears the bar. Each dollar goes to the channel that earns most for that audience, and the budget lasts until midnight.
Every interaction shrinks the uncertainty around what works. The model updates in place, so memory stays flat no matter how much traffic the database has seen.
.91.12.04.08.12.74.09.03.04.09.66.14.08.03.14.81
.42.17.63.09
For data scientists
Old evidence fades. Every decision is on file.
Decision half-life
Markets drift and audiences change. Set a half-life and the model’s confidence halves on that clock, so it tests again instead of trusting stale wins. Its best guesses are kept.
At every checkpoint, each completed decision is written to Parquet per campaign: what it saw, what it chose, what happened, and the probability it had of choosing it.
Logged propensities make off-policy evaluation (IPS, SNIPS) possible. List files with GET /export.
Causal effects (CATE)
A bandit’s own scores are biased by who it chose to show each option to. Run the bundled causal-forest analysis on the export to separate real effect from selection.
Every reward is on disk before the API answers. If the server dies a moment later, the reward is still there.
POST /rewardWAL fsync200 OK
Recoverable
After a crash it rebuilds itself from disk. Nothing it confirmed is lost.
~0.6 sto replay 100,000 events on boot
Secure by default
Role-based access (RBAC)
Constant-time key checks
Per-key rate limiting
Input validation
JSONL audit log
Self-healing WAL
Model Context Protocol
Shared policy state for agent fleets.
The MCP server exposes campaigns as tools, so every agent in the fleet reads and writes one shared, persistent policy. Every recorded outcome sharpens the policy the whole fleet reads from.
claude mcp add banditdb banditdb-mcp --env BANDITDB_URL=http://localhost:8080