A reasonable critique we keep hearing about sealed-bid RFQ goes roughly: the model fixes intent leakage, sure — but six MCP tools sound thin. Who validates signal quality before settlement locks in?
It's a fair question. "Sealed-bid" tells you what other traders don't see. It doesn't tell you what the protocol does see. So this post walks through the four pre-settlement filters that a quote has to clear on Hashlock Markets before an agent ever sees a price, and before an HTLC ever funds.
The TL;DR: six tools is the surface that an MCP-capable agent calls. The substrate underneath is a four-stage filter chain that runs before respond_rfq ever returns a quote to the caller.
The flow, in one sentence
A trader (human or agent) calls create_rfq with an intent. The intent contains a counterparty_filter block. The protocol broadcasts the auction to the subset of registered market makers that pass the filter. Each maker that wants to quote calls respond_rfq. Their quote runs through three more filters before it lands in the trader's wallet as a quotable offer. Only after the trader picks a quote does an HTLC chain get armed with create_htlc.
So there are two distinct broadcast/filter passes — before auction (Layer 1) and per quote (Layers 2–3) — plus an audience-bounding option (Layer 4) that runs at the broadcast stage for the most selective intents.
Let's walk them.
Layer 1 — counterparty KYC tier (auction-time filter)
Every registered market maker carries a tier:
-
NONE— anonymous, fresh wallet, no attestation -
BASIC— wallet plus light verification (jurisdiction signal, sanctions check) -
INSTITUTIONAL— full KYC/KYB attestation with notarized credentials -
RING— by-invitation set, pre-approved by a specific trader or trader collective
The trader's intent carries a counterparty_filter field. The simplest form is a minimum tier:
{
"kind": "swap",
"give": { "asset": "USDC", "amount": "250000.00", "chain": "ethereum" },
"want": { "asset": "BTC", "min_amount": "0.0", "chain": "bitcoin" },
"deadline": "2026-05-04T11:30:00Z",
"counterparty_filter": {
"min_tier": "INSTITUTIONAL",
"exclude": ["did:hashlock:maker:0xabc...123"],
"include": null
}
}
When the protocol auctioneer receives this intent, it computes the eligible maker set as { all_registered_makers } ∩ { tier ≥ INSTITUTIONAL } \ { excluded }. A NONE-tier maker never receives the auction broadcast for this intent. No off-chain hint, no sniff of the size. They simply aren't on the wire.
This matters because the most common information-leakage attack on RFQ systems isn't a leak from the trader, it's a leak through the maker pool — a quoting maker walks the order to a backchannel before responding. Bounding the auction audience to attested makers cuts the attack surface up front.
Layer 2 — bonded reputation (per-quote filter)
A quote is not free. To call respond_rfq and have the quote land in the trader's wallet, the maker has to post a bond that is slashable on:
- cancel-after-quote (maker walks back the quote before the trader's chosen-quote window closes)
- failure-to-fund (maker is selected but doesn't lock the matching HTLC within the protocol's lock-window)
- repeated stale quotes (a Sybil-style noise pattern that the auctioneer detects across windows)
The bond size scales with the maker's tier and the intent's notional. The accounting is per-pair, so a maker with a great track record on USDC↔BTC and a thin track record on USDC↔SUI carries different bond requirements per intent type.
The slash conditions are checked at three points: end of quote window, end of HTLC arming window, and end of HTLC settlement window. Slashed bond is paid out partly to the trader (as a settlement-failure cushion) and partly burnt — the second piece is what makes spam economically negative.
The visible effect is that a maker's quote isn't just a price — it's a price plus economic skin. That's the bit a "what validates the signal?" critique often misses: the quote-side bond is the answer to the maker's information advantage. The maker can know more than the trader, but they can't extract that information for free.
Layer 3 — price-deviation guard (per-quote filter)
Before a quote lands in the trader's wallet as a clickable offer, the protocol applies a hard sanity check against an internal mid-mark for the pair. Quotes whose midpoint is more than N basis points off mid are dropped. They don't reach the trader. The maker is not slashed (this isn't a malicious-quote condition, it could just be stale data on the maker side), but the quote is filtered.
The mid-mark itself is an oracle composite — a TWAP across the protocol's own internal trade history for the pair, blended with external feeds, with the blend weights tuned per pair (deeper pairs weight internal history more, shallow pairs weight external feeds more). The deviation threshold N is a per-pair parameter that the protocol tunes against the realised volatility of the pair, so a stable-stable pair has a tighter deviation threshold than a long-tail pair.
The point of this layer is not to enforce a "fair price" — sealed-bid auctions are explicitly designed so the trader picks among quotes — it's to drop quotes that would never be acceptable to any rational trader. It's a noise filter. An agent that hands a quote-list to its routing logic is then choosing between quotes that are all within a sane band, instead of having to reason over outlier garbage.
For an agent in particular, this is the layer that makes "quote shopping" tractable. Your LangChain or Claude Desktop or Cursor-driven agent doesn't have to write outlier-handling code; the protocol's already done it.
Layer 4 — ring privacy (auction-time, optional)
Ring privacy applies for the most sensitive intents. Instead of broadcasting to "all makers passing the tier filter", the trader can specify an inclusion list — a hand-picked set of counterparty DIDs:
"counterparty_filter": {
"min_tier": "RING",
"include": [
"did:hashlock:maker:0x1f...aa",
"did:hashlock:maker:0x82...c4",
"did:hashlock:maker:0xb7...39"
],
"exclude": null
}
Now the auction broadcasts only to those three makers. The intent isn't visible to the rest of the maker pool at all. This is the OTC-desk pattern: a trader who has a relationship with three institutional desks runs the RFQ across those three only. Sealed-bid (each maker's quote is private from the others) and audience-bounded (the intent itself is only visible to the chosen audience).
For agent-to-agent trading — two agents who already know each other's DIDs — Layer 4 is the natural default. The MCP server exposes the counterparty_filter field on create_rfq, so the agent's logic just sets include: [counterparty_did] for a known counterparty trade.
Putting it together
The quote that finally lands in the trader's wallet has cleared:
- an auction-audience filter (Layer 1, optionally Layer 4)
- a per-quote bonded reputation gate (Layer 2)
- a per-quote price sanity check (Layer 3)
Then the trader picks a quote. Only then does create_htlc arm the cross-chain settlement, and the HTLC's hashlock+timelock primitives take over for the actual atomic exchange.
So the answer to "who validates signal quality before settlement locks in?" is: the protocol does, in four layers, before an agent ever sees the quote and before any chain's HTLC contract is touched. The MCP tools (create_rfq, respond_rfq, get_htlc, create_htlc, withdraw_htlc, refund_htlc) are the user-facing surface. The validation chain is the machinery underneath that makes the surface usable.
What this means for agent builders
If you're wiring an MCP-capable agent (Claude, GPT, LangChain, Cursor, custom runtime) into Hashlock Markets, three practical implications:
- You don't need to write counterparty-quality logic. Set
min_tieron the intent and let the protocol filter the audience. Default toBASICfor retail-size intents,INSTITUTIONALfor size,RINGfor desk-to-desk and agent-to-agent. - You don't need to write outlier-quote handling. Layer 3 already drops the noise. Your routing code chooses among quotes within a sane band.
- You don't have to trust that a quote will be honored. Layer 2's bond is the maker's economic commitment. Cancel-after-quote and failure-to-fund both burn maker collateral.
That's the substrate the six tools sit on. Sealed-bid is the headline; the four-layer validation chain is what makes the headline true under load.
The MCP server is on npm as @hashlock-tech/mcp (scoped) and on the canonical MCP Registry at io.github.Hashlock-Tech/hashlock. Two transports: stdio via npx -y @hashlock-tech/mcp, or hosted Streamable HTTP at https://hashlock.markets/mcp. SIWE on the auth, six tools on the wire, and the four-layer filter underneath.
If you've been on the fence about pointing an agent at non-custodial OTC because counterparty quality felt like a black box — this is the box.
Hashlock Markets — sealed-bid RFQ + HTLC atomic settlement for AI agents.
Site: https://hashlock.markets
Hosted MCP: https://hashlock.markets/mcp
GitHub (canonical): https://github.com/Hashlock-Tech/hashlock-mcp
Top comments (0)