Docs / Proposals and approval

[ TUTORIAL ]

Proposals and approval

A proposal is an argument, not an order. This page covers how one is assembled, which parts of it a model wrote, which parts are arithmetic, and what your signature actually authorises.

How a draft is assembled

When a watch trips, the evaluator gathers the tripped watch, the latest quote, and your current positions, and asks a model for exactly three things: a title, a rationale, and a target allocation.

The request is made with a JSON schema attached, and the reply is re-validated against that schema in code before anything is stored. A model is never trusted to have obeyed its own contract.

PART OF THE PROPOSALWHO PRODUCED IT
TitleThe model — one line you can scan.
RationaleThe model — two to four sentences: what tripped, why it matters, what this draft does.
Proposed allocationThe model argues for it; code validates it.
Current allocationComputed from your quantities and the latest prices.
Portfolio valueComputed.
Trade notionalComputed.
Kind, agent, timestampsDerived from the watch.

Reading the allocation table

Each card shows current versus proposed percentages per symbol, and a notional. The notional is the money the change would actually move:

trade notional
drift  = Σ |proposed.pct − current.pct|      across every symbol
moved  = (drift / 2) × portfolioValueUsd / 100

# halved, because every percentage point sold
# is a percentage point bought somewhere else

The halving is the part people misread. A rebalance that shifts five points from one holding into another has ten points of total drift but moves five points of portfolio value, because the sale funds the purchase.

Reviewing a draft properly

Four questions worth asking of any proposal before you decide:

  • Are the prices real? Check the market badge. A proposal drafted on placeholder prices is a piece of fiction with a confident tone.
  • Does the rationale match the numbers? The model wrote the prose and the code wrote the table. When they disagree, the table is right.
  • Is the notional a size you would place? The percentages can look modest while the money does not.
  • Would you do this if no agent had suggested it? The failure mode of a review queue is rubber-stamping.

Deciding

Approve or reject, in the deck. Both are legal only from pending; anything else returns 409 rather than silently doing nothing.

the same decision over the APIBASH
curl -X PATCH https://oddysey.dev/api/proposals/<id> \
  -H "content-type: application/json" \
  -H "cookie: oddysey_session=<your session cookie>" \
  -d '{ "decision": "approve" }'

Approving marks work as authorised. It does not execute it.

No order is placed, no token moves, nothing is sent to a venue. The proposal becomes approved and an approval event is appended to the ledger.

Rejecting is terminal.

The proposal moves to rejected with a rejection event. If the same watch trips again after its cooldown, you get a fresh draft — rejecting does not disarm the watch.

Provenance, and how to verify it

Every proposal is hashed when it is drafted. The digest is a SHA-256 over a canonical rendering of the record — a fixed field list in a fixed order, joined by newlines — and it is stored beside the proposal and never recomputed.

what gets hashed
oddysey-proposal-v1
"<owner address>"
"<proposal id>"
"<title>"
"<agent>"
"<kind>"
"<rationale>"
[<current allocations>]
[<proposed allocations>]
<value in USD>
<created at, ms>

Only the digest is ever published. Your positions are nobody else’s business, and a hash proves a record existed at a point in time without saying what it said. Disclose the record to whoever you like, whenever you like; they recompute and check.

After you decide a proposal you may write that decision to the

ERC-8004 reputation registry

the on-chain registry where feedback about an agent accumulates

on Robinhood Chain. Oddysey assembles the call; your wallet sends it, and pays the gas. Approving records a point in favour of the agent that drafted it, rejecting a point against, and the digest rides along so the rating can be tied back to the exact draft it was about.

Closing the loop

An approved proposal is work waiting to be done somewhere Oddysey cannot reach. Your own agent — or you, by hand — executes it on whatever rail you use, then reports the fill through the record_execution tool with a venue and the venue’s own order reference.

That call flips the proposal to executed and appends an execution event attributed to the client that reported it. Only approved proposals can be closed out; anything else is refused. See connect your own agent for the wiring.