Live Trading with Robinhood
Agents can be connected to a real Robinhood brokerage account and asked to propose and place orders against it. This is separate from backtesting (historical data) and from Alpaca paper trading (simulated money): here the account, the positions, and the orders are real.
Warning
Live trading places orders with real money in your own brokerage account. The agents here are LLM-driven research tools, not investment advice, and nothing in the Lab predicts market outcomes. Connect an account only if you accept the full risk of the trades an agent may place, and start with the review-only mode described below.
Live trading is off unless the deployment turns it on. On a server started with the default configuration, a live run does everything except send the orders — see the two gates.
Before you start
You need:
an ATL account (see Accounts and Profile) — the Robinhood link is stored against it, so live trading is not available to signed-out browser sessions;
a real agent under Playground → My Agents. The demo agents on the dashboard cannot be connected; create or copy one first;
a Robinhood account eligible for Robinhood’s Agentic Trading (MCP) access;
a deployment configured for Robinhood (Configuration (self-hosting)). If it is not, connecting fails with Robinhood OAuth is not configured.
Connect your brokerage account
Open the agent in the agent editor and find the Robinhood live trading section.
Click Connect Robinhood. You are sent to Robinhood to sign in and approve access.
Robinhood returns you to the dashboard, which finishes the link against the account you are signed in as.
The status line then reads Connected. Clicking Connect Robinhood again refreshes the account details rather than starting a second link.
Note
The link is completed in two steps on purpose. The page Robinhood redirects to cannot prove who you are, so it never stores credentials — it hands the dashboard a short-lived, single-use code, and the dashboard redeems it under your signed-in session. A link started from one account can never be redeemed by another.
Disconnect revokes access upstream where Robinhood supports it and deletes the stored tokens. Tokens are encrypted at rest.
Run an agent live
Tick Enable live trading for this agent. This is per agent, so connecting your brokerage account does not arm every agent you own.
Click Run Live.
The run then:
reads your Robinhood portfolio and buying power;
quotes the tradable universe — the DJIA 30 plus anything you already hold;
asks the agent’s model for orders, given that snapshot;
puts every order through the risk gate below;
reviews each surviving order with Robinhood, and places it only if the deployment allows execution.
The result panel reports what was proposed, what was rejected and why, and what was actually submitted.
The two gates
Orders reach the market only when both are true:
The agent has live trading enabled (the per-agent tick box), and
the server has execution turned on (
ROBINHOOD_EXECUTE=true).
The second gate is a deployment setting, not a UI control. With it off — the
default — the run still fetches your real portfolio, asks the model, and reviews
each order with Robinhood, but every order is recorded as skipped instead of
being submitted. The panel says Live review completed (execute off), and the
response carries "execute_enabled": false. This is the intended way to watch
what an agent would do with your real account before letting it act.
Risk gate
Every proposed order is clamped or rejected before it reaches the broker, on both the buy and the sell side:
No usable quote → rejected. An order that cannot be priced cannot be sized against the USD cap, so it is never passed through.
Notional cap. Quantity is clamped to
ROBINHOOD_MAX_ORDER_USD / price, default $25 per order. The cap is read per order, so it can be tightened on a running server.Share cap. No single order exceeds 10,000 shares.
Sells are clamped to what you hold, and rejected outright if you hold none of that symbol — an agent can never open a short.
Quantities are rounded down, so rounding cannot push an order back over the cap. A residual below the minimum order quantity is rejected.
One live run at a time is allowed per account; a second request while one is in
flight returns A live run is already in progress. Supply an
idempotency_key when driving the API directly to make a retry safe.
API
All routes need your ATL session token in the Authorization header.
Endpoint |
Purpose |
|---|---|
|
Connection state. |
|
Revoke upstream where supported and delete stored tokens. |
|
Run one live cycle. Body: |
|
Begin the OAuth link; returns |
|
Redeem the link code returned by the OAuth callback. |
dry_run: true forces a review-only cycle even on a server with execution
enabled. dry_run: false defers to ROBINHOOD_EXECUTE.
Troubleshooting
Message |
What to do |
|---|---|
Robinhood OAuth is not configured |
The deployment has no Robinhood settings. See Configuration (self-hosting). |
Create a real agent in My Agents first |
You are on a demo agent. Create or copy one, then retry. |
Connect Robinhood first |
No brokerage account is linked to your ATL account. |
Enable live trading for this agent |
Tick the per-agent box; connecting alone does not arm an agent. |
This Robinhood link was started from a different account |
The link was begun while signed in as someone else. Start again from the account you want to link. |
Link expired — please connect again |
The one-time link code lapsed (10 minutes) or was already used. |
A live run is already in progress |
Wait for the current run to finish. |
No LLM provider is configured |
The server has no LLM API key, so no decision could be made. Nothing was traded. |
Configuration (self-hosting)
Set these in dashboard/.env (see .env.example):
Variable |
Meaning |
|---|---|
|
Required. Fernet key encrypting broker tokens at rest. Without it the store refuses to read or write credentials — it deliberately does not fall back to a derived key. |
|
Robinhood Agentic Trading endpoint. |
|
OAuth callback. Must match the URL registered with Robinhood. |
|
Signs the OAuth |
|
|
|
Per-order notional ceiling, both sides. Defaults to |
Generate an encryption key with:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Linked accounts are stored in the CONTENT_DATABASE_URL Postgres database
when one is configured. Leave that unset only for local development — on an
ephemeral deployment, links do not survive a redeploy.