← ClaudeAtlas

broker-adapterlisted

Generic broker interface for the example portfolio agent. Documents the adapter pattern (get_positions / get_nav / submit_order) with an allow_live poka-yoke, a no-op stub for demos, and Alpaca shown as one worked example using env-var credentials. Plug your own broker SDK behind this interface — NO real keys ship here.
Bubble-invest/bubble-ops-loop · ★ 0 · AI & Automation · score 68
Install: claude install-skill Bubble-invest/bubble-ops-loop
# broker-adapter — the generic broker interface This skill is the **single seam** between the example agent and the outside world where real money lives. The agent never imports a broker SDK directly; it talks to a `BrokerAdapter`. To support a new broker you implement one class behind this interface. To run a safe demo you use the built-in `StubAdapter`. ## Why a single adapter seam 1. **One fence, one poka-yoke.** Every mutating call goes through `submit_order`, which **refuses to place an order unless the caller explicitly passes `allow_live=True`**. This guard is independent of any agent prompt — accidental or exploratory calls cannot move money. 2. **Arm-state is testable.** `secrets_armed(broker)` is the *only* authority on whether a broker is live. The agent RUNS it; it never infers from memory. 3. **No SDK lock-in.** The agent reasons against `Position` / `AccountSummary` / `OrderResult` dataclasses, not a vendor's response shape. 4. **Credentials stay out of the repo.** Adapters read keys from environment variables only. Nothing is committed, nothing is hardcoded. ## The interface `broker_adapter.py` defines: ```python class BrokerAdapter(ABC): name: str def secrets_armed(self) -> bool: ... # are creds present in the env? def get_account(self) -> AccountSummary: ... # cash, equity, buying_power def get_positions(self) -> list[Position]: ... def get_nav(self) -> float: ... def submit_order(self, *, symbol, qty,