0.0 / 30
What changed in the harness
Selection accuracy 100→100, token cost up 3%, unconfirmed writes 0%→0%.
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
24.6 / 30
03Economics
18.8 / 20
04Discoverability
9.6 / 20
Highest-impact fix
Estimated gain +30 pointsAdd explicit identity and permission preflight tools
Expose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
Defects and rewrites.
12 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 |
|---|---|---|
whoami |
no_return_description |
Report the server version, current browser/login status (whether a LinkedIn session is active), and the capabilities the server exposes. Returns a status object summarizing these fields. |
health_check |
no_return_description |
Run a deep health check of the LinkedIn session. Returns a report including: cookie login state, a live Voyager probe result confirming the API actually answers (not just that a cookie exists), and today's safety-budget headroom (per-action used/cap/remaining plus pending invites). |
close_session |
no_return_description |
Close the browser context and release resources by killing the Chrome process. Returns confirmation that the session has been closed. |
get_my_profile |
no_return_description |
Retrieve the authenticated user's own LinkedIn profile. Returns the profile data including experience, education, headline, and summary. |
get_profile |
name_restates_behavior no_return_description |
Fetch a LinkedIn member's profile using their public identifier (the vanity slug in the profile URL, e.g. "satyanadella"). Useful for researching a member before connecting. Returns the profile's experience, education, headline, and summary. |
get_feed |
no_return_description |
Return recent posts from your LinkedIn home feed. Returns a list of posts with author and post text. |
get_notifications |
no_return_description |
Return your recent LinkedIn notifications. Returns a list of notifications with headline, time, and read state. |
get_inbox |
no_return_description |
List your recent LinkedIn messaging conversations. Returns a list of conversations with title, last activity, and unread count. |
get_job_details |
no_return_description |
Get full details for a job posting from its numeric id (the digits in /jobs/view/<id> or the jobUrn from search_jobs). Returns the complete job posting details. |
get_pending_invitations |
no_return_description |
List your pending connection invitations, read-only. Returns received (inbound) invitations with the urn/sharedSecret to accept later, and sent (outbound) invitations. |
get_conversation |
no_return_description |
Read the messages in a LinkedIn conversation identified by its URN (obtained from get_inbox). Returns the conversation's message history. |
react_to_post |
params_unexplained |
[ALPHA, write] React to a post. Gated: requires confirm:true. The "reaction" parameter selects the emotion to express (LIKE, PRAISE, EMPATHY, INTEREST, APPRECIATION, or ENTERTAINMENT; defaults to LIKE). Returns a structured status indicating success or failure. |
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 |
|---|---|---|---|
get_company |
get_company_posts |
medium | Both take the same company URL slug; a task like 'see what Microsoft has been sharing on LinkedIn' or 'pull up Google's LinkedIn activity' could select get_company (company info) instead of get_company_posts (posts), since both return content tied to the same slug. |
get_my_profile |
get_profile |
medium | Both are 'profile' getters with high name overlap; a task phrased 'show me my profile/headline/summary' hinges only on the 'my' token, and a terse fetch-profile request could land on get_profile, which requires a username the user never supplied. |
react_to_post |
comment_on_post |
medium | Both are write actions on the same post_urn input; a task like 'engage with this post' or 'respond to/leave feedback on this post' is ambiguous between liking (react_to_post) and commenting (comment_on_post). |
connect_with_person |
send_message |
medium | Both are gated write actions that 'reach out' to someone with an optional message; a task like 'reach out to this person' or 'send a note to this candidate' could pick either a connection request or a direct message. |
get_feed |
get_inbox |
medium | Both return 'recent' content 'of yours' (feed posts vs conversations); a task like 'show me what's new on LinkedIn' or 'check my recent messages/activity' is ambiguous between the two. |
get_feed |
get_notifications |
medium | Both return 'your recent' updates (feed posts vs notifications); 'see what happened on LinkedIn recently' or 'check my latest' could select either, since the descriptions overlap heavily on recency and ownership. |
get_notifications |
get_inbox |
medium | Both list 'your recent' items with read/activity status; a task like 'check my unread items' or 'see what I missed' is ambiguous between notifications and message conversations. |
create_post |
comment_on_post |
low | Both are text-publishing write actions involving posts; a task worded 'post a comment on this' could match create_post by name ('post') instead of comment_on_post, which takes the same text-field shape. |
search_people |
search_companies |
low | Both search by free-text keywords with identical schemas; a generic task like 'search LinkedIn for [keyword]' leaves the entity type unresolved, e.g. a keyword that is plausibly either a company or a people term. |
Compare the field