01Safety
0.0 / 30
What changed in the harness
Selection accuracy 100→100, token cost up 2%, 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
26.0 / 30
15.9 / 20
11.7 / 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
5 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 |
|---|---|---|
publish |
params_unexplained |
Publish a markdown article to one CMS platform: devto, ghost, hashnode, wordpress, medium, or substack. Costs 1 credit per call. Requires platform credentials configured via the setup tool. Supports draft or published status, tags, canonical_url for cross-posting, series on Dev.to and Hashnode, and featured_image_url as the article's lead cover image. Substack is published via reverse-engineered cookie auth. Returns: { url, id, platform, status }. Common errors: platform not configured (VALIDATION_ERROR), credit exhaustion (PAYMENT_REQUIRED), upstream 4xx/5xx (PLATFORM_ERROR), network timeout (NETWORK_ERROR). |
list_posts |
params_unexplained |
List your published and draft posts on a configured platform (devto, ghost, hashnode, wordpress, medium, substack). FREE. Requires platform credentials. status filters results to draft, published, or all (default all); limit caps how many posts are returned (default 30). Returns: { posts: [{ id, title, status, url, published_at }] }. Common errors: platform not configured (VALIDATION_ERROR), upstream auth failure (PLATFORM_ERROR). |
cross_publish |
params_unexplained |
Publish one article to multiple CMS platforms in a single call. Costs 1 credit total regardless of how many platforms (typical use: 5 platforms). The first successful platform's URL is wired as the canonical for the rest; primary_platform overrides which platform's URL becomes canonical. Requires credentials for every target platform. Optional fields: subtitle (used by Substack), tags, status draft or published (default draft), featured_image_url as the lead cover image, canonical_url for cross-posting, and series on Dev.to and Hashnode. Returns: { results: [{ platform, status: success or error, url?, error? }], canonical_url, summary: { ok, failed } }. Per-platform failures are reported in results without aborting the whole call. Common errors: zero platforms configured (VALIDATION_ERROR), credit exhaustion (PAYMENT_REQUIRED). |
frontmatter |
params_unexplained |
Generate correctly-formatted frontmatter for SSGs and publishing platforms: hugo, jekyll, astro, nextjs, devto, hashnode, ghost. FREE. Auto-extracts description, reading_time, slug, and suggests tags from content; no external calls. author sets the frontmatter author field, draft controls the draft flag (default true), canonical_url sets the canonical URL, featured_image sets the cover image URL, and tags are used when provided instead of auto-extracted ones. Returns: { frontmatter: string, format, extracted: { slug, reading_time_min, description } }. Common errors: unknown format (VALIDATION_ERROR). |
bluesky_search |
params_unexplained |
Search public Bluesky posts by keyword, author, mentions, tag, or language via app.bsky.feed.searchPosts. FREE. Now requires Bluesky auth (handle + app password) because the AppView gates this endpoint. The cursor parameter is an opaque pagination token returned in a prior response; pass it to fetch the next page of posts. Returns: { posts: [{ uri, cid, author, text, created_at, like_count, repost_count }], cursor? }. Common errors: missing credentials (VALIDATION_ERROR), AppView 5xx (PLATFORM_ERROR). |
Selection evidence
10 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
publish |
cross_publish |
high | Both publish markdown to the same CMS platforms and share nearly identical schemas. A task like 'publish this article to Ghost and WordPress' could route to publish (single platform, called repeatedly), while 'publish this article' could plausibly route to cross_publish with one platform since it accepts the same fields. |
bluesky_post |
bluesky_reply |
medium | bluesky_post's description explicitly mentions 'reply-chained thread' and both accept single text or a thread array, so 'reply to that Bluesky post' may be routed to bluesky_post instead of bluesky_reply, which additionally requires parent_uri. |
list_posts |
list_drafts |
medium | 'Show me my drafts' is ambiguous: list_drafts returns local drafts, while list_posts with status=draft returns drafts stored on the CMS platform. Both are FREE listing tools whose descriptions reference drafts, list, and platform. |
bluesky_mentions |
bluesky_search |
medium | 'Find mentions of @handle on Bluesky' is ambiguous: bluesky_search has a dedicated mentions filter for arbitrary handles, while bluesky_mentions lists notifications for the configured account. A vague 'find mentions' task can pick either. |
seo_meta |
seo_schema |
medium | 'Generate SEO tags/markup for this article' is ambiguous because seo_meta produces title/description/Open Graph tags while seo_schema produces JSON-LD structured data; both are 1-credit SEO generators with 'article' in their descriptions. |
generate_social_posts |
linkedin_post |
medium | 'Create/make a LinkedIn post about this article' is ambiguous: generate_social_posts produces the copy (platforms include linkedin) while linkedin_post actually publishes; the 'make a post' phrasing matches both. |
generate_social_posts |
mastodon_post |
medium | Same write-vs-publish ambiguity as LinkedIn: 'draft a Mastodon status for me' could route to generate_social_posts for copy generation, but a task phrased as 'post this to Mastodon' could wrongly hit the copy generator; the shared 'post single' naming blurs the boundary. |
bluesky_post |
x_post |
medium | Both post directly as a single post or reply-chained thread with identical text/thread input shapes, so a generic 'post this thread' or 'post this to social' task without naming the platform is ambiguous between the two. |
mastodon_post |
x_post |
medium | Both are direct 'single status or threaded' posting tools with near-identical descriptions; a task like 'post a status/thread' that omits the platform (Twitter/X vs Mastodon) can route to the wrong one. |
seo_score |
seo_meta |
low | 'Improve/optimize the SEO of my article' could route to seo_score (analyze and report issues) or seo_meta (generate improved title/description/OG tags); both reference content + seo, though the analyze-vs-generate distinction usually disambiguates. |
Compare the field