01Safety
0.0 / 30
What changed in the harness
Selection accuracy 100→100, token cost up 4%, unconfirmed writes 0%→0%.
Category breakdown
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
0.0 / 30
24.6 / 30
17.7 / 20
12.3 / 20
Highest-impact fix
Estimated gain +30 pointsExpose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
7 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 |
|---|---|---|
search_articles |
params_unexplained |
Search Storyflo's article corpus. Pass query as the free-text search term. Use vertical to scope the search to a single vertical (tech / finance / science / media / sports / culture). Set limit to cap the number of matches returned (1-100, default 20). Returns slug, title, publisher, vertical, snippet, audio_url, and listen_seconds for each match. |
get_article |
params_unexplained |
Fetch the full record for an article by slug, including body_text + audio_url. Pass the article's slug, exactly as returned by search_articles. |
get_audio_url |
params_unexplained |
Resolve the playable audio URL for an article by slug. Returns a stitched-with-ad URL on the free tier or the bare audio for plus/pro. Pass the article's slug, exactly as returned by search_articles. |
get_market_linked_stories |
params_unexplained |
Storyflo stories that match an actively traded event contract on Kalshi (a CFTC-regulated exchange). Each item carries qualitative signal tags (high_velocity, genuine_uncertainty) plus a link-out to Kalshi's own page where the live market data lives. Editorial sourcing surface, not market-data redistribution: Storyflo never returns raw prices, market-implied probabilities, volumes, or open interest in this payload. Use this when the agent needs to know which Storyflo stories are about news themes that have an actively traded event contract — e.g. World Cup matches, political mention contracts, corporate events. Filter by story vertical, Kalshi category (Politics, Economics, Companies, Science and Technology, Sports), or by signal tag. Set limit to cap the number of stories returned (1-50, default 10). |
digest |
params_unexplained no_return_description |
Aggregate and return the top-N articles across the selected verticals for the requested window. Pass verticals as the list of verticals to pull from (tech / finance / science / media / sports / culture), window as the lookback period (24h / 7d / 30d, default 24h), and limit to cap how many top articles to return (1-20, default 5). Heaviest action — counts more against the per-agent rate limit. Use this for 'read me today's tech news' style prompts. |
search_declassified |
params_unexplained no_return_description |
Search Storyflo's Declassified archive — narrated cases drawn from FBI, CIA, NSA, NASA, DOJ, AARO, war.gov and other publicly-released government documents. Pass query as a substring matched against case title + synopsis, and set limit to cap the number of matching cases returned (1-50, default 10). Returns the matching cases (e.g. title, slug, synopsis) so the agent can fetch the full case via get_declassified_case or hand the audio_url to a player. Use when the agent needs to find a Declassified case matching a topic (e.g. 'UAP', 'JFK', 'COINTELPRO', 'Roswell'). Public — no auth required. |
digest_declassified |
params_unexplained |
Return the most-recently-published Declassified cases over a rolling window. Use for 'what's new in Declassified this week' style prompts. Pass window as today (~24h), week (default), or month, and set limit to cap the number of cases returned (1-50, default 10). Public — no auth required. |
Selection evidence
12 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
get_embedder_manifest |
get_embedder_network_manifest |
high | Nearly identical names — both wrap a 'manifest' and only differ by per-embedder vs network scope. A task like 'read the embedder manifest' or 'get the manifest JSON' maps to both; the network one takes no args while the per-embedder one requires a slug, so the agent must guess the scope from context. |
get_vertical_briefing |
get_vertical_landscape |
high | Both take a single vertical and describe a per-vertical package of top stories/audio. 'Give me the tech vertical briefing' or 'set up the finance vertical' fits either description; one returns a payable audio briefing, the other an onboarding bundle with RSS + sample audio, so the wrong pick is a real risk. |
subscribe_topic |
subscribe_declassified_topic |
medium | Both 'subscribe…topic' tools mint podcast RSS feeds. 'Subscribe me to the UAP topic' could send the agent to subscribe_topic (which only accepts the 6 vertical slugs and would fail) instead of subscribe_declassified_topic, or vice versa for a generic 'subscribe to a topic' prompt. |
digest |
digest_declassified |
medium | Both aggregate top content over a window and share the 'digest' + 'window' semantics. 'What's new this week?' or 'give me the digest' is ambiguous: digest needs verticals for articles, digest_declassified covers cases with no vertical param, so the agent must infer the corpus from the task. |
search_articles |
search_declassified |
medium | A generic 'search Storyflo for X' task fits both — same verb, both search a Storyflo corpus. 'Search for UAP' or 'find JFK content' could be routed to search_articles (article corpus) when the declassified archive was intended, since neither description mentions the corpus explicitly in the name. |
get_article |
get_declassified_case |
medium | Both fetch a full record by slug and both return body/audio_url — 'get the full record for slug X' is genuinely ambiguous about whether X is a regular article or a declassified case; nothing in the names disambiguates the corpus. |
list_subscriptions |
list_podcasts |
medium | 'List my podcasts' reads as ambiguous: list_subscriptions returns the listener's own minted feeds while list_podcasts returns the public show catalog. A task phrased 'show me the podcasts' could surface the catalog instead of the user's personal subscriptions, or vice versa. |
get_market_linked_stories |
get_crypto_market_link |
medium | Near-mirror names combining 'market' + 'linked/link'. 'Get me market stories linked to crypto' could route to get_crypto_market_link (returns just an affiliate URL) instead of get_market_linked_stories (returns the Kalshi-matched stories), or a BTC market-link request could land on get_market_linked_stories. |
search_declassified |
digest_declassified |
medium | 'Show me the latest declassified cases' fits both: search_declassified is the discovery verb for cases and digest_declassified returns the most-recent cases over a window. Without a phrase like 'this week' or an explicit topic query, the agent can't tell which path was intended. |
get_article |
get_audio_url |
low | 'Get the audio for article X' could resolve to get_article (returns audio_url in the full record) instead of the dedicated get_audio_url stitcher, or a request for the full record might land on the audio-only tool. Both take the same slug, so the mispick is plausible but the functional delta is small. |
get_trending_topics |
get_vertical_landscape |
low | 'What's hot in tech right now' could go to get_trending_topics (cross-vertical trending snapshot) or get_vertical_landscape (single-vertical top stories). Both surface top/per-vertical stories, so the agent must guess whether the user wants the global snapshot or a single-vertical deep-dive. |
register_embedder |
get_embedder_network_manifest |
low | Both share the 'embedder onboarding' theme — register_embedder returns the signup URL while get_embedder_network_manifest returns the DSP/SSP integration bundle. 'Help me onboard as an embedder' or 'get the embedder onboarding package' could select the wrong member because the action words overlap. |
Compare the field