30.0 / 30
What changed in the harness
Selection accuracy 93→96, token cost up 14%, unconfirmed writes 100%→100%.
Category breakdown
Where the score comes from.
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
01Safety
02Legibility
19.4 / 30
03Economics
17.3 / 20
04Discoverability
12.7 / 20
Highest-impact fix
Estimated gain +1 pointRewrite 23 underspecified tool descriptions
State each tool's behavior, explain every parameter, and declare return semantics, prioritizing tools exercised by failed selection tasks.
Description evidence
Defects and rewrites.
23 defects found across the exposed tool descriptions. Suggested rewrites make purpose, inputs, boundaries, and returns easier for an agent to understand.
| Tool | Defect types | Suggested rewrite |
|---|---|---|
list_subgraphs |
name_restates_behavior no_return_description |
Enumerate the Polymarket subgraphs available to this server and their purposes so a caller can choose which one to introspect or query. Returns a list where each entry identifies a subgraph (main, beefy_pnl, slimmed_pnl, activity, orderbook, open_interest, resolution, traders) with a short description and the key entities it indexes. |
get_subgraph_schema |
name_restates_behavior no_return_description |
Introspect one of the registered Polymarket subgraphs by passing its identifier (main, beefy_pnl, slimmed_pnl, activity, orderbook, open_interest, resolution, or traders). Returns the subgraph's complete GraphQL introspection schema (types, fields, enums, and relationships) so you can discover which entities and queries it supports before writing a query against it. |
query_subgraph |
name_restates_behavior no_return_description |
Run an arbitrary GraphQL query against a Polymarket subgraph. Provide subgraph (one of main, beefy_pnl, slimmed_pnl, activity, orderbook, open_interest, resolution, traders), a query string, and optional variables as key-value pairs. Returns the data the subgraph resolves, alongside any GraphQL errors, exactly as the subgraph responds. |
get_market_data |
name_restates_behavior params_unexplained no_return_description |
Fetch Polymarket market and condition records from the Main subgraph, including each market's outcomes and trading volumes. Use first (1-100, default 10) to control how many records are returned, orderBy to select the entity field to sort on (defaults to id; introspect the subgraph for the valid field names), and orderDirection to sort ascending or descending (default desc). Returns the matching list of market and condition records with their outcome and volume data. |
get_account_pnl |
no_return_description |
Retrieve a single trader's profit-and-loss and performance breakdown from the Beefy P&L subgraph for the given account (lowercase Ethereum address). Returns the trader's realized and unrealized P&L, trade counts, win rate, and related performance metrics. |
get_user_positions |
no_return_description |
Return the current open positions for account (lowercase Ethereum address) from the Slimmed P&L subgraph, showing each holding and its associated P&L. Degrades gracefully rather than erroring when the indexers are behind, so a caller can still get partial data. |
get_recent_activity |
name_restates_behavior no_return_description |
Fetch recent on-chain activity events — specifically splits, merges, and redemptions — from the Activity subgraph. Limit the count with first (1-100, default 20) and optionally filter to events involving a single account by Ethereum address. Returns a list of the most recent activity events with their details. |
get_orderbook_trades |
no_return_description |
Fetch recent order fills from the Orderbook subgraph. Filter by maker and/or taker Ethereum addresses and control the count with first (1-100, default 20). Returns the most recent trades with fill details such as token IDs, prices, and sizes. |
get_global_stats |
no_return_description |
Return aggregate Polymarket platform metrics without any parameters: market counts sourced from the Main subgraph combined with accurate total volume, fees, and trade numbers from the Orderbook subgraph. Use this for a quick platform-wide overview. |
get_daily_stats |
no_return_description |
Return per-day Polymarket statistics for the last days (1-90, default 7) from the Beefy P&L subgraph, including volume, fees, trader counts, and market activity per day. Use this for trend analysis and historical performance. |
get_top_traders |
no_return_description |
List the top Polymarket traders from the Beefy P&L subgraph, ranked by orderBy (totalRealizedPnl, collateralVolume, winRate, profitFactor, or numTrades; default totalRealizedPnl). Returns up to first (1-100, default 10) traders filtered to those with at least minTrades (default 10) trades, along with each trader's P&L, volume, and win metrics. |
get_market_positions |
no_return_description |
Return the largest positions for a specific outcome token (tokenId) from the Beefy P&L subgraph, sorted by orderBy (realizedPnl, unrealizedPnl, or valueBought; default valueBought) and limited by first (default 20). Each position shows who holds it, position size, and associated P&L. tokenId matches clobTokenIds from search_markets/get_market_info, token_id from get_clob_market, or makerAssetId/takerAssetId from get_orderbook_trades. |
get_market_open_interest |
no_return_description |
Rank Polymarket markets by open interest (USDC locked in outstanding positions) using data unique to the Open Interest subgraph. Returns up to first (1-100, default 10) markets, sorted by orderBy (amount, splitCount, mergeCount, or lastUpdatedTimestamp; default amount) in orderDirection order (asc or desc, default desc), with each market's OI and split/merge counts. |
get_oi_history |
no_return_description |
Return hourly open interest snapshots for a market given conditionId (the hex string obtained from get_market_open_interest or the main subgraph). Returns up to first snapshots (1-1000, default 168 which equals one week) in orderDirection order (asc or desc, default desc by timestamp). Use this to chart how a market's open interest changes over time. |
get_global_open_interest |
no_return_description |
Return the platform-wide total open interest — the aggregate USDC locked in outstanding positions across all Polymarket markets — from the Open Interest subgraph, with no parameters required. |
get_market_resolution |
no_return_description |
Return UMA oracle resolution status for Polymarket markets: whether each is initialized, proposed, disputed, or resolved, along with proposed and final prices and dispute history. Optionally filter by status, limit with first (1-100, default 10), and sort by orderBy (lastUpdateTimestamp or id) in orderDirection order (default desc). |
get_disputed_markets |
no_return_description |
Return Polymarket markets that went through the UMA oracle dispute process, where someone challenged a proposed outcome — a high-signal event. Returns up to first (1-100, default 20) disputed markets with their dispute history. |
get_market_revisions |
no_return_description |
Return moderator revisions and updates to Polymarket markets, showing when and how moderators intervened in market resolution. Optionally filter by questionId for a single market and cap the count with first (1-100, default 20). |
get_trader_profile |
no_return_description |
Return a trader's on-chain profile from the Traders subgraph for address: when they first appeared, their recent CTF events (splits, merges, transfers), and USDC flows. Returns up to eventLimit (default 20) recent events along with the overall profile summary. |
get_trader_usdc_flows |
no_return_description |
Return a trader's USDC deposit and withdrawal history for address, filtered by direction (inbound, outbound, or both; default both) and capped at first (1-100, default 50) transfers. Use this to see when traders fund or withdraw from Polymarket. |
list_polymarket_events |
no_return_description |
List Polymarket events, which are topic groups bundling multiple related Yes/No markets under one umbrella (for example an election containing many candidate markets), via the Gamma API. Returns up to limit (1-100, default 10) events, optionally filtered by the active and closed booleans and by tag, sorted by orderBy (volume, liquidity, startDate, endDate, or createdAt), with ascending (default false) controlling the sort direction. |
get_polymarket_event |
no_return_description |
Fetch a single Polymarket event for eventId (an event ID or slug) along with all the markets it bundles, since an event groups related prediction markets under one topic. Returns the event metadata and its associated markets. |
get_last_trade |
name_restates_behavior no_return_description |
Fetch the most recently executed trade for a Polymarket outcome token from the CLOB. Returns the last trade price, which is useful for gauging the current market price and recent trading activity before placing an order. |
Selection evidence
Confusable tool pairs.
9 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
search_markets |
search_markets_enriched |
high | Nearly identical names; a query like 'search markets for Trump' returns valid results either way, and enriched still satisfies 'search markets' tasks, masking the intended distinction and blocking enrichment. |
get_market_info |
get_clob_market |
medium | Both are accessed via market identifiers and both describe CLOB-related data; 'get the clob market info for condition X' plausibly maps to either, especially since get_market_info also returns CLOB token IDs and lists CLOB calls in its description. |
get_market_resolution |
get_disputed_markets |
medium | Both cover UMA/oracle dispute data; a task like 'which markets were disputed' or 'show dispute status' could pick get_market_resolution (which includes a 'disputed' filter) instead of get_disputed_markets, or vice versa. |
get_live_prices |
get_live_spread |
low | Both take CLOB token IDs and return current price-like data ('price' vs 'bid/ask'), so 'get the real-time price of token X' is adequately matched by either, though names and descriptions mostly disambiguate the exact output. |
get_market_data |
get_market_info |
medium | Names are near-identical ('market data' vs 'market info'); a task like 'get market data for a specific market slug' could select the subgraph market listing tool instead of the Gamma market-info tool, since both fetch market metadata. |
get_orderbook_trades |
get_live_orderbook |
medium | Both share 'orderbook' and a task like 'show me the orderbook trades for this market' is ambiguous between recent fills (orderbook subgraph) and the resting bid/ask book (live CLOB), though descriptions partially disambiguate. |
get_market_positions |
get_clob_market |
low | Both index data by token/condition IDs, so a request like 'get positions/clob details for this market token' could briefly route to either, but the descriptions (top holders+P&L vs token IDs+prices) separate them clearly. |
get_live_prices |
get_last_trade |
low | Both provide a 'real-time price' for a token; 'get the current/last price of token X' is satisfied by both, though 'last_trade' is specific enough in name and description that genuine mis-selection is unlikely. |
get_live_spread |
get_live_orderbook |
low | Both return bid/ask data for one token and both contain 'live'; 'give me bid and ask / the spread / the order book depth' could point at either, but descriptions (spread metrics vs full depth) differentiate them well. |
Compare the field