cd /news/ai-agents/i-built-an-autonomous-treasury-agent… · home topics ai-agents article
[ARTICLE · art-115274] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

I built an autonomous treasury agent, then let a code review bot find every way it could lose money

A developer built TreasuryForge, an autonomous treasury management agent for the WeMakeDevs × TrueFoundry Agent Harness Hackathon, using TrueForge's agent harness. The agent manages a simulated portfolio across cash, crypto, and NSE equities, with a human approval gate and a code review bot (Qodo) that caught critical bugs, including an approval bypass and a double-execution issue. The project demonstrates a safe decision loop with computed risk checks and sandboxed stress testing.

read5 min views1 publishedAug 29, 2026

I just submitted TreasuryForge to the WeMakeDevs × TrueFoundry Agent Harness Hackathon, an autonomous agent that manages a simulated treasury across cash, crypto, and NSE equities, built entirely on TrueForge, TrueFoundry's agent harness. This isn't a writeup about the idea. It's about what actually broke, what a code review bot caught before it shipped, and what I learned wiring a real approval gate into an agent loop.

The strategy is deliberately dumb. The harness around it is what has to be strong. TreasuryForge doesn't try to out-trade the market: it demonstrates a safe decision loop, real tool calls, computed risk checks (not the model's own guess), a sandboxed stress test when something looks risky, a hard human approval gate before anything executes, and a second agent that audits the first one's history afterward.

The hackathon's own bar for this was blunt: a judge has to see TrueForge reaching a tool, running code in a sandbox, and stopping for a person. If it'd work as well as a chat box, change the project.

So nothing here is custom orchestration:

What happens TrueForge primitive
Agent calls a tool A registered remote MCP server, not a function call from app code
A trade s for a human TrueForge's native approval checkpoint, not a custom /approvals endpoint
Pre-trade analysis runs TrueForge's own sandbox (bubblewrap-isolated), not a subprocess I spawned
Periodic self-review
create_sub_agent , a real child thread in the session, not the main agent reasoning longer

The wallet itself is a FastAPI + FastMCP server exposing get_portfolio

, check_risk_limits

, execute_trade

, etc. TrueForge never touches the database directly: every mutation goes through MCP, gated behind the approval checkpoint and a shared secret.

get_portfolio

/ get_transaction_log

, read-only evidence.check_risk_limits

for the exact trade it's considering. This is a execute_trade call unconditionally, so the four risk triggers can't live in TrueForge's own config; they have to be a real tool the human can trust.check_risk_limits

reports a breach, the agent runs exactly one Python script in TrueForge's sandbox, with no network access, applying a correlated shock (crypto −20%, equities −10%) to the fetched position values and computing the resulting drawdown.execute_trade

independently recomputes its own risk snapshot server-side; it doesn't trust whatever the model claims in reason

.user.tool_approval

.Current Threshold (5%): 3 decisions breached the limit. Alternative Threshold (7%): 0 decisions would have breached. Suggestion: relax the daily drawdown threshold. The current one flagged 3 of 20 recent trades as breaches despite portfolio equity remaining stable, while 7% still safely bounds risk below the historical 6.1% max drawdown observed.

Every PR went through Qodo before merging, and it wasn't style nitpicks. A few that stuck with me: The approval gate had a bypass. Early on, the wallet server bound to 0.0.0.0

instead of localhost, and the reset endpoint had no auth. Nothing stopped a direct MCP call from skipping TrueForge's checkpoint entirely, the one thing the whole project exists to guarantee.

A trade could double-execute on retry. execute_trade

reported failure to the caller after it had already committed the write. If the caller retried on that "failure," it would trade twice. Nastiest kind of bug: correct in the happy path, wrong exactly when something else already went wrong.

Fixing one race condition created another. Switching some FastAPI routes from async def

to synchronous def

(to stop blocking the event loop with SQLite calls) meant those routes now ran concurrently in a thread pool, which turned out to make the day-start risk-baseline rollover non-atomic. The fix for one review finding created a brand-new one, caught in the very next round. Then that fix had its own bug: the date was captured before acquiring the lock, so a stale thread could still overwrite a fresh baseline.

A test that didn't test what it claimed to. A migration race-condition test looked correct but wasn't actually exercising the race. Confirmed by deliberately sabotaging the code under test and checking the test still passed (it did, which meant the test was wrong, not the code, yet).

One finding I dismissed on purpose, not by accident. Qodo flagged that the dashboard's auth middleware fails open when no access secret is configured. True, but this project has exactly one operator and one deployment target (local, for a demo), not a production environment to fail closed in. I replied on the thread explaining why, and left it. Qodo accepted it and marked it resolved. Not every finding should turn into a fix; the point is deciding on the record instead of silently ignoring it.

Gemini's free tier (gemini-flash-lite ) ran out mid-testing on a single busy day. Groq's qwen3.8-27b

has an 8,000 token-per-minute ceiling that's uncomfortably close to this agent's own ~4,600-token fixed per-turn overhead, fine for light use, not for rehearsing a demo repeatedly. I ended up wiring in OpenRouter as a third provider, verified two of its free models with an actual multi-turn tool-call round trip (two others that claimed tool support failed on the first real call), and made the one that held up the default. TrueForge's manifest takes a single model.name

with no built-in runtime fallback between providers, so this is a fixed preference order picked at setup time, not live failover.

Repo: [github.com/codedpool/treasuryforge](https://github.com/codedpool/treasuryforge)

If you're building anything with a real approval gate in the loop, I'd genuinely recommend running a code review bot against every PR before you trust your own read of it. Three of the bugs above are things I was completely confident were fine.
── more in #ai-agents 4 stories · sorted by recency
── more on @treasuryforge 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-built-an-autonomou…] indexed:0 read:5min 2026-08-29 ·