Qualto documentation

Claim-bound orders on Binance Agent OS

Everything on this page reflects the shipped code at main. No command here is hypothetical.

Start

Install

Python 3.11 or newer. Zero runtime dependencies, the whole gateway is standard library.

# from the repository root
python3 -m venv .venv
.venv/bin/pip install -e ".[test,quality]"
.venv/bin/pytest -q   # 11,414 tests, ~16s, no network

The qualto command is installed on your PATH by the same step.

Quickstart

The full loop, read-only first, then one zero-cost proof cycle:

# 1. gateway check: initialize, tools/list, account read. read-only.
qualto smoke

# 2. draft a claim from a mandate. no order is placed.
qualto propose --mandate "buy 5 USDT of BNB" --symbol BNBUSDT

# 3. place, attest, prove, cancel. real order, zero cost pattern.
qualto claim --claim-file my-claim.json \
  --receipts-file runtime/receipts.jsonl \
  --confirm-live-write \
  --cancel-after-attestation

# 4. re-verify any receipts file against live Binance. read-only.
qualto verify --receipts-file runtime/receipts.jsonl
Zero-cost proof pattern: a below-market dust LIMIT order with --cancel-after-attestation exercises the entire bind, dual readback, attestation, and cancellation cycle with no fill. Every live proof in this repository used it.

Prerequisites

RequirementDetail
Binance Agentic sub-accountFunded. This is the structural envelope: the agent can never touch main-account funds.
Supported host credentialA registered host (for example the Codex CLI with the Binance connector authenticated). Set QUALTO_CODEX_CREDENTIALS_FILE to your credential path.
Optional: HermesOnly for the bundled agent loop (qualto propose / qualto agent). Override with QUALTO_HERMES_BIN and QUALTO_HERMES_PYTHON.

Qualto reads the credential per request, in memory, and never writes it to logs or receipts. If it is missing, malformed, or expired, every command fails closed with no order sent.

Concepts

The claim contract

A claim is a strict JSON object. Exactly these nine fields, nothing more, nothing less. Unknown fields are rejected before anything is sent.

{
  "claimId":  "qualto-claim-<12 lowercase alphanumerics>",
  "mandate":  "what the operator asked for",
  "symbol":   "BNBUSDT",
  "side":     "BUY | SELL",
  "orderType": "LIMIT | MARKET",
  "quantity": "0.009",
  "price":    "600",          // null for MARKET
  "status":   "NEW | FILLED | PARTIALLY_FILLED | CANCELED",
  "reason":   "the agent's honest reasoning, 1-1000 chars"
}

Field rules

FieldRule
claimIdFormat qualto-claim- plus 12 lowercase alphanumerics. Single-use per session: a replay is rejected before placement and logged.
quantity, pricePositive finite decimal strings. Never floats. Sent to Binance exactly as written.
priceRequired for LIMIT, must be null for MARKET.
statusThe status the claim commits to at readback. NEW for resting limit intent, FILLED for market intent.
mandate, reason1 to 500 and 1 to 1000 characters. The mandate is the human instruction; the reason is the agent's stated justification.

Claim binding

Binding happens at placement. The harness, never the LLM, sends the order with newClientOrderId = claimId. From that moment the claim's ID lives inside Binance's own order record, visible in Binance order history.

At readback the order is fetched twice from Binance Agent OS: by orderId and by origClientOrderId. Both readbacks must return the same order. Then six fields are diffed:

FieldMatch rule
claimIdexact, against the order's client order ID
symbol, side, statusexact
quantityexact
pricewithin 0.5% of the claimed price

Verdicts

VerdictMeaningSession effect
PROVEDAll six fields matched on a live dual readbacknone
UNPROVEDThe exchange could not prove the claim: readback failure, disagreement, or field mismatchsession BLOCKED
PARTIALIdentity matched and the order is partially filled. The filled quantity is recorded.none
PENDINGA claimed market order is still NEW. Retried up to 3 times, 2 seconds apart, before a final verdict.none until retries exhaust
No third path: a claim is never marked PROVED from any source other than a live Binance readback. Not the LLM, not the log, not the operator.

Session states

StateEntered whenCan write orders?
CREATEDCONNECTEDACTIVENormal startyes, when ACTIVE
BLOCKEDAny UNPROVED verdict, failed cancellation, or unresolved cleanupno. further placement refused
ERRORAgent or execution failure before attestationno
CLOSEDSession closeno, terminal

From BLOCKED, an operator can still cancel a known order (cleanup is allowed, new writes are not), then recover the session explicitly. The agent cannot unblock itself.

Reference

CLI reference

qualto smoke

Read-only gateway check: MCP initialize, tools/list, account read. Prints client ID, protocol version, visible tool count, and balance record count.

qualto propose

FlagDefaultMeaning
--mandaterequiredFree-text operator instruction, 1-500 characters.
--symbolBNBUSDTUppercase Binance spot symbol.

Fetches live price and balance, asks the bundled LLM loop for one claim, validates it, prints the claim JSON. Places no order.

qualto claim

FlagDefaultMeaning
--claim-filerequiredPath to a claim JSON object.
--receipts-fileruntime/receipts.jsonlAppend-only JSONL receipt path.
--confirm-live-writeoffAuthorizes the live order request. Without it: exit 2, nothing sent.
--cancel-after-attestationoffCancels the proved order immediately after dual readback.

qualto agent

One command: mandate → generated claim → placed order → attestation → optional cancellation. Flags of propose and claim, plus:

FlagMeaning
--disconnect-before-orderSevers the gateway after claim generation, proving the negative path: UNPROVED, BLOCKED, then reconnect and recover.

qualto cleanup

Recovers an orphan order by claim ID and cancels the exact exchange order. Use when a placement's outcome is unknown. Requires --confirm-live-write.

qualto verify

Re-verifies every claim attestation in a receipts file against live Binance state. Read-only, calls only spot.getOrder. Prints a per-claim match table.

Receipt events

Receipts are append-only JSONL. Every line is timestamped and written with fsync before the flow continues. The verdict field appears only on attestation and cancellation events; lifecycle events use outcome.

EventWritten whenKey fields
order_submittedImmediately before the placement callclaim, orderRequest
claim_attestationAfter dual readback and field diffclaim, attestation, both readbacks
order_cancellationAfter a proved cancellationorder, verdict
order_cleanupOrphan resolution attemptoutcome: resolved / unresolved
claim_rejectedClaim ID replay attemptclaimId, reason
gateway_recoveryReconnect and session recoveryclaimId, reason
session_errorSession enters ERRORerrorType (class name only, never the message)

Exit codes

CodeMeaning
0Success. For write commands: verdict PROVED.
1Failure or unproved verdict. Read the reason on stderr.
2Live-write confirmation missing. Nothing was sent.
Trust

Verification

Qualto's receipts are convenience. The proof is the Binance order record.

Binance orderClaim IDVerdict
12565050896qualto-claim-56eda03b6069PROVED then CANCELED
12565013192qualto-claim-live00000002PROVED then CANCELED

Both orders remain in Binance order history with the claim IDs above as their client order IDs. To re-check any receipts file against the exchange right now:

qualto verify --receipts-file runtime/receipts.jsonl
# claimId                  orderId      recorded  live     matched
# qualto-claim-56eda03b6069 12565050896  PROVED    PROVED   true

Security model

Tool allowlist

Binance Agent OS exposes 366 tools. Qualto's gateway admits exactly 6: spot.getAccount, spot.tickerPrice, spot.newOrder, spot.getOrder, spot.myTrades, spot.deleteOrder. Everything else is rejected client-side before a request exists. No withdrawals, no transfers, no futures, no margin.

Who can place orders

Only the harness, only claim-bound, only after --confirm-live-write. The LLM has no tools, receives the prompt over stdin, and its output is validated against the strict claim schema with the harness-assigned claim ID enforced.

Credential handling

The host credential is loaded per request, kept in memory for that request, never logged, never in receipts, never in error messages. Expiry is checked on every call. Missing, malformed, or expired: fail closed, no order.

Agent skill

Qualto ships as a SKILL.md-compatible agent skill that teaches any agent to trade claim-bound: never place raw orders, always go through the harness, never soften an UNPROVED, stop when the session locks.

# Claude Code
cp -r qualto/skills/qualto-trading ~/.claude/skills/
# Qwen Code
cp -r qualto/skills/qualto-trading ~/.qwen/skills/

Limits

Single session, spot only, one symbol per claim. Attestation is per-order, not per-strategy. Qualto does not judge whether a trade was smart, only whether it happened exactly as claimed. The claim file, not the mandate, is the binding contract. Third-party agent OAuth identities are not yet admitted by Binance; Qualto runs on the supported host-credential path.