Skip to content

Agent-boundary compaction: trading tool outputs stop misleading the model#331

Merged
luokerenx4 merged 3 commits into
masterfrom
UTA-issue
Jun 12, 2026
Merged

Agent-boundary compaction: trading tool outputs stop misleading the model#331
luokerenx4 merged 3 commits into
masterfrom
UTA-issue

Conversation

@luokerenx4

Copy link
Copy Markdown
Contributor

Summary

  • Compaction at the agent boundary (trading-compact.ts): unset = absent. Staged-order echoes / git status / push results / quotes / contract details / commits no longer dump 120-field IBKR serializations full of UNSET sentinels that read as data to an LLM. Measured live on okx demo: git status with one staged order went 4278B / 38 sentinels → 404B / 0. Money 2dp, prices 8dp at display; ledger precision untouched.
  • --help honesty: every order verb showed "(no flags)" because .transform() in the qty/price validators made z.toJSONSchema throw (silently caught). Input-side conversion fixes it — full flag lists now render.
  • Flow completion: git reject (undo for a wrong stage; auto-prepares the commit), order history / order trades (the same domain projections the UI reads — AI and human see one translation).
  • AccountInfo at the tool boundary follows the same never-fabricate rule as the UI panel (omit unreported fields).

Test plan

  • pnpm test 1895 passing (new: sentinel normalization across all three value forms incl. Decimal toFixed rendering; no-sentinel-in-JSON invariant; reject-reason preservation)
  • Live CLI walk on okx demo: stage→status (404B clean)→reject→history, place --help shows full flags, new verbs reachable

Boundary touch

Agent-facing trading tool outputs only; order execution paths unchanged.

🤖 Generated with Claude Code

…g to the model

Live audit of alice-uta found the agent surface poisoning analysis:
a staged order echoed the full IBKR Order serialization — 4.3KB, 38
UNSET sentinels per order. Sentinels READ AS DATA to an LLM
("minQty: 2147483647" looks like a real constraint), and a single
stage→status→push round burned thousands of tokens of noise.

trading-compact.ts: at the tool boundary, unset = absent. Contracts
keep instrument identity (IBKR-superset derivative fields ride along
exactly when set), Orders keep only set fields, results drop the raw
echo and the 120-field orderState while keeping the one signal field
(rejectReason). Money displays at 2dp, prices at 8dp; full precision
stays in the ledger. Measured live: git status 4278B/38 sentinels →
404B/0.

Discoverability fix: every order verb's --help showed "(no flags)" —
positiveNumeric's .transform() made z.toJSONSchema throw and the catch
silently emptied the manifest schema. io:'input' + unrepresentable:
'any' renders the input side, which is what a CLI manifest wants;
flags are now fully listed.

Surface completion: tradingReject (the undo for a wrong stage —
auto-prepares the commit so the mental model stays stage→reject),
orderHistory + tradeHistory tools (the same exchange-frontend
projections the UI reads), wired as git reject / order history /
order trades on alice-uta.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openalice-demo Ready Ready Preview, Comment Jun 12, 2026 1:02am

Request Review

…hannel, self-correcting errors

Used alice-uta end-to-end as the trading agent it serves. Three more
catches:

1. Per-account contract search ALWAYS returned [] — the SDK assumed the
   aggregated /contracts/search returns grouped {id, results[]} rows,
   but the route returns flat {source, contract} rows; the find() never
   matched. Worst possible failure for an agent: "SOL isn't tradeable"
   (it was). Shape aligned + search results now compact their contracts
   like every other output.

2. The tradingPush approval-wall message told agents users could
   approve via "Telegram /trading" — the Telegram connector was deleted
   in 0.30.0. Agents were relaying dead instructions. Now points at the
   Web UI surfaces that exist.

3. resolve(source) misses said "No accounts available." — false when
   accounts exist and the SOURCE didn't match. Now: 'Unknown source
   "okx-banana". Available accounts: …' — the agent self-corrects in
   one step instead of concluding the broker layer is down.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sweep

The headline catch from a full pre-trade→TPSL dogfood run: an attached
TP/SL order on okx spot STAGED fine, PUSHED fine, FILLED fine — and the
stop never existed. ccxt accepted the unified takeProfit/stopLoss
params and the venue mapping silently dropped them: the ledger said
"long with a stop", the exchange said "naked long". CcxtBroker now
REFUSES tpsl placement unless the exchange has a venue-verified
placeOrderWithTpSl override (none yet — okx needs attachAlgoOrds,
bybit its native v5 fields), with an actionable message. A missing
stop that looks attached is the worst failure mode a trading system
has; loud refusal beats silent downgrade.

CLI shim (all four byte-identical copies):
- JSON-looking flag values parse into objects — `--takeProfit
  '{"price":"1725"}'` previously shipped as a raw string and failed
  validation opaquely.
- Gateway validation errors now surface field-level zod issues, and the
  shim prints them — "Validation failed" alone stranded the agent
  guessing flag names.

Trading-as-git tool ergonomics (from the same run):
- placeOrder/closePosition/modifyOrder/cancelOrder accept commitMessage
  — stage AND commit in one call (one decision = one operation is the
  dominant agent flow; the push approval wall is untouched).
- placeOrder/closePosition derive source from aliceId when omitted —
  the account id was always inside the aliceId.
- compactStatus renames the overloaded "pending*" fields to
  awaitingApproval (pending ORDERS are a different thing).
- Sync commit messages carry symbols: "[sync] ETH filled" instead of
  "[sync] 1 order(s) updated".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@luokerenx4 luokerenx4 merged commit c548414 into master Jun 12, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant