Lovinka
An autonomous multi-agent trading engine with a human-in-the-loop approval gate.
- →kafka bus · per-service routing
- →RAG context · confidence escalation
- →human-approval trade gate
- NestJS
- React 19
- tRPC
- Kafka
- Python
- TimescaleDB
An autonomous crypto-trading engine: ~20 LLM-driven services on a Kafka bus, each with per-service model routing, confidence-based escalation, and RAG market context. Trade proposals queue behind a human-in-the-loop approval gate; a React control plane shows positions, the live AI-call log and the approval queue. Self-hosted end to end — TimescaleDB for the time series, no third party in the trade path.
The problem
An LLM that reads a market and places an order is a five-minute demo. Running one is a different problem entirely. The danger isn't a wrong prediction — markets punish those cheaply. The danger is an autonomous system moving real capital on its own confidence, with no record of why it acted and no human in the decision.
I wanted the inverse. A system that does the analytical work continuously — ingesting data, forming signals, sizing positions — but that physically cannot touch capital without my approval. The intelligence runs unattended; the authority does not.
And I refused to build it on a stack I don't own. No broker's black box, no third-party inference sitting in the path between a market signal and an order. If the system was going to act on my behalf, every part of it had to be mine to inspect.
The architecture
I built it as ~20 LLM-driven services on a Kafka bus, each a narrow specialist — ingestion, market context, signal generation, risk, position sizing — rather than one prompt trying to do everything. Kafka decouples them: a service can fail and restart on its own, and the bus stays the durable record of what was decided and when.
Each service does per-service model routing — it runs the model that fits its job, not a single model stretched across all of them. When a service isn't confident in its own output, confidence-based escalation hands the call up to a stronger model instead of letting it guess. The cheap path stays cheap; the hard calls get the weight they need.
Reasoning is grounded with RAG over market context, so a proposal cites the conditions it was made under rather than free-associating. TimescaleDB holds the time series the whole system reads and writes. Everything is self-hosted end to end.
The human gate
Every service in the system can analyze. None of them can trade. A trade proposal is exactly that — a proposal — and it queues behind a human-in-the-loop approval gate that I hold. Nothing reaches the market until I approve it.
The React control plane is built around that gate, not around a P&L number. It shows live positions, the approval queue, and a live AI-call log — every model call the system made, with the reasoning behind it — so when a proposal arrives I can see how it was reached, not just what it recommends. The decision is auditable before it's authorized, not after.
No third party sits in the trade path. The inference, the data, the gate, and the execution all run on infrastructure I operate, which means the one place a human must intervene is also the one place no one else can. The AI does the work; the authority to act on real money stays with a person.