Nilyo
Server Details
Your own LinkedIn, WhatsApp, Instagram, Telegram, Email and Calendar accounts, usable from any agent
- Status
- Healthy
- Uptime
- 99.5% over 21 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- nilyo-com/nilyo-mcp
- GitHub Stars
- 0
TDQS
Scored across 175 tools
There are heavy overlaps between layered tool families: generic tools (messaging_send_message, message_edit, chat_update, social_react_to_comment) duplicate provider-specific ones (whatsapp_send_message, linkedin_react_to_message, linkedin_react_to_post). Descriptions attempt heavy disambiguation, but with 175 tools and multiple prefixes per resource (chat_, message_, messaging_, linkedin_, social_), an agent still faces unclear boundaries and misselection risk.
Names follow a predictable snake_case verb_noun pattern with clear domain prefixes (linkedin_, whatsapp_, email_, calendar_, webhook_, account_, team_). Minor inconsistency exists where the same domain uses different prefixes (message_ vs messaging_ vs chat_ for chat/message resources, and linkedin_classic_/linkedin_recruiter_/linkedin_sales_navigator_ variants), but the convention is still readable and mostly uniform.
175 tools is an extreme surface far beyond the 50+ threshold for a single MCP server, creating maintenance, selection and reasoning burdens. Even for a multi-provider integration, this count suggests excessive fragmentation (e.g. separate generic and provider-specific duplicates) rather than a well-scoped set.
Coverage is very broad: full CRUD/lifecycle for messaging, social posts/comments, email/Gmail/Outlook/IMAP, calendars, LinkedIn including premium/recruiter/Sales Navigator flows, plus account/billing, webhooks and feedback. Minor gaps remain, such as missing Instagram follow/unfollow and a few provider-specific edit/delete operations, but most workflows have a path.
Available Tools
175 toolsaccount_change_planAccount: Change planADestructiveInspect
Change the user's plan (Personal, Personal Plus, Team) or billing interval. During the trial the choice is free and applies immediately. With an active Stripe subscription the change is prorated immediately on the saved payment method: FIRST call without confirm to get the price and the explanation (and a one-click Stripe confirmation link), show them to the user, and only call again with confirm=true after explicit approval. Use when a second account of a provider needs Personal Plus, when the user wants Team for colleagues, or asks to switch monthly/annual.
| Name | Required | Description | Default |
|---|---|---|---|
| plan | Yes | Target plan: personal (1 account per provider), personal_plus (up to 10 accounts, several per provider allowed) or team (5 isolated users, extra seats available). | |
| confirm | No | Set true ONLY after the user explicitly confirmed the price shown to them. Without it, the tool returns the price, the proration explanation and a Stripe confirmation link instead of changing anything. | |
| interval | No | Billing interval. Annual = 10 monthly payments (2 months free). Defaults to the user's current interval. | |
| organization_name | No | Team name when moving to the Team plan (defaults to 'My team'). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Although annotations already mark destructiveHint: true, the description adds substantial behavioral detail: the free and immediate effect during trial, prorated charging on the saved payment method for active subscriptions, the confirm requirement, and the one-click Stripe confirmation link. This goes far beyond the generic annotation and gives the agent the necessary caution.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loads the core action, and packs conditional behavior, confirmation flow, and use cases into about four sentences. It is slightly longer than strictly necessary but every sentence carries operational information, so no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating billing tool with no output schema, the description covers the essential operational aspects: trial vs. subscription behavior, the confirm gate, plan/interval changes, and typical use cases. It does not explicitly describe the result of the confirm=true call or error conditions (e.g., missing payment method), but it is sufficient for safe invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and each parameter is already well documented, including confirm's behavior and interval's annual discount. The description restates the confirm workflow in narrative form but does not introduce new parameter semantics beyond the schema, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Change the user's plan (Personal, Personal Plus, Team) or billing interval.' It then lists concrete use cases ('Use when a second account of a provider needs Personal Plus...') that distinguish it from sibling tools like account_start_subscription and team_add_seats, even though it does not name them explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool ('Use when a second account of a provider needs Personal Plus, when the user wants Team for colleagues, or asks to switch monthly/annual') and prescribes a two-step invocation sequence (call without confirm, then with confirm after approval). It lacks explicit when-not-to-use guidance or named alternatives, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
account_connectAccount: ConnectAInspect
Get a secure connection (or reconnection) link for one of the user's provider accounts: LinkedIn, WhatsApp, Instagram, Telegram, Google/Gmail, Microsoft/Outlook or generic IMAP email. Use when the user asks to connect/add/reconnect an account, or after a connect_account/reconnect_account result. Pass account_id only to re-authenticate an existing disconnected account (from list_connected_accounts). For WhatsApp and Telegram prefer whatsapp_connect / telegram_connect, which show the QR code directly in the conversation; this tool is the browser fallback. Never ask the user for provider passwords; the link opens the provider's own authentication.
| Name | Required | Description | Default |
|---|---|---|---|
| provider | Yes | Provider to connect. Use 'email' to let the user pick Gmail, Outlook or IMAP; 'imap' for a generic mailbox. | |
| account_id | No | Nilyo connection ID (unipile_account_id from list_connected_accounts) of an EXISTING account to re-authenticate. Omit to connect a new account. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all-false hints, so the description carries the burden, and it adds real behavioral context: the tool returns a provider-owned auth link, requires no user password, and is a browser fallback. It does not detail side effects like link expiry or whether initiating re-auth revokes the old session, but the core behavior and security stance are clearly disclosed. There is no contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence adds a distinct fact: purpose, trigger, re-auth condition, sibling routing, and password prohibition. It is dense but not bloated, and the main purpose is front-loaded before caveats. The length is proportionate to the tool's branching cases.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-param tool with no output schema, the description covers providers, re-authentication, sibling alternatives, and security guidance; the returned 'link' is identified even if its shape/expiry is not. It could note the imap_connect sibling as an alternative, but nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description substantially enriches both params. It maps account_id to the concrete unipile_account_id from list_connected_accounts and explains that omitting it creates a new account, and it clarifies the 'email' vs 'imap' enum distinction. This goes well beyond the schema's property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get a secure connection (or reconnection) link' for listed providers, and explicitly names sibling alternatives (whatsapp_connect, telegram_connect) to differentiate. The provider list and the re-authentication clause make the tool's exact role unmistakable. It clearly distinguishes from siblings rather than merely restating the name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states exactly when to use it ('when the user asks to connect/add/reconnect an account'), when to pass account_id, and when not to use it (prefer whatsapp_connect/telegram_connect for QR in-conversation). It also gives a hard rule: never ask for provider passwords. This is explicit routing with no reliance on inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
account_connection_statusAccount: Connection statusARead-onlyIdempotentInspect
Check an in-conversation WhatsApp/Telegram connection started with whatsapp_connect or telegram_connect. Returns pending (with the current QR code image or pairing code, refreshed when it changed), connected, expired or failed. Poll every 10-20 seconds until the status is connected, then retry the user's original request. Omit intent_id to check the most recent attempt.
| Name | Required | Description | Default |
|---|---|---|---|
| intent_id | No | intent_id returned by whatsapp_connect/telegram_connect. Omit for the latest attempt. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: it returns pending with a QR code or pairing code that refreshes when changed, and it explicitly instructs polling behavior. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: it states the purpose, the return states, the polling cadence, and the parameter behavior in three sentences. Every sentence earns its place with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only status tool with one optional parameter and no output schema, the description covers the essential workflow: what statuses to expect, how to poll, and what to do when connected. It doesn't describe the exact structure of the QR code or pairing code fields, but that is minor given the tool's simplicity and the annotations covering safety.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single parameter, and the description adds meaning by explaining that intent_id is the value returned by whatsapp_connect/telegram_connect and that omitting it checks the latest attempt. This clarifies the parameter's provenance and default behavior beyond the schema's simple description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool checks the status of an in-conversation WhatsApp/Telegram connection initiated by whatsapp_connect or telegram_connect. It names the specific resource (connection status) and the possible return states, distinguishing it from the connect tools and other account tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use this tool: poll every 10-20 seconds until status is connected, then retry the user's original request. It also explains how to handle the optional intent_id parameter, saying to omit it to check the most recent attempt. This is clear operational guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
account_get_subscriptionAccount: Get subscriptionARead-onlyIdempotentInspect
Show the authenticated Nilyo user's login email, plan, trial/subscription status, account limits, team seats and members, plus the available billing actions (subscribe, upgrade, add seats, invite). Use to verify which Nilyo login the agent is connected to, when the user asks about their plan, trial, price, seats, team, why an action is blocked, or before proposing an upgrade. Never exposes payment details.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, so the safety profile is covered. The description adds a genuine data-boundary disclosure — 'Never exposes payment details' — plus the implicit scope that it targets only the authenticated user, which is useful context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with what is returned and followed by when to use it; the field enumeration is long but each item earns its place by telling the agent what it can answer without a follow-up call. Slight density cost from the parenthetical billing-action list.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so by enumerating the returned fields and listing the billing actions surfaced. Combined with the explicit usage triggers and the payment-data exclusion, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline of 4 applies; there is nothing parameter-level for the description to clarify or miss.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Show') and resource (the authenticated Nilyo user's account/subscription state), then enumerates the exact contents: login email, plan, trial/subscription status, limits, seats, members, and billing actions. It reads clearly against adjacent siblings like account_connection_status or list_connected_accounts but never names them, so differentiation is left to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives unusually rich trigger conditions: verifying which login the agent is connected to, user questions about plan/trial/price/seats/team, diagnosing a blocked action, or before proposing an upgrade. It stops short of naming alternative tools or stating when not to use it, which keeps it out of the top band.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
account_list_attentionAccount: List attentionARead-onlyIdempotentInspect
List the user's connected accounts that currently need re-authentication (status disconnected) so the agent can proactively offer to reconnect them before a request fails. Returns an empty list when everything is healthy.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so safety is covered. The description adds useful behavioral context beyond annotations: it filters to disconnected accounts and returns an empty list when healthy, which clarifies the tool's effect and output semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences of purposeful prose. It front-loads the core purpose, then adds the empty-list behavior, with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only tool with rich annotations, the description is complete: it states what is listed, why, and what an empty result means. No schema or output details are needed to select or invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters and schema description coverage is 100%, so the description carries no parameter burden. Per the baseline for zero-parameter tools, this is a solid score; the description also clarifies what the returned list represents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'List the user's connected accounts that currently need re-authentication (status disconnected)'. It clearly distinguishes this from broader account tools like list_connected_accounts and account_connection_status by focusing on the re-authentication need.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use it proactively to offer reconnection before a request fails. It does not explicitly name alternatives or state when not to use it, but the use case is well implied by the 'proactively offer to reconnect' framing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
account_start_subscriptionAccount: Start subscriptionADestructiveInspect
Return Stripe Checkout links (one-click hosted payment, no need to visit the website) to start or restore the paid subscription when the user is on trial, the trial expired or the subscription lapsed. Use after a subscribe result or when the user asks to subscribe/pay/upgrade before having a subscription. If the user already has an active Stripe subscription, use account_change_plan instead. Present monthly and annual options; default to the current plan unless the user chose another one.
| Name | Required | Description | Default |
|---|---|---|---|
| plan | No | Target plan: personal (1 account per provider), personal_plus (up to 10 accounts, several per provider allowed) or team (5 isolated users, extra seats available). | |
| interval | No | Billing interval. Annual = 10 monthly payments (2 months free). Defaults to the user's current interval. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate it's a mutating operation (destructiveHint=true). The description adds value by explaining it returns Stripe checkout links (so the actual payment happens externally), and notes the presentation behavior ('Present monthly and annual options; default to the current plan'). This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact yet informative. Each sentence earns its place: it opens with the core function, then usage conditions, then the alternative, then presentation preferences. No fluff, though it could be slightly tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with an output schema absent, the description explains what it returns (checkout links) and when to use it. It also covers edge cases (trial, expired, lapsed) and defaulting. The only minor omission is a description of the actual response structure, but that's not required given the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% — both 'plan' and 'interval' are fully described in the schema. The description adds some behavior guidance (e.g., 'default to the current plan'), but this is about tool behavior rather than parameter semantics, so it stays at the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb and resource: 'Return Stripe Checkout links ... to start or restore the paid subscription.' It also distinguishes itself from the sibling account_change_plan, making its unique purpose obvious without reading the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use is given: 'Use after a subscribe result or when the user asks to subscribe/pay/upgrade before having a subscription.' It also provides an exclusion: 'If the user already has an active Stripe subscription, use account_change_plan instead.' This is a model of clear routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
agent_capability_guideGuide: Capability guideARead-onlyIdempotentInspect
Return Nilyo's agent workflow recipes and chaining rules. Use when you need to know how to turn a LinkedIn URL/name into a provider user ID, how to find a chat before replying, how to resolve LinkedIn search parameter IDs, or how to combine several account providers.
| Name | Required | Description | Default |
|---|---|---|---|
| workflow | No | Optional workflow name; omit to return all recipes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safe, non-mutating nature is fully covered. The description adds no behavioral detail beyond saying it returns recipes and rules, which is consistent but not extra disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence followed by a focused 'Use when' list. It front-loads the purpose and then gives concrete examples without redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only guide tool with one optional parameter and rich annotations, the description fully covers what the tool returns and when to invoke it. No output schema exists, but the return content (recipes and chaining rules) is described sufficiently for an agent to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the single optional 'workflow' parameter is already clearly documented in the schema as 'Optional workflow name; omit to return all recipes.' The description doesn't need to add more, and it doesn't.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Return') and a specific resource ('Nilyo's agent workflow recipes and chaining rules'), and then enumerates concrete use cases such as resolving LinkedIn URLs to provider user IDs and finding a chat before replying. This clearly distinguishes it from sibling tools like agent_id_guide and general LinkedIn lookup tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use when you need to know how to...' and lists several concrete scenarios, giving an agent clear triggers for invocation. It does not explicitly name alternatives or when not to use it, so it stops short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
agent_id_guideGuide: ID guideARead-onlyIdempotentInspect
Return the authoritative Nilyo ID semantics guide. Use this when unsure whether a tool needs a LinkedIn system user ID, public identifier, request ID, post/comment/chat/message ID, inbox/contract ID, email/thread/folder/attachment ID, calendar/event ID or recruiting/list ID. The guide explains exactly which previous tool produces each ID and which lookalike values must NOT be passed.
| Name | Required | Description | Default |
|---|---|---|---|
| id_type | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds substantive behavioral context beyond this: the guide is 'authoritative', it explains 'exactly which previous tool produces each ID', and it warns that 'lookalike values must NOT be passed'. This tells the agent what kind of content and constraints the tool returns, which is meaningful additional disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The main action ('Return the authoritative Nilyo ID semantics guide') is front-loaded, followed immediately by usage context, and then content scope. Every clause earns its place and the description remains skimmable despite covering many ID categories.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only reference tool with one optional enum parameter and no output schema, the description covers the resource, when to use it, and what it contains. The main missing piece is how the 'id_type' parameter affects the returned content—whether it filters the guide or is required. This is a notable but non-critical gap given the tool's simplicity and the annotations already covering safety and idempotency.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for the lone 'id_type' parameter. It groups the ID types into human-readable categories ('inbox/contract ID', 'email/thread/folder/attachment ID', etc.), which maps helpfully onto the enum values. However, it never explains the parameter's actual behavior—that passing a specific id_type filters the guide and that omitting it returns the full guide. This is a significant gap given zero schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Return the authoritative Nilyo ID semantics guide.' It makes the tool's function immediately clear and enumerates the ID types covered. However, it does not differentiate itself from the sibling tool 'agent_capability_guide', which is also a guide-style tool, so it falls short of a full 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use this when unsure whether a tool needs a LinkedIn system user ID, public identifier, request ID, ...' This is clear contextual guidance. It does not, however, state when NOT to use it (e.g., when the ID type is already certain) or name any alternative tools, so it does not fully meet the 5-level bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_cancel_eventCalendar: Cancel eventADestructiveInspect
Cancel an event organized by the connected account and notify attendees. This differs from deleting an event only from the user's calendar; confirm the exact event before cancellation.
| Name | Required | Description | Default |
|---|---|---|---|
| comment | No | Cancellation message sent to attendees; supported by Outlook only. | |
| event_id | Yes | Exact event ID returned by calendar_list_events or calendar_create_event, paired with its parent calendar_id. Calendar event ID: Exact event id in the selected calendar/account. Obtain with: calendar_list_events -> event.id; calendar_create_event -> created event.id Never pass: event title, date. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the destructive nature is structured. The description adds valuable behavioral context beyond annotations: it notifies attendeescias a side effect, only applies to events organized by the connected account, and warns to confirm before acting. This enriches the safety profile without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The primary action and scope come first, followed by a concise differentiator and a practical caution. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent operation, the description covers the key context: what it cancels, its side effect, how it differs from the delete sibling, and a confirmation warning. With no output schema, it doesn't need to explain returns. The main small gap is that it doesn't mention parameter prerequisites, but those are thoroughly handled in the schema, so overall it is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool description itself does not add parameter semantics, but the input schema covers 100% of the parameters with detailed descriptions (e.g., event_id says how to obtain it and never pass a title/date; calendar_id warns against names). Since the schema already documents param meaning, a baseline of 3 is appropriate—no extra value is needed or provided.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Cancel') with a clear resource ('an event organized by the connected account') and a distinct side effect ('notify attendees'). It also explicitly differentiates from the alternative 'deleting an event only from the user's calendar', which aligns with the sibling calendar_delete_event. This leaves no ambiguity about the tool's function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit when-to-use: cancel events organized by the connected account when attendees should be notified. It also names the alternative scenario ('deleting an event only from the user's calendar') and adds a caution to 'confirm the exact event before cancellation', which guides safe usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_create_calendarCalendar: Create calendarAInspect
Create a calendar in the selected Google or Microsoft account. Use only when the user explicitly asks for a new calendar, not merely an event.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| timezone | No | IANA timezone, for example Europe/Paris. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| description | No | ||
| background_color | No | Hexadecimal calendar color. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a non-read-only, non-idempotent mutation. The description adds the provider scope but does not disclose further behavior such as duplicate handling, immediate visibility, or external side effects. There is no contradiction with annotations, but the description contributes little beyond the obvious creation action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. The core action is front-loaded in the first sentence, and the usage guardrail is in the second. Perfectly sized for the tool's simplicity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a straightforward creation tool with annotations covering the write nature, the description plus the detailed account_id parameter guidance are sufficient to invoke the tool correctly. The only notable omission is any indication of the return value, but no output schema exists, so this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description itself does not expand on individual parameters, but the schema already covers 3 of 5 parameters (timezone, account_id, background_color) with descriptions. The remaining parameters, name and description, are self-explanatory. The account_id parameter description is especially rich, providing operational guidance beyond basic semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Create') and resource ('calendar') with the account scope ('selected Google or Microsoft account'). It explicitly differentiates from the sibling calendar_create_event by adding 'not merely an event,' so an agent can immediately tell which creation tool is appropriate.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear when-to-use condition: 'Use only when the user explicitly asks for a new calendar, not merely an event.' Additionally, the account_id parameter description gives detailed guidance on when to omit versus when to list accounts and ask, preventing incorrect multi-account selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_create_eventCalendar: Create eventAInspect
Create an event in one resolved calendar. Require an explicit title, attendees array, start and end; preserve timezone and all-day semantics instead of guessing them.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| body | No | ||
| start | Yes | ||
| title | Yes | ||
| notify | No | Google-only guest update policy; omit for Microsoft. | |
| location | No | ||
| timezone | No | IANA timezone for the event. | |
| attendees | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| conference | No | ||
| recurrence | No | RFC5545 RRULE, EXRULE, RDATE or EXDATE lines. | |
| visibility | No | ||
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. | |
| transparency | No | ||
| background_color | No | ||
| is_attendees_list_hidden | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds a behavioral guarantee ('preserve timezone and all-day semantics instead of guessing them'), which is useful. Annotations already cover mutability and non-idempotency, so the description adds a bit of extra context but not extensive behavior like side effects or response details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the main purpose, and no wasted words. The required fields and behavioral note are efficiently stated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with 16 parameters and nested objects, the description is sparse. It does not cover optional parameters or return expectations, though the schema has some descriptions and the behavioral note about timezone/all-day helps. Still, an agent may lack guidance on many optional fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Description mentions only required parameters (title, attendees, start, end) and a timezone note, but does not explain the many optional parameters (location, conference, recurrence, visibility, etc.). With schema coverage at 31%, it fails to compensate for the gaps, adding minimal value beyond the schema's own descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Create), resource (event), and scope (one resolved calendar), clearly distinguishing from calendar_create_calendar and calendar_update_event. It also mentions required fields and a behavioral nuance, making the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for creating events; does not explicitly compare with siblings like calendar_update_event or calendar_cancel_event, but the purpose is clear and no exclusions are needed. The 'one resolved calendar' hint suggests it is not for multi-calendar operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_delete_calendarCalendar: Delete calendarADestructiveInspect
Delete one exact calendar. This is destructive: resolve and confirm the calendar before deleting it; never infer calendar_id from its display name.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, and the description reinforces this by stating 'This is destructive'. It adds valuable context beyond annotations by instructing the agent to resolve and confirm the calendar and to never infer the ID, which is a critical behavioral guardrail not expressed in the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero redundancy. The action is front-loaded, and the safety warning follows immediately. Every word earns its place; no filler or vague language.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive delete tool with no output schema, the description adequately covers the key risks (destructive nature, ID resolution) and the required parameter. It doesn't describe return values, but none are expected. The inclusion of the confirmation guidance makes it complete enough for an agent to use it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already explains the calendar_id parameter, including how to obtain it and never pass a display name. The description reiterates the 'never infer' warning but adds no new parameter semantics beyond what the schema provides. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Delete' and the resource 'one exact calendar', which distinguishes it from sibling tools like calendar_delete_event. It also adds the qualifier 'exact' to set precision expectations. This is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not explicitly name alternatives or when-not-to-use, but it provides critical usage guidance: resolve and confirm the calendar before deleting, and never infer the ID from its display name. This gives clear context for safe invocation, even though it doesn't contrast with siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_delete_eventCalendar: Delete eventADestructiveInspect
Delete one resolved calendar event. Confirm the intended event and preserve its parent calendar_id; this removes it only from the connected account's calendar.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Exact event ID returned by calendar_list_events or calendar_create_event, paired with its parent calendar_id. Calendar event ID: Exact event id in the selected calendar/account. Obtain with: calendar_list_events -> event.id; calendar_create_event -> created event.id Never pass: event title, date. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false. The description adds context beyond annotations: deletion is scoped to the connected account's calendarasi and the parent calendar_id must be preserved. This provides useful operational detail without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the action, and every phrase carries weight. It avoids repeating schema content, delivering only the essential behavioral scope and caution in 26 words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive three-parameter tool with no output schema, the description combined with the rich parameter schema and annotations covers all necessary details: the event to delete, the required IDs, and the scope. The account_id parameter is fully explained in the schema. No critical contextual gap exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter is thoroughly documented (event_id must be exact and never a title/date; calendar_id must be exact and never a name; account_id is optional for single-account contexts). The description's mention of preserving calendar_id reinforces the schema but adds minimal new meaning. The baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The title and description clearly state the action ('Delete') and the resource ('resolved calendar event'). The phrase 'removes it only from the connected account's calendar' distinguishes this tool from siblings like calendar_cancel_event or calendar_delete_calendar, clarifying it deletes a specific event instance within a single account.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by specifying 'resolved' event and the scope (only from connected account's calendar), but it never explicitly names alternatives or states when not to use this tool. The caution to 'Confirm the intended event' is a usage note, but no direct comparison to calendar_cancel_event or calendar_restore_event is made.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_get_calendarCalendar: Get calendarARead-onlyIdempotentInspect
Get one calendar by the exact ID returned by calendar_list_calendars. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description only needs to add behavioral nuance. It adds the requirement of an exact ID and the warning not to pass a display name. It does not detail error behavior or return format, but the safety profile is fully covered by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler. The key constraint (exact ID, not display name) is front-loaded, and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only get-by-id operation, the description, schema, and annotations together provide enough to call it correctly. It does not describe the return value, but that is typically inferred for a 'get' operation and the absence of an output schema does not create ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters. The description reinforces the calendar_id semantics (exact ID, obtain via list, never display name) but adds little beyond the schema's own text. This matches the baseline 3 for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Get one calendar') and immediately scopes it to 'the exact ID returned by calendar_list_calendars', which distinguishes it from the listing sibling. It also explicitly warns against passing a display name, preventing misuse.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use the exact ID from calendar_list_calendars, and explicitly forbids passing a calendar display name. It does not name alternative tools or explain when to prefer this over other calendar operations, but the prerequisite and constraint are unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_get_eventCalendar: Get eventARead-onlyIdempotentInspect
Get one event using both its exact parent calendar_id and event_id. Never identify an event only by title or date.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Exact event ID returned by calendar_list_events or calendar_create_event, paired with its parent calendar_id. Calendar event ID: Exact event id in the selected calendar/account. Obtain with: calendar_list_events -> event.id; calendar_create_event -> created event.id Never pass: event title, date. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and a non-destructive operation, so safety is covered. The description adds a useful pairing/identification constraint and warns against title/date lookup, but it does not disclose not-found behavior or any provider-specific response details. This is moderate added value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the core action and required IDs front-loaded, followed by a critical guardrail. There is no filler, repetition, or unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only get-by-ID tool, the description plus the fully documented input schema and safety annotations give an agent everything needed to invoke it correctly. The return value is evident from the name and operation type, and no side effects need disclosure. Not-found behavior would be a nice addition but is not essential for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter description already documents exact ID sources, pairing, and the rule to never pass titles or dates. The tool description's mention of exact parent calendar_id and event_id restates the schema relationship without adding new semantics. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get'), the resource ('one event'), and the required identifying pair (exact parent calendar_id and event_id). This clearly distinguishes the tool from siblings like calendar_list_events and calendar_get_calendar. The negative instruction about not using title or date sharpens the purpose even further.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear when-to-use condition: call this only when both exact calendar_id and event_id are available. It also gives an explicit when-not: never identify an event only by title or date. It does not name sibling tools or point to calendar_list_events/calendar_create_event as ID sources, though that information appears in the schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_list_calendarsCalendar: List calendarsARead-onlyIdempotentInspect
List calendars for the connected Google or Microsoft account. Use the returned calendar.id before listing, creating or updating events; never pass a calendar display name as calendar_id.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | ||
| offset | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful behavioral context about supporting Google/Microsoft accounts and the requirement to use the returned calendar.id rather than a display name, which goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core action is front-loaded, and the critical usage constraint (use calendar.id, not display name) follows immediately. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool, the description covers the essential workflow: list calendars, use the returned id, and pass account context when needed. It does not describe pagination or response shape, but those are partially inferable from the parameter names, and annotations carry the safety-related context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%: account_id is richly documented, but limit, cursor, and offset have no descriptions. The main description reinforces the connection between the tool and account_id but does not explain pagination parameter behavior, leaving those parameter semantics to be inferred from their names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a clear action and resource: 'List calendars for the connected Google or Microsoft account.' It also explains the purpose of the result ('Use the returned calendar.id before listing, creating or updating events'), which differentiates it from sibling calendar tools like calendar_get_calendar or calendar_list_events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives practical routing guidance: obtain a calendar.id from this tool before listing, creating, or updating events, and never pass a display name as calendar_id. It does not name sibling alternatives explicitly, but the 'use before...' pattern clearly positions this tool as the entry point for calendar operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_list_eventsCalendar: List eventsARead-onlyIdempotentInspect
List or search events inside one resolved calendar. Use this to obtain event.id before reading, updating or deleting an event.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ISO 8601 upper time bound. | |
| busy | No | ||
| limit | No | ||
| start | No | ISO 8601 lower time bound. | |
| title | No | ||
| cursor | No | ||
| offset | No | ||
| ical_uid | No | ||
| location | No | ||
| attendees | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| event_type | No | ||
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. | |
| description | No | ||
| is_cancelled | No | ||
| updated_after | No | ||
| updated_before | No | ||
| expand_recurring | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive behavior, so the description does not need to restate safety. It adds useful context about 'one resolved calendar' and the event.id workflow. However, it does not disclose pagination behavior, filtering defaults, or output shape, leaving some behavioral gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no fluff, and the core action is front-loaded. Every phrase earns its place: the verb, the resource scope, and the intended workflow are all present without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 18 parameters and no output schema, the description is far from complete. It gives a clear purpose but leaves search semantics, filter usage, pagination, account disambiguation, and return values unexplained. The low schema coverage makes this a significant gap for an agent trying to use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 22%, and the description adds no parameter-level meaning beyond the purpose. Many parameters such as busy, limit, title, cursor, offset, and event_type are left undocumented. The description does not compensate for the low schema coverage, making it hard for an agent to know which filters to use.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List or search events inside one resolved calendar.' It also clarifies the primary use case: 'obtain event.id before reading, updating or deleting an event,' which clearly distinguishes this tool from event mutation tools and calendar listing tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use this tool: before reading, updating, or deleting an event. It implies the tool is for working within a single resolved calendar, setting a clear prerequisite. It does not name an alternative like calendar_get_event, but the intended workflow is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_restore_eventCalendar: Restore eventAInspect
Restore an event previously cancelled by the connected organizer. Available only for Google Calendar while Google still retains the cancelled event; report the provider error for Outlook without substituting another action.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Exact event ID returned by calendar_list_events or calendar_create_event, paired with its parent calendar_id. Calendar event ID: Exact event id in the selected calendar/account. Obtain with: calendar_list_events -> event.id; calendar_create_event -> created event.id Never pass: event title, date. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate this is not read-only and not idempotent, but the description adds valuable behavioral context: the restore depends on Google's retention of the cancelled event, and Outlook should surface an error rather than be handled with a fallback. This goes beyond the structured annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two compact sentences with no filler. The core action and object are front-loaded, followed by the necessary provider and error-handling constraints, making it easy for an agent to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Together with the fully detailed input schema, the description covers the action, provider availability, a time-based precondition, and failure behavior for an unsupported provider. The absence of an output schema is not a major gap for a simple restore operation, though a bit more detail about the response could push it higher.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already provides detailed semantics for event_id, calendar_id, and account_id, including exact ID requirements and never-pass guidance for titles/names. The description does not add parameter-specific detail, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Restore') and resource ('event previously cancelled by the connected organizer'), which clearly identifies the action and distinguishes it from sibling tools like calendar_cancel_event and calendar_delete_event. The provider scoping ('Google Calendar') further sharpens the intended operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when this tool can be used: only for Google Calendar and only while Google retains the cancelled event. It also gives direct guidance for Outlook by instructing the agent to report the provider error without substituting another action, which prevents misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_rsvp_eventCalendar: Rsvp eventAInspect
Accept, tentatively accept or decline an invitation for the connected account only. Resolve the event first; Outlook organizers cannot RSVP and declining can remove the event from their calendar.
| Name | Required | Description | Default |
|---|---|---|---|
| status | Yes | ||
| comment | No | ||
| event_id | Yes | Exact event ID returned by calendar_list_events or calendar_create_event, paired with its parent calendar_id. Calendar event ID: Exact event id in the selected calendar/account. Obtain with: calendar_list_events -> event.id; calendar_create_event -> created event.id Never pass: event title, date. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description warns that 'declining can remove the event from their calendar,' which directly contradicts the annotation destructiveHint=false. Even though it adds useful caveats about Outlook organizers and account scope, the contradiction undermines the agent's ability to trust either signal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences contain all essential guidance with no filler. The main action is front-loaded, and the important caveat about Outlook organizers follows immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers scope, prerequisites, and provider-specific caveats, which is strong for an RSVP tool. It omits return-value details, but there is no output schema and the mutation semantics are reasonably clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 60% schema coverage, the description adds useful context by mapping the action to status values and emphasizing the connected-account restriction, which relates to account_id. However, it does not explain the comment parameter or add much beyond the existing schema descriptions for event_id and calendar_id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear, specific verb-resource pair: accept, tentatively accept, or decline an invitation. It also immediately scopes the action to 'the connected account only,' which helps distinguish it from other calendar mutation tools like calendar_cancel_event or calendar_update_event.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives actionable usage prerequisites: resolve the event first and avoid using this tool for Outlook organizers. It clearly notes a limitation but does not explicitly name sibling alternatives or contrast with them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_update_calendarCalendar: Update calendarAInspect
Update explicit fields on an existing calendar. Resolve calendar_id first and pass only changes requested by the user.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| timezone | No | IANA timezone, for example Europe/Paris. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. | |
| description | No | ||
| background_color | No | Hexadecimal calendar color. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations providing readOnlyHint=false, destructiveHint=false, and openWorldHint=true, the description adds value by specifying that only 'explicit fields' are updated, implying partial updates and not destructive behavior. It also instructs to 'pass only changes requested by the user,' which is behavioral context not in annotations. No contradictions found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: two sentences, front-loading the core action and key guideline. It avoids redundancy with the schema but also omits some potentially useful info like example updates. However, it is efficient and well-structured for its purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 parameters, mutation, no output schema), the description provides essential context: resolve calendar_id first, pass only changes, and rely on schema for param details. It could mention what fields are updatable or consequences, but the schema covers field details. Missing return info is minor since no output schema exists, but the tool's function is clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67%, meaning most parameters have descriptions, including important guidance on account_id and calendar_id. The description reinforces that calendar_id must be resolved and only changes passed, which adds value beyond the schema. For parameters without descriptions like name and description, the description's general context compensates reasonably.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Update explicit fields on an existing calendar,' which is a specific verb and resource. It clearly indicates this tool is for modifying a calendar, distinguishing it from sibling tools like calendar_create_calendar and calendar_delete_calendar. The description also emphasizes passing only user-requested changes, which adds clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context: resolve calendar_id first and pass only changes requested by the user. It implicitly guides when to use this tool (when updating existing calendars) but does not explicitly state when not to use it or mention alternatives like calendar_update_event. However, the instruction to resolve calendar_id is a strong usage guideline.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendar_update_eventCalendar: Update eventAInspect
Update explicit fields on a resolved event. Keep event_id paired with the parent calendar_id and do not blindly retry after an ambiguous failure.
| Name | Required | Description | Default |
|---|---|---|---|
| end | No | ||
| body | No | ||
| start | No | ||
| title | No | ||
| notify | No | Google-only guest update policy; omit for Microsoft. | |
| event_id | Yes | Exact event ID returned by calendar_list_events or calendar_create_event, paired with its parent calendar_id. Calendar event ID: Exact event id in the selected calendar/account. Obtain with: calendar_list_events -> event.id; calendar_create_event -> created event.id Never pass: event title, date. | |
| location | No | ||
| timezone | No | IANA timezone for the event. | |
| attendees | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| conference | No | ||
| recurrence | No | RFC5545 RRULE, EXRULE, RDATE or EXDATE lines. | |
| visibility | No | ||
| calendar_id | Yes | Exact calendar ID returned by calendar_list_calendars; never pass a calendar name. Calendar ID: Exact Google/Microsoft calendar id. Obtain with: calendar_list -> calendar.id Never pass: calendar display name. | |
| transparency | No | ||
| background_color | No | ||
| is_attendees_list_hidden | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already state non-read-only, non-idempotent, and non-destructive behavior. The description adds value by specifying that only explicit fields are updated (behavioral detail not in annotations) and by warning against retrying after ambiguous failures, which indicates partial-application risk. These traits are beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences: the first states the primary purpose, the second gives two critical operational warnings. It is front-loaded and concise with no filler or redundant information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with 17 parameters, no output schema, and low schema coverage, the description is too sparse. It does not explain return values, how unspecified fields are treated, provider-specific behaviors (only the notify parameter hints at Google-specificity), or account selection steps. The two warnings are helpful but insufficient for complex edge cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 35%, so the description should compensate. However, the only parameter-related guidance (event_id paired with calendar_id) is already present in the schema's event_id description. No additional meaning is provided for the other 15 parameters, such as start, end, attendees, or recurrence.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Update explicit fields on a resolved event' with a specific verb and resource, and the 'resolved' qualifier distinguishes it from creation and other calendar operations. This clearly differentiates it from siblings like calendar_create_event and calendar_update_calendar. The phrase 'explicit fields' also signals a partial update rather than a full overwrite.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage after resolving an event (by mentioning 'resolved event') but does not explicitly contrast with alternatives like calendar_create_event or calendar_cancel_event. It gives operational guidance (pairing event_id with calendar_id, avoiding blind retries) but lacks an explicit when-to-use or when-not-to-use statement, leaving some inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chat_add_participantChat: Add participantAInspect
Add an exact provider user to an exact group chat. Resolve chat_id independently from user_id. For LinkedIn user references, URL/name -> profile resolver -> profile.id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| user_id | Yes | Exact provider user ID returned by the relevant profile/person/contact resolver. Never pass a display name. For LinkedIn actions use the stable system user ID returned as profile.id, not a linkedin.com URL. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, so the safety profile is known. The description adds ID resolution context but does not disclose additional behavioral traits like side effects or rate limits. It does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core action and then provides structured ID resolution guidance. While verbose, the length is justified by the complexity of ID handling; it remains efficient and well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with 3 params (2 required) and no output schema, the description covers all necessary operational details: ID resolution, what to avoid, and provider-specific nuances. The optional account_id is fully explained in the schema, so no gap exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, giving a baseline of 3. The description significantly enhances parameter meaning by detailing how to obtain chat_id and user_id, including LinkedIn-specific resolver chains and explicit exclusions, going beyond the schema's descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the specific verb 'Add' and resource 'exact provider user to an exact group chat', clearly distinguishing it from siblings like chat_remove_participant and chat_list_participants. The emphasis on 'exact' reinforces the precision required.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit instructions on resolving chat_id and user_id, including what never to pass (person name, URL, etc.). It does not explicitly mention when to use this tool over alternatives, but the purpose is unambiguous and the guidance is highly actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chat_deleteChat: DeleteADestructiveInspect
Delete/remove one exact chat where supported. Resolve/verify chat_id first; destructive. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare destructiveHint=true and idempotentHint=false, so the description's 'destructive' label is redundant. However, it adds meaningful context by stating deletion is 'where supported' and instructing the agent to resolve/verify chat_id first, which conveys limited support and a safety precondition beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively concise and front-loaded, leading with the core action and then layering preconditions and identifier guidance. The middle section repeats some schema text, but it serves as a standalone summary. No unnecessary filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool with no output schema, the description covers the most critical invocation details: what to delete, how to obtain the identifier, and what to never pass. However, it does not explain what happens when deletion is unsupported or on error/response behavior, and the account_id selection guidance is only in the schema, leaving a moderate gap for agents dealing with multiple accounts.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description repeats the chat_id semantics already present in the schema and does not add new parameter-specific meaning. The account_id parameter is described only in the schema, not in the main description, but the schema itself covers it thoroughly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Delete/remove one exact chat where supported.' It clearly distinguishes this from sibling tools like message_delete by targeting the chat object, and reinforces the resource type by explaining that a chat_id, not a person name, user_id, or message_id, is required.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: resolve and verify chat_id first, note that this is destructive, and it only works 'where supported.' It also tells the agent exactly what identifiers are unacceptable. It does not explicitly name alternative tools or conditions for choosing a different tool, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chat_list_participantsChat: List participantsARead-onlyIdempotentInspect
List members of an exact group/multi-party chat. Resolve chat_id first. Returned participant user IDs can be reused for membership operations; they are NOT chat IDs. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint, destructiveHint), the description clarifies that returned participant user IDs are NOT chat IDs and can be reused for membership operations. This is valuable output-semantics disclosure that annotations do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose, then gives necessary resolution and output guidance. It is slightly dense and repeats some chat_id text also present in the schema, but every sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only two-parameter tool with no output schema, the description compensates by explaining output ID semantics and how to resolve the required chat_id. It could mention the response shape more explicitly, but the essentials for correct invocation are covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already thoroughly documents chat_id and account_id. The description adds usage emphasis like 'Resolve chat_id first' and 'Never pass...' but does not add substantive parameter semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List members of an exact group/multi-party chat.' It is clearly distinguished from sibling chat operations like adding/removing participants, and the first sentence immediately tells the agent what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives strong usage context: resolve chat_id first, obtain it from conversation listings, and never pass person name/user_id/message_id. It does not explicitly name alternatives, but the prerequisite and ID-type guidance make correct invocation clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chat_remove_participantChat: Remove participantADestructiveInspect
Remove an exact provider user from an exact group chat. Inspect participants first when identity is ambiguous. chat_id and user_id are separate. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| user_id | Yes | Exact provider user ID returned by the relevant profile/person/contact resolver. Never pass a display name. For LinkedIn actions use the stable system user ID returned as profile.id, not a linkedin.com URL. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint: true, so the agent knows this is a mutation. The description adds context about exact matching and the need to inspect participants, which is useful beyond annotations. However, it doesn't elaborate on side effects (e.g., notifications, irreversibility) or error behavior, so it provides only moderate additional transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single focused paragraph that front-loads the purpose and then gives practical warnings. It is not bloated, though it repeats some schema text verbatim, which is slightly redundant but does not hinder readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a straightforward removal operation, the description covers the essential: action, exactness, inspection hint, and ID separation. The sibling chat_list_participants provides the inspection path, and annotations cover the destructive nature. It lacks explicit notes on permanent effects, but that is minor given the simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the parameter descriptions in the schema are already detailed (including the exact same warnings about chat_id and user_id). The tool description largely repeats this content rather than adding new meaning, so it doesn't compensate beyond the baseline for high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise action: 'Remove an exact provider user from an exact group chat.' It clearly distinguishes from siblings like chat_add_participant (add) and chat_list_participants (list). The verb and resource are specific, and the 'exact' qualifiers prevent ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance: 'Inspect participants first when identity is ambiguous' implies using chat_list_participants before removal. Also warns against passing wrong ID types. While it doesn't name sibling tools directly, the usage context is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
chat_updateChat: UpdateBInspect
Update mutable metadata of an exact chat. Resolve chat_id first; do not use person/user ID. Pass only fields explicitly requested. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| label | No | ||
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| pin_status | No | ||
| muted_until | No | ||
| read_status | No | ||
| archive_status | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds useful ID-handling constraints ('Never pass: person name, user_id, message_id'), but it does not explain what happens when fields like pin_status or archive_status change, nor any permission or reversibility details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the purpose and then gives ID guidance in a compact, structured way. Some of the chat_id text duplicates the schema, but overall it is appropriately sized and every sentence is relevant to correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description does not explain the semantics of six of the eight parameters, including the string or boolean forms for muted_until. It covers chat_id acquisition and negative ID constraints well but leaves significant gaps for a mutation tool with many metadata fields.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25%, so the description must compensate for six undocumented parameters. Instead, it repeats the chat_id guidance that already appears in the schema and adds no meaning for name, label, pin_status, muted_until, read_status, or archive_status. An agent gets no help understanding what values those fields expect or represent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Update mutable metadata of an exact chat.' It clearly distinguishes the operation from deletion or participant management, though it does not explicitly name any sibling tool. The purpose is clear enough for an agent to know this is a metadata mutation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives strong ID-resolution guidance: 'Resolve chat_id first; do not use person/user ID' and 'Pass only fields explicitly requested.' It also explains how to obtain the chat ID. However, it does not mention when to use this tool instead of overlapping siblings such as messaging_set_chat_state for chat state changes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_create_draftEmail: Create draftAInspect
Create an email draft without sending. If replying, first read the source email and use the provider-appropriate reply_to_message_id (IMAP may use RFC822 Message-ID).
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | Yes | ||
| bcc | No | ||
| html | No | ||
| subject | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| plain_text | No | ||
| reply_to_message_id | No | Reply reference. Gmail/Outlook normally use provider email ID; IMAP may require RFC822 Message-ID from the read email. Email reply reference: For Gmail/Outlook normally use the provider email id. For generic IMAP, reply_to_message_id may be the RFC822 Message-ID returned in the email data. Obtain with: email_read_message -> inspect id and provider/RFC Message-ID fields Never pass: subject, sender email address. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=false, so it is a non-destructive write. The description adds the reply nuance and the requirement to obtain a reply_to_message_id, which is extra context. However, it does not describe side effects (e.g., that the draft is saved to the account and retrievable later) or any authentication requirements. Given the annotations already indicate mutation, the description adds moderate value but not a full behavioral picture.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The main action ('without sending') is front-loaded, and the reply guidance is provided efficiently. Every word contributes to clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 8 parameters and no output schema. The description covers the core action and the tricky reply scenario, but it does not clarify whether html and plain_text can both be provided, the relationship between them, or how the draft is later sent (e.g., via email_send_draft). It also doesn't mention error conditions or the expectation that drafts are stored. For a draft-creation tool with this many parameters, more guidance would improve completeness, but the description is adequate for basic usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 25% (account_id and reply_to_message_id have descriptions). The tool description adds context specifically for reply_to_message_id (provider-specific formats and how to obtain it), which is valuable. However, it does not explain the common parameters (to, cc, bcc, html, plain_text, subject) beyond what the schema provides. With low coverage, the description could compensate more, but it only partially does.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Create' and the resource 'email draft', and explicitly notes 'without sending', which distinguishes it from email_send_draft and email_send. It also hints at the reply scenario, making the primary purpose unambiguous even without examining sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides specific guidance for the reply case ('If replying, first read the source email...'), which helps when to use this tool with a reply reference. It does not explicitly mention alternatives like email_update_draft or email_send_draft, but the 'without sending' clarification implicitly distinguishes it from send operations. This is useful context though not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_create_folderEmail: Create folderBInspect
Create a mailbox folder/label. parent_id, when supplied, must be an exact existing folder ID resolved from email_list_folders; it is not a parent folder display name.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| parent_id | No | Exact existing parent folder ID. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=false, and destructiveHint=false, so the description does not need to restate these. It adds a useful constraint about parent_id not being a display name, which clarifies parameter behavior. However, it does not disclose potential side effects like duplicate handling or whether the operation is reversible, which would be helpful given it is a mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: one sentence for purpose and one for the critical parent_id constraint. It is front-loaded with the primary action and contains no filler. Every sentence adds value, making it efficient for an agent to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple create operation with 3 parameters, the description is adequate. It explains the purpose and the key constraint on parent_id. However, it does not mention what happens when parent_id is omitted (e.g., creates at root level) or what the return value is (since no output schema exists). These are minor gaps given the tool's simplicity and the schema's coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67% (parent_id and account_id are described). The description adds a redundant clarification about parent_id being an exact ID from email_list_folders, which is already in the schema. It adds no information about the 'name' parameter. Since the schema already covers most parameters, the description adds marginal value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'create' and the resource 'mailbox folder/label', which distinguishes it from sibling tools like email_delete_folder, email_update_folder, and email_list_folders. It is specific enough to avoid confusion with other email actions, though it could be more explicit about creating a new folder vs. other folder operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not mention that this is the tool for creating folders while others are for updating or deleting, nor does it state any prerequisites beyond the parent_id note. The parent_id note hints at needing email_list_folders, but it does not clarify usage context relative to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_delete_draftEmail: Delete draftADestructiveInspect
Discard one exact draft. draft_id comes from draft list/create; destructive.
| Name | Required | Description | Default |
|---|---|---|---|
| draft_id | Yes | Exact draft ID returned by email_list_drafts/email_create_draft; never use subject or email_id as draft_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the description's 'destructive' tag is largely redundant. It does add that the operation affects exactly one draft and that the ID must come from list/create, which helps prevent misuse. It does not mention permanence/irreversibility, but the destructive annotation already signals that risk.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single short sentence that front-loads the core action, then adds the necessary input source and a destructive warning. There is no filler or repetition beyond the intentional emphasis on destructiveness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive tool, the schema and annotations cover parameter semantics and safety, while the description clarifies scope and input provenance. It lacks an explicit note about response/confirmation behavior and does not distinguish from email_trash, but the essentials for correct invocation are present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already documents draft_id as the exact ID from email_list_drafts/email_create_draft with a warning not to use subject or email_id. The account_id schema also provides detailed guidance. The tool description only restates ID provenance and adds no new parameter meaning, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a specific verb and object: 'Discard one exact draft.' This clearly identifies the tool as a single-draft deletion operation. It does not explicitly name sibling tools like email_trash or email_delete_folder, but the scope ('exact draft') plus the title make the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a useful usage cue: the draft_id must come from email_list_drafts or email_create_draft, implying the tool is for drafts that already exist. However, it does not explicitly mention when to prefer this over alternatives such as email_trash, nor does it state exclusions. The destructive warning is a caution, not a usage routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_delete_folderEmail: Delete folderADestructiveInspect
Delete one exact mailbox folder/label. Resolve folder_id first and verify target; destructive. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| folder_id | Yes | Exact provider folder/label ID from email_list_folders/email_resolve_folder. Human folder names are not IDs. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the destructive nature is covered. The description adds operational caution: 'verify target' and the 'exact' match requirement, plus the explicit ID-type warning. It does not disclose downstream effects (e.g., whether messages inside the folder are deleted), but the annotations carry the primary behavioral burden and the description adds useful safety context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences and front-loaded with the core action. The third sentence is long and partly duplicates the schema's folder_id description, but it consolidates the ID-source workflow and the human-name warning into one place. Overall it is dense without being bloated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only 2 params, no output schema, and annotations covering the destructive and read-only profile, the description covers the key prerequisites and the most common failure mode (passing a human folder name). It does not mention account_id, but the schema fully handles that. It also doesn't explain what happens to folder contents, but that is arguably beyond what a delete invocation needs from the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline applies. The description repeats folder_id semantics already in the schema but adds a concise resolution path ('Obtain with: email_list_folders -> folder.id'). It stays silent on account_id, but the schema provides a detailed explanation of when and how to pass it. The description adds marginal value on top of the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource statement: 'Delete one exact mailbox folder/label.' The qualifier 'one exact' and the focus on folder/label clearly distinguish it from sibling tools like email_trash (messages), email_delete_draft, and email_update_folder. It also signals that resolution is a separate concern, differentiating from email_resolve_folder.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear prerequisite workflow: 'Resolve folder_id first and verify target.' It also gives a strong negative constraint: 'Never pass: human folder name such as Inbox when an ID is required.' While it doesn't explicitly name alternative tools or state when not to use this tool, the context of the email_* siblings and the ID-resolution guidance make usage conditions clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_get_attachmentEmail: Get attachmentARead-onlyIdempotentInspect
Retrieve one exact attachment from Gmail, Outlook/Microsoft or IMAP. Required chain: resolve/list email -> email_id -> read email -> attachment.id -> retrieve. Filename is NOT attachment_id. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. Attachment ID: Exact attachment id returned inside a specific email/message. Obtain with: read the parent email/message first -> attachment.id Never pass: filename, URL.
| Name | Required | Description | Default |
|---|---|---|---|
| email_id | Yes | Exact email provider ID from email list/read/resolve tools. Do not pass subject or RFC Message-ID unless a specific reply field explicitly asks for RFC Message-ID. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| attachment_id | Yes | Exact attachment ID from the already-read parent email. Never use filename or URL as attachment_id. Attachment ID: Exact attachment id returned inside a specific email/message. Obtain with: read the parent email/message first -> attachment.id Never pass: filename, URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations already declaring readOnlyHint=true, idempotentHint=true, and destructiveHint=false, the description adds crucial behavioral nuance: it explains that on IMAP (and Exchange over IMAP) the email ID encodes folder+UID and changes when the email is moved or a draft is updated, so the last returned ID must always be used. It also clarifies that filenames are not valid IDs. This is beyond what annotations convey and is essential for correct invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose and repetitive. The same warnings about never passing filename/URL and about IMAP ID changes are duplicated for both email_id and attachment_id. The text is not front-loaded; it mixes critical guidance with redundancy. It could be condensed by half without losing information, and the structure (a single long paragraph) makes it hard to scan quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the required chain, ID stability pitfalls, and sources for both IDs, which is comprehensive for the main flow. However, it does not mention the account_id parameter (though the schema covers it with its own guidance) and does not state what the tool returns (e.g., binary data or a URL). Since there is no output schema, a brief note on return type would make it fully complete. Still, given the tool name and context, the missing info is minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description enriches both key parameters with explicit acquisition instructions: email_id via email_list_messages/email_list_folder_messages or from email_move_or_label/email_update_draft after a change, and attachment_id from reading the parent email first. It also lists what to never pass (filename, URL, subject, RFC Message-ID). This substantially exceeds the schema's bare definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Retrieve'), resource ('attachment'), and scope ('from Gmail, Outlook/Microsoft or IMAP'), and explicitly defines the required chain (resolve/list email -> email_id -> read email -> attachment.id -> retrieve). This clearly distinguishes it from siblings like email_read_message, which fetches the message body, not the attachment. No ambiguity remains.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit step-by-step usage chain and explicitly warns against passing filenames, URLs, or RFC Message-ID, and against reusing stale IMAP IDs after moves/updates. It even names the source tools (email_list_messages, email_list_folder_messages) and the post-change IDs to reuse, leaving no doubt about when and how to call this tool. This exceeds the typical 'when to use' guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_get_draftEmail: Get draftARead-onlyIdempotentInspect
Get one exact draft. draft_id must come from email_list_drafts or email_create_draft; never use subject/email_id.
| Name | Required | Description | Default |
|---|---|---|---|
| draft_id | Yes | Exact draft ID returned by email_list_drafts/email_create_draft; never use subject or email_id as draft_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered. The description adds minimal behavioral context beyond this, such as 'one exact draft' implying a single-resource getter, but no additional side-effect or error behavior is disclosed. Since it does not contradict annotations and adds a small amount of context, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero filler: it states the core purpose first, then the critical constraint. All information is front-loaded and every word earns its place, making it highly scannable for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple getter tool with rich annotations and complete schema coverage, the description is nearly sufficient. It does not explicitly state the return format or error behavior, but the presence of annotations and the tool's straightforward pattern make these gaps minor. An agent can confidently call this tool with the provided ID and account context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents both draft_id and account_id, including the instruction that draft_id must come from email_list_drafts/email_create_draft and the account selection logic. The description repeats the draft_id source constraint but adds no new information beyond the schema, fitting the baseline of 3 when schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Get one exact draft' uses a specific verb and resource, clearly distinguishing it from sibling tools like email_list_drafts (which lists drafts) and email_get_thread (which retrieves a thread). It also adds a precise scoping constraint by stating the draft_id source and excluding subject/email_id, making its unique purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs that draft_id must come from email_list_drafts or email_create_draft and never from subject/email_id, which is a strong usage rule that prevents common misidentification. However, it does not explicitly contrast with alternatives like email_get_thread or email_read_message, though the source constraint implicitly routes the agent to the correct sibling for listing drafts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_get_folderEmail: Get folderARead-onlyIdempotentInspect
Get one exact Gmail/Outlook/IMAP folder. Resolve folder name -> folder.id first. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| folder_id | Yes | Exact provider folder/label ID from email_list_folders/email_resolve_folder. Human folder names are not IDs. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the bar is lower. The description adds the exactness and ID-resolution constraint, but doesn't describe error behavior or return shape, which matters because there is no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loads the core purpose, then gives the resolve-first rule and the 'never pass a human folder name' caution. It has some redundancy with the schema, but every sentence still contributes actionable guidance; the missing punctuation after 'folder.id' is a minor readability flaw.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read operation, the description plus schema and annotations cover the required folder_id format, where to obtain it, and the optional account_id selection rule. There is no output schema, so a brief note on return value or not-found behavior would make it fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the description largely repeats the folder_id schema text ('Exact Gmail label... Obtain with email_list_folders -> folder.id'). It therefore doesn't add meaning beyond what the input schema already provides, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description uses a specific verb ('Get') and a clearly bounded resource ('one exact Gmail/Outlook/IMAP folder'), immediately distinguishing it from listing or resolving folder operations such as email_list_folders and email_resolve_folder.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs the agent to resolve a folder name to an ID first and to obtain that ID via email_list_folders, and it warns never to pass human folder names like 'Inbox'. It doesn't explicitly contrast this tool with the resolve/list siblings, so it stops short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_get_threadEmail: Get threadARead-onlyIdempotentInspect
Retrieve full email thread by exact thread_id. Obtain thread_id from email list/read response; do not substitute subject/email_id. Email thread ID: Exact thread/conversation id returned by the email provider when available. Obtain with: email list/read result -> thread_id Never pass: email_id unless equal according to returned data.
| Name | Required | Description | Default |
|---|---|---|---|
| thread_id | Yes | Exact thread ID returned by the email provider. Do not substitute email_id unless returned data says they are equal. Email thread ID: Exact thread/conversation id returned by the email provider when available. Obtain with: email list/read result -> thread_id Never pass: email_id unless equal according to returned data. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, and the description adds useful context: the requirement for an exact thread_id and the account selection logic. It does not contradict annotations and provides extra behavioral detail beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately concise but contains redundancy (e.g., repeating the thread_id instructions in two places). The main purpose is front-loaded, but the repetitive phrasing could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the description covers the necessary details: how to get thread_id, the optional account_id behavior, and the safety profile from annotations. It is complete enough for an agent to invoke correctly, though it lacks explicit mention of return format.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters. The description repeats the thread_id warning but does not add significant new meaning beyond what the schema provides. It meets the baseline but does not elevate it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Retrieve full email thread by exact thread_id' with a specific verb and resource, and distinguishes from other email tools like email_read_message by focusing on the thread ID. It clearly indicates what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit guidance on obtaining thread_id from list/read responses and warns against substituting subject/email_id. It also gives context for account_id when multiple accounts exist. However, it does not explicitly name alternative tools, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_list_contactsEmail: List contactsARead-onlyIdempotentInspect
List Gmail/Microsoft contacts to resolve a human recipient name to an email address before composing. Generic IMAP normally has no provider contact directory; use mailbox context instead.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | Opaque cursor returned by previous contact listing. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds an important behavioral constraint: availability is provider-dependent, since generic IMAP typically has no contact directory. It doesn't mention return format or pagination, but those are minor given the strong annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero filler. The core verb, resource, and purpose are front-loaded, and the second sentence earns its place by warning about a common misuse case (generic IMAP).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple optional-parameter list tool with no output schema, the description covers the tool's purpose, the key provider limitation, and enough return implication (contact info enabling name-to-address resolution). Pagination mechanics are left to the cursor schema, and the return shape is not spelled out, but those gaps are not critical for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema carries most of the meaning: account_id is richly documented (Nilyo connection ID, unipile_account_id, disambiguation instructions), and cursor is described. The description adds no parameter-specific detail, and the undocumented limit parameter is left to inference, though its intent is fairly clear from the name and bounds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a well-scoped resource ('Gmail/Microsoft contacts'), and an explicit goal ('resolve a human recipient name to an email address before composing'). It distinguishes itself from generic IMAP and from the sibling whatsapp_list_contacts by naming the provider scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when to use the tool (before composing, to map a recipient name to an address) and when not to rely on it ('Generic IMAP normally has no provider contact directory'). It doesn't name a specific sibling tool as the alternative, but 'use mailbox context instead' gives a clear fallback strategy, so it earns just below the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_list_draftsEmail: List draftsARead-onlyIdempotentInspect
List email drafts. Returned draft.id is the draft_id for get/update/send/delete. draft_id is not email_id or subject.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | Opaque pagination cursor returned by previous call. | |
| any_email | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context by explaining the draft.id field's role in subsequent operations and warning that it is not email_id or subject. This enriches the annotation-covered core without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences with no filler. The primary purpose is stated first, followed by the key output-field caveat. It is efficient and front-loaded, though it could have been even more structured by grouping the draft.id clarifications into one sentence. Overall, it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema, so the description should compensate for return-structure details; the draft.id clarification helps but leaves the rest of the return object unspecified. The description also omits any explanation of the limit and any_email parameters, which are left to schema (limit has none) and guesswork. Given the complexity of 4 params and no output schema, the description is adequate but incomplete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50% (limit and any_email lack descriptions). The tool description does not compensate; it mentions no parameters at all. Cursor and account_id are described in the schema, but limit and any_email remain ambiguous. The description's note about draft.id concerns output, not input parameters, so it does not help an agent understand the meaning or usage of any_email or limit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists email drafts with a specific verb and resource. It also adds a crucial distinction: the returned draft.id is the identifier for subsequent get/update/send/delete operations, and clarifies it is not email_id or subject. This distinguishes it from sibling tools like email_list_messages and prevents misuse of the returned ID.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no explicit guidance on when to use this tool over alternatives such as email_list_messages, nor does it state any exclusions or prerequisites. The only implication is that this is for drafts, but it doesn't clarify whether email_list_messages includes drafts or when to prefer one over the other. There is no mention of the account_id requirement for users with multiple accounts (even though the schema describes it, the description doesn't reference it).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_list_folder_messagesEmail: List folder messagesARead-onlyIdempotentInspect
List messages inside one exact folder. Especially for IMAP: list folders -> select folder.id -> list messages -> email.id -> read/action. Dates: after/before are ISO 8601 UTC datetimes (YYYY-MM-DDTHH:MM:SS.sssZ); for "today" use after=start of the user's day. Counting: an empty page is not "zero emails" unless no filter was applied; for totals use folder.total_count/unread_count from email_list_folders instead of listing. IMAP pages are capped at 50 live messages; keep limit small (20) to avoid runtime timeouts. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | ||
| from | No | ||
| after | No | ||
| limit | No | ||
| before | No | ||
| cursor | No | Opaque pagination cursor returned by previous message listing. | |
| any_email | No | ||
| folder_id | Yes | Exact provider folder/label ID from email_list_folders/email_resolve_folder. Human folder names are not IDs. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/idempotentHint annotations, the description reveals key behavioral traits: empty pages do not mean zero emails unless no filter is applied; IMAP pages are capped at 50 live messages; limiting to 20 avoids runtime timeouts; and IMAP email IDs change on move/update, so reuse the latest ID. These are essential for correct usage and go well beyond annotation defaults.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but every sentence provides actionable detail: workflow, date format, counting caveats, pagination limits, and ID handling. It is front-loaded with the core purpose and workflow, then deepens into edge cases. While it could be tightened, the density of useful information justifies its length; nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter tool with no output schema and low schema coverage, the description covers the most critical aspects: workflow, date semantics, counting, pagination limits, folder_id acquisition, and ID mutability. It does not explicitly explain to, from, any_email, or cursor, but those are simpler and likely self-evident or covered by schema descriptions. Overall, it provides sufficient context for an agent to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33%, so the description carries the burden of explaining parameters. It specifies after/before as ISO 8601 UTC datetimes with a 'today' hint, advises a small limit (20) to avoid timeouts, and details how to obtain folder_id (via email_list_folders -> folder.id) and the distinction from human names. It also explains the email provider ID behavior for related tools, adding context that is not in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement of the tool's function: 'List messages inside one exact folder.' It specifies the resource (folder) and the operation (list messages), and provides a concrete workflow (list folders -> select folder.id -> list messages -> email.id -> read/action). This clearly distinguishes it from siblings like email_list_messages (which likely lists across folders) and email_list_folders (which lists folders, not messages).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: for listing messages in a specific folder after obtaining a folder ID via email_list_folders. It also tells when NOT to use it: for totals, use folder.total_count/unread_count from email_list_folders instead. It does not explicitly name email_list_messages as an alternative for cross-folder listings, but the folder-specific workflow implies the distinction. This is clear and practical.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_list_foldersEmail: List foldersARead-onlyIdempotentInspect
List Gmail labels, Outlook folders or IMAP folders. Returned folder.id is required by folder-specific operations. For IMAP this is normally the first step before listing messages. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | Opaque cursor returned by prior folder listing; never invent. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful behavioral context by explaining that the returned folder.id is an exact Gmail label/Outlook/IMAP folder ID and that this listing is a preamble to message listing in IMAP. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentences are efficient, but the tail block ('Mailbox folder/label ID: ...') reads like copy-pasted parameter documentation and is confusingly disconnected from this tool's input schema. It repeats the folder-id concept already stated, so the structure is not as clean as it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with no output schema, the description covers the essential operational facts: what is listed, why the returned IDs matter, and how this fits into IMAP message listing. It does not describe pagination or the full return shape, but the cursor schema and annotations compensate reasonably.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is at 67%, and the schema already documents cursor and account_id well; limit has no description. The description's 'Mailbox folder/label ID' block is more about output semantics than the current tool's parameters, so it adds only marginal value for parameter understanding. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List Gmail labels, Outlook folders or IMAP folders.' It goes beyond a simple label by explaining the output's role ('Returned folder.id is required by folder-specific operations'), which clearly differentiates this list tool from folder mutation or message-listing siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete usage context: 'For IMAP this is normally the first step before listing messages' and warns 'Never pass: human folder name such as Inbox when an ID is required.' However, it does not explicitly name alternatives like email_resolve_folder or email_get_folder, so the when-to-use guidance is strong but not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_list_messagesEmail: List messagesARead-onlyIdempotentInspect
List email messages from the user's connected Gmail, Microsoft/Outlook OR generic IMAP mailbox. This is especially useful for IMAP mailboxes not covered by native agent connectors, and for cross-channel workflows that combine email context with LinkedIn/WhatsApp/Instagram. Use to find email_id before opening a message. For totals use email_list_folders (folder.total_count); IMAP pages are capped at 50 and listed live, keep limit small (20).
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | ISO 8601 UTC datetime; only emails after it (exclusive). | |
| limit | No | ||
| before | No | ISO 8601 UTC datetime; only emails before it (exclusive). | |
| cursor | No | ||
| folder_id | No | Exact folder/label ID returned by email_list_folders/email_resolve_folder. Never pass a human folder name unless the provider returned it as the ID. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint safely. The description adds useful non-obvious behavior: IMAP pages are capped at 50, results are listed live, and the limit should be kept small. This is genuinely helpful context beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively compact and front-loaded with the core purpose. It packs provider scope, use cases, pagination limits, and an alternative into a few sentences. The cross-channel phrasing is slightly verbose, but it still earns its place by explaining when the tool is helpful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only listing tool with no output schema, the description covers the essential decisions: provider scope, when to use, pagination caps, limit advice, and the alternative for totals. It could be more complete by explicitly describing the return shape or cursor-based pagination, but the core agent workflow (find email_id, then open the message) is supported.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67%, and the schema already documents after, before, folder_id, and account_id in detail. The description adds guidance for the limit parameter ('keep limit small (20)') and implies email_id appears in results. However, it does not clarify cursor semantics or add meaning for the undocumented limit/cursor parameters beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear action and resource: 'List email messages from the user's connected Gmail, Microsoft/Outlook OR generic IMAP mailbox.' It also explains that the tool is used to find email_id before opening a message. However, it does not explicitly distinguish itself from the sibling email_list_folder_messages, so an agent may still be unsure which listing tool to choose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete usage context: it is especially useful for IMAP mailboxes not covered by native connectors and for cross-channel workflows. It also directs agents to email_list_folders for totals, which is a helpful alternative. It does not explicitly state when to choose email_list_folder_messages or email_list_drafts instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_mark_readEmail: Mark readAInspect
Mark one exact email read. Resolve human email reference -> email_id first. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP.
| Name | Required | Description | Default |
|---|---|---|---|
| email_id | Yes | Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already state readOnly=false, idempotent=false, and destructive=false. The description adds valuable behavioral context beyond that: IMAP IDs encode folder+UID, change on moves/draft updates, and must always come from the last operation. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded, but the description becomes a dense run-on that repeats the schema text nearly verbatim and lacks clear structure, e.g. 'after a change Never pass'. Bulleted caveats would make it much easier to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple mutation, the description covers the critical resolution workflow, ID acquisition, IMAP ID-staleness, and forbidden input values. Account_id handling is covered in the schema. The only minor gap is no mention of the return shape since there is no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so a baseline of 3 applies. The description adds extra meaning with 'Resolve human email reference -> email_id first' and reinforces what must never be passed, which helps the agent construct the email_id parameter correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Mark one exact email read', a specific verb, resource, and scope. The word 'exact' plus the read state distinguishes it from siblings like email_mark_unread and email_read_message without needing to name them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear workflow: resolve human references to email_id first, obtain IDs from email_list_messages or email_list_folder_messages, and avoid stale IDs on IMAP. It does not explicitly name alternative tools for other read-related intents, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_mark_unreadEmail: Mark unreadAInspect
Mark one exact email unread. Resolve email_id first. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP.
| Name | Required | Description | Default |
|---|---|---|---|
| email_id | Yes | Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a mutation (readOnlyHint=false), but the description adds crucial behavioral context beyond that: IMAP IDs encode folder+UID and change on moves/draft updates, so the caller must always reuse the last-operation ID. It also explicitly forbids passing RFC Message-ID, subject, or pre-move IDs. This is valuable, non-obvious behavioral information.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and a prerequisite, then presents essential ID-resolution rules. It is longer than strictly necessary because it duplicates the schema's parameter text, but every included caveat ('CHANGES when moved', 'Never pass: RFC Message-ID') carries real operational value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple state-change tool with no output schema, this description covers the only genuinely difficult part: how to obtain a valid email_id, under what conditions it goes stale, and which ID forms must never be used. The optional account_id handling is fully specified in the schema. Nothing needed for a correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the property descriptions already fully explain email_id and account_id. The tool description repeats the email_id semantics rather than adding new parameter-level meaning, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action ('Mark one exact email unread') and clearly identifies the resource ('one exact email') and the intended state ('unread'). The word 'exact' and the instruction to 'Resolve email_id first' distinguish this from bulk operations and from the sibling email_mark_read without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly establishes when to use the tool: after resolving an email_id via email_list_messages or email_list_folder_messages, and it warns against using stale or non-provider IDs. It does not explicitly name the alternative email_mark_read or state 'when not to use' conditions, but the workflow context is sufficiently clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_move_or_labelEmail: Move or labelAInspect
Move/label one exact email. The result is the email after the change: on IMAP its id CHANGES (folder+UID), so reuse result.id for any follow-up. Resolve email_id independently, then resolve every human folder name to folder.id. Never put 'Inbox'/'Archive' strings in folders_ids unless the provider actually returned those strings as IDs. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| email_id | Yes | Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. | |
| specifics | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| folders_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate mutation (readOnlyHint=false) and non-idempotence (idempotentHint=false). The description adds critical context: on IMAP the email ID changes after move/update, so the result.id must be reused. It also warns against using stale IDs. This goes beyond annotations and is essential for correct follow-up calls.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized, starting with the core purpose and then diving into necessary caveats and resolution steps. It is front-loaded with the key behavior (ID change) and structured into clear sections. While a bit verbose, the complexity of the tool justifies the length; every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description explains the return value ('the email after the change') and the critical ID mutation. It covers ID resolution for both email and folders, warns about common pitfalls, and clarifies account_id handling. It lacks explicit error conditions or edge cases, but covers the primary use cases and traps. Slightly incomplete for specifics parameter, but overall strong.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50% (email_id and folders_ids have descriptions; specifics and account_id lack them). The description compensates by providing detailed instructions for email_id and folders_ids, including how to obtain and what not to pass. For specifics and account_id, the description offers some guidance (e.g., account_id resolution), but specifics remains underdocumented. Overall, the description adds significant value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Move/label') and resource ('one exact email') with scope. Clearly distinguishes from siblings like email_trash, email_update_draft, and email_send by focusing on moving/labeling. The description also mentions the result is the email after the change, which is unique.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on how to resolve email_id and folder IDs, including specific sources (email_list_messages, email_list_folders) and what to avoid (RFC Message-ID, human folder names). While it doesn't explicitly compare to alternatives like email_trash, it clearly scopes the operation and offers procedural steps. Lacks explicit 'when not to use' but strong on how to use correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_read_messageEmail: Read messageARead-onlyIdempotentInspect
Read a specific email including body/headers from Gmail, Microsoft/Outlook or IMAP. Use after email_list_messages and before a contextual reply or cross-channel decision.
| Name | Required | Description | Default |
|---|---|---|---|
| email_id | Yes | Exact provider email ID returned by an email list/resolve/read result. Never pass the subject or sender. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish the read-only, idempotent, non-destructive profile, and the description's 'Read' is consistent with that. The description adds useful scoping (body/headers, provider support) but does not disclose behavior such as whether fetching marks the email as read, how attachments are handled, or response shape. Since annotations cover the safety profile, this is acceptable but not exemplary.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, with the core action and scope in the first sentence and workflow placement in the second. There is no filler, repetition, or needless detail; each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The schema carries the complex ID caveats and account-selection rule, while the description supplies workflow placement and a high-level return description ('body/headers') in the absence of an output schema. It could be more complete by explicitly excluding attachments or pointing to email_get_attachment/email_get_thread, but the tool remains callable with the information provided.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters have 100% schema description coverage, with the email_id description going into depth about provider IDs, IMAP ID instability, and what not to pass. The prose description adds no extra parameter semantics beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete action ('Read'), the resource ('a specific email'), and the payload scope ('body/headers'), plus supported providers (Gmail, Microsoft/Outlook, IMAP). It is clear enough to be picked over list/resolve tools, but it does not explicitly contrast itself with sibling getters such as email_get_thread or email_get_draft.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence is explicit workflow guidance: 'Use after email_list_messages and before a contextual reply or cross-channel decision.' This tells an agent the appropriate position in a multi-step task. It does not, however, name exclusions or alternative tools like email_get_thread for thread-level reads, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_resolve_folderEmail: Resolve folderARead-onlyIdempotentInspect
List mailbox folders/labels to map human names such as Inbox, Archive, Junk or a custom folder to exact folder_id before moving/labeling or listing folder messages. This is especially important for IMAP. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description is not required to re-state safety. It adds workflow behavior: it lists folders to map names to IDs, notes IMAP importance, and provides a warning. It does not describe edge cases like missing folders or pagination behavior, but for a read-only listing tool with these annotations, the added context is sufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately concise and front-loaded: the first sentence states the core purpose. The subsequent sentences add relevant context (IMAP relevance, ID acquisition via email_list_folders, and the warning). It is a bit dense with mixed instructional fragments, but every sentence contributes meaning and there is no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool with no output schema, the description provides purpose and workflow context, but it leaves ambiguity about the input/output contract. The schema has no parameter for a human folder name, yet the description says 'map human names... to exact folder_id' without clarifying that the tool returns a list for the agent to match. The reference to email_list_folders as the source of folder.id is also somewhat confusing about the relationship between the two tools. More explicit guidance on the response shape and how to use the returned data would improve completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33% (only account_id has a description). The tool description does not mention limit or cursor at all, nor does it add meaning to any parameter beyond the schema. It implies a list operation but does not explain how limit/cursor affect results. With low schema coverage, the description should compensate for undocumented parameters, and it fails to do so.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: listing mailbox folders/labels to map human-readable names to exact folder_id. It identifies the trigger ('before moving/labeling or listing folder messages'), highlights the IMAP relevance, and explicitly warns against passing human names when an ID is required. This distinguishes it from siblings like email_list_folders and email_get_folder by focusing on the resolution workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives context on when to use the tool ('before moving/labeling or listing folder messages') and emphasizes the IMAP case. It also includes a clear exclusion: 'Never pass: human folder name such as Inbox when an ID is required,' and points to email_list_folders as the source of folder.id. It could be more explicit about when not to use this tool (e.g., when an ID is already known), but the guidance is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_resolve_messageEmail: Resolve messageARead-onlyIdempotentInspect
Search/list email candidates so a human reference such as sender, recipient, subject or date can be mapped to exact email_id before read/reply/trash/move/attachment operations. For generic IMAP, if account-wide listing is unavailable, use email_list_folders then email_list_folder_messages instead. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. Email reply reference: For Gmail/Outlook normally use the provider email id. For generic IMAP, reply_to_message_id may be the RFC822 Message-ID returned in the email data. Obtain with: email_read_message -> inspect id and provider/RFC Message-ID fields Never pass: subject, sender email address. Email thread ID: Exact thread/conversation id returned by the email provider when available. Obtain with: email list/read result -> thread_id Never pass: email_id unless equal according to returned data.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | ||
| from | No | ||
| after | No | ||
| limit | No | ||
| before | No | ||
| cursor | No | ||
| any_email | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description discloses critical behavioral traits: IMAP IDs encode folder+UID and change when emails are moved or drafts updated, so the last returned ID must always be reused. It also explains how to obtain correct IDs (via email_list_messages or email_list_folder_messages) and what never to pass (RFC Message-ID, subject, stale ID). This adds significant value over the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured into sections (overview, provider ID, reply reference, thread ID) and front-loads the core purpose. However, it is quite long and somewhat dense, with technical caveats that could be condensed. Every sentence carries relevant information, but the length may reduce scannability for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the 8-parameter schema with no output schema, the description covers many important edge cases: provider differences (Gmail/Outlook vs IMAP), ID stability, and alternative tools. However, it does not describe the return format (e.g., whether output is a list of candidates with id, subject, sender fields), which is needed since there is no output schema. It also leaves parameter semantics for from/to/before/after/limit/cursor unexplained, so completeness is good but not perfect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 13% (only account_id is described), so the description must compensate for the other seven parameters. It mentions 'sender, recipient, subject or date' as human references, but does not explicitly map them to schema properties (from, to, any_email, after, before). It also does not explain limit, cursor, or the meaning of any_email. The description provides no concrete parameter-level semantics, leaving agents to guess.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Search/list email candidates so a human reference such as sender, recipient, subject or date can be mapped to exact email_id before read/reply/trash/move/attachment operations.' This distinguishes it from siblings like email_list_messages or email_read_message by focusing on resolving references to IDs. It also names the specific use case and alternative tool, making it easy for an agent to select correctly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: 'For generic IMAP, if account-wide listing is unavailable, use email_list_folders then email_list_folder_messages instead.' It also gives detailed do/don't instructions for obtaining and passing email provider IDs, reply references, and thread IDs, including warnings about IMAP IDs changing after moves/draft updates. This is strong when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_sendEmail: SendADestructiveInspect
Send or reply to an email from the user's connected Gmail, Microsoft/Outlook or IMAP account. Use reply_to_message_id for a true reply when available. Only send after the user has clearly requested/approved the final recipients and content.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | Yes | ||
| bcc | No | ||
| html | No | ||
| subject | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| plain_text | No | ||
| reply_to_message_id | No | Provider reply reference from the source email. Gmail/Outlook normally use provider email ID; IMAP may require its RFC822 Message-ID. Email reply reference: For Gmail/Outlook normally use the provider email id. For generic IMAP, reply_to_message_id may be the RFC822 Message-ID returned in the email data. Obtain with: email_read_message -> inspect id and provider/RFC Message-ID fields Never pass: subject, sender email address. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation nature is covered. The description adds valuable context: it must only be used with user consent, and it supports multiple providers. It also hints at reply behavior via reply_to_message_id, which is beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. It front-loads the core purpose (send/reply) and then adds the reply hint and consent requirement. Every word earns its place, and the structure is clean.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 8 parameters and no output schema, the description is relatively sparse. It does not explain what happens on success or failure, how to handle multiple connected accounts (though account_id is in schema), or edge cases like invalid recipients. It covers the essential 'when' but lacks depth for a complex operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only 2 of 8 parameters (account_id and reply_to_message_id) have descriptions in the schema, which is 25% coverage. The tool description does not explain common parameters like to, cc, bcc, subject, html, or plain_text. It mentions reply_to_message_id but that is already covered in the schema, so it adds no new meaning. With low schema coverage, the description should compensate, but it does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool sends or replies to an email from a connected Gmail, Outlook, or IMAP account. It distinguishes itself from sibling tools like email_create_draft and email_send_draft by emphasizing direct send/reply, and mentions the reply_to_message_id for true replies, which sets it apart from draft workflows.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context on when to use this tool (to send or reply) and includes a critical safety guideline about only sending after user approval. However, it does not explicitly exclude alternatives like email_create_draft or email_send_draft, so the differentiation is implicit rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_send_draftEmail: Send draftADestructiveInspect
Send one exact existing draft. Resolve draft_id and inspect final recipients/content first when not already explicitly approved; this creates a real external send.
| Name | Required | Description | Default |
|---|---|---|---|
| draft_id | Yes | Exact draft ID returned by email_list_drafts/email_create_draft; never use subject or email_id as draft_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true, but the description adds real-world consequence: 'this creates a real external send.' It also instructs the agent to inspect recipients/content before sending, reinforcing that this action is irreversible and has external impact. This goes beyond the bare annotation and provides valuable behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no wasted words. The core action is front-loaded ('Send one exact existing draft'), followed immediately by the critical safety instruction. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter destructive action with no output schema, the description covers the essential pre-send verification step and discloses the external-send consequence. It doesn't describe return values, but that is less critical for a send action. Overall, the agent has everything needed to invoke the tool safely and correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are already well-documented in the input schema. The tool description itself adds little about parameter semantics; it references draft_id but not account_id. Per the rubric, with high schema coverage the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb and resource: 'Send one exact existing draft.' It clearly differentiates from sibling tools like email_create_draft, email_update_draft, and email_send by emphasizing it sends an already-created, exact draft rather than composing or modifying. No ambiguity remains about the tool's function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a crucial operational condition: 'Resolve draft_id and inspect final recipients/content first when not already explicitly approved.' This tells the agent when it is appropriate to execute the send and what preconditions must be met. It does not explicitly name alternative tools or give a contrast to email_send, but the context and phrasing make the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_trashEmail: TrashBDestructiveInspect
Trash one exact email. Resolve email_id first; destructive mailbox action. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP.
| Name | Required | Description | Default |
|---|---|---|---|
| email_id | Yes | Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo/Unipile for the connected mailbox. On IMAP (and Exchange over IMAP) the ID encodes folder + UID: it CHANGES when the email is moved or a draft is updated; always reuse the id returned by the last operation. Obtain with: email_list_messages or email_list_folder_messages -> email.id; the id returned by email_move_or_label / email_update_draft after a change Never pass: RFC Message-ID unless a tool explicitly documents it, subject, an email_id captured before a move/update on IMAP. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, and the description reinforces that with 'destructive mailbox action.' It adds valuable context about ID instability: the ID changes on move/update, and it must be the latest one. It also warns against passing RFC Message-ID or stale IDs. These are beyond annotations and help avoid misuse.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a long, dense paragraph, especially for email_id, mixing prerequisites, warnings, and ID acquisition steps. It front-loads the core action but then becomes a wall of text without bullets or clear sectioning. While informative, it is not concise or well-structured for quick consumption.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite verbosity, it covers all critical operational details: how to resolve the ID, when it becomes invalid, what to never pass, and how to handle the optional account_id with multiple accounts. With no output schema, it explains the return behavior implicitly via 'destructive action.' An agent can safely invoke it correctly after reading this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the description essentially repeats the same text for email_id and adds a concise account_id explanation. It does not add meaning beyond the schema; it mirrors it. Since the schema already documents the parameters thoroughly, a baseline of 3 is appropriate; no extra semantic value is provided by the description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: 'Trash one exact email.' It also flags it as a 'destructive mailbox action,' which sets expectations. It does not explicitly contrast with sibling tools like email_move_or_label, but the purpose is unambiguous and not a tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. It does not mention that email_move_or_label could be used for moving to trash, or that this is a permanent action, nor does it specify prerequisites beyond resolving the ID. The only context is 'destructive mailbox action,' which implies but does not state selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_update_draftEmail: Update draftBInspect
Update an exact existing draft. On IMAP the updated draft gets a NEW draft.id (returned in the result); use it for email_send_draft. without sending. Resolve/read draft first when preserving recipients/content matters.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | ||
| to | No | ||
| bcc | No | ||
| html | No | ||
| subject | No | ||
| draft_id | Yes | Exact draft ID returned by email_list_drafts/email_create_draft; never use subject or email_id as draft_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| plain_text | No | ||
| reply_to_message_id | No | Reply reference. Gmail/Outlook normally use provider email ID; IMAP may require RFC822 Message-ID from the read email. Email reply reference: For Gmail/Outlook normally use the provider email id. For generic IMAP, reply_to_message_id may be the RFC822 Message-ID returned in the email data. Obtain with: email_read_message -> inspect id and provider/RFC Message-ID fields Never pass: subject, sender email address. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a mutation (readOnlyHint=false) and non-destructive (destructiveHint=false). The description adds valuable behavioral context: on IMAP the draft ID changes and the new ID must be used for email_send_draft, and that reading the draft first is advised to preserve unspecified fields. This goes beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description contains an awkward fragment: 'without sending.' which appears as an incomplete sentence with a double space before it. While the core message is short, the structure is unclear and could confuse an agent. The placement of 'without sending' after the IMAP note seems out of order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 9 parameters, no output schema, and sparse annotations, the description should clarify the update semantics and expected result. It mentions the new draft ID on IMAP but does not describe the return object, how missing fields are handled, or the exact behavior for non-IMAP providers. It also omits guidance on which parameters are typically updated together. The description is incomplete for an agent to confidently call this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%, with only draft_id, account_id, and reply_to_message_id having descriptions. The tool description provides no additional meaning for the remaining six parameters (to, cc, bcc, html, subject, plain_text). It does not clarify whether the update is a full replacement or a merge, nor which fields are optional. The description fails to compensate for the low schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Update' and resource 'exact existing draft', distinguishing it from create/send/delete siblings. The qualifier 'exact existing' implies it targets a specific draft, but it does not explicitly contrast with email_create_draft or email_get_draft. The redundant 'without sending' adds no value but does not mislead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a precondition: 'Resolve/read draft first when preserving recipients/content matters.' This is useful guidance for a partial-update scenario. However, it does not explicitly state when to use this tool versus alternatives like email_create_draft or email_send_draft, nor does it list exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
email_update_folderEmail: Update folderAInspect
Rename/move one existing folder. Resolve folder_id first; parent_id is also an exact folder ID when supplied. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| folder_id | Yes | Exact provider folder/label ID from email_list_folders/email_resolve_folder. Human folder names are not IDs. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. | |
| parent_id | No | Exact parent folder ID from folder listing. Mailbox folder/label ID: Exact Gmail label, Outlook folder or IMAP folder id. Obtain with: email_list_folders -> folder.id Never pass: human folder name such as Inbox when an ID is required. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, so the mutation profile is known. The description adds that it renames/moves an existing folder and that parent_id is an exact folder ID, but doesn't disclose side effects like whether moving changes child folders or whether renaming affects labels. It doesn't contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core action. The repeated ID guidance is somewhat redundant with the schema descriptions, but it's placed efficiently and the critical warning is clear. It earns its place by emphasizing the ID requirement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no output schema, the description covers the key prerequisites (resolve folder_id, use exact IDs) and the main parameters. It doesn't explain return values or side effects, but the annotations cover the safety profile and the schema covers parameters. The main gap is lack of detail on what happens when moving a folder (e.g., does it affect children), but this is a minor gap for a simple rename/move operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 75%, so the schema already documents folder_id, parent_id, and account_id in detail. The description adds the workflow hint 'Resolve folder_id first' and the 'Never pass human folder name' warning, which reinforces the schema. The name parameter is not described in the schema, but its meaning is obvious from the tool name and description. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Rename/move one existing folder.' It clearly distinguishes from email_create_folder and email_delete_folder. However, it doesn't explicitly contrast with email_move_or_label, which is a sibling that also moves/labels messages, though the folder-specific scope is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'Resolve folder_id first' and 'Obtain with: email_list_folders -> folder.id'. It also provides a clear exclusion: 'Never pass: human folder name such as Inbox when an ID is required.' This tells the agent exactly how to prepare inputs and what not to do.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
feedback_report_bugFeedback: Report bugAInspect
Report a bug to the Nilyo team as a tracked issue. Use after a tool failed unexpectedly (TOOL_FAILED, wrong or empty result, broken flow) and the user agrees to report it; also when the user says 'ça ne marche pas' / 'report this'. Include the exact error code and details from the failing result so engineers can reproduce. Never include credentials, message bodies or third-party personal data. Ask the user for consent first (user_consent=true).
| Name | Required | Description | Default |
|---|---|---|---|
| tool | No | Nilyo tool name involved, if any. | |
| steps | No | Minimal steps to reproduce: which tools/arguments in which order (IDs can be included). | |
| title | Yes | Short, specific title in English (what fails or what is wanted), e.g. 'email_list_messages fails on OVH IMAP mailbox with 501'. | |
| actual | No | ||
| expected | No | ||
| provider | No | Provider involved when relevant: linkedin, whatsapp, instagram, telegram, gmail, outlook, imap, calendar. | |
| severity | No | high = user blocked with no workaround; medium = wrong behaviour with a workaround; low = cosmetic. | |
| error_code | No | Error code returned by Nilyo, e.g. TOOL_FAILED, PROVIDER_VALIDATION_ERROR. | |
| description | Yes | What the user was trying to do, in their words plus your observations. No passwords, tokens, message contents or third-party personal data. | |
| user_consent | Yes | Must be true: the user explicitly agreed to send this report to the Nilyo team. | |
| error_details | No | The 'Details:' text of the failing result, verbatim. | |
| sentry_event_id | No | error.sentry_event_id from the failing result, when present. | |
| suspected_layer | No | Where you think the bug is: 'nilyo' (tool logic, resolution, errors, billing, connection flow) or 'unipile_api' (the provider connection layer returned an error like UNIPILE_5xx/provider/…). 'unknown' lets the server infer it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are mostly negative hints and do not describe side effects, consent, or data-handling expectations, so the description carries the burden. It discloses that the tool creates a tracked issue, requires user_consent=true, should include exact error codes/details for reproduction, and must never include credentials, message bodies, or third-party personal data. This is meaningful behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four dense sentences with no filler. It front-loads the purpose, then gives trigger conditions, then data requirements. Every sentence contributes to correct invocation or safe execution.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 13 parameters and no output schema, the description covers the essentials: when to invoke, consent requirements, what evidence to include, and what to exclude. It does not mention how to classify severity or suspected_layer, but those are covered by enum descriptions in the schema and are not critical to deciding whether to call the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 85%, so the baseline is 3. The description adds value by reinforcing how error_code and error_details should be used ('exact error code and details from the failing result') and by imposing privacy constraints across free-text parameters. It does not elaborate on the two undocumented parameters (actual/expected), but the schema handles most parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and object: 'Report a bug to the Nilyo team as a tracked issue.' It also gives clear triggering conditions ('after a tool failed unexpectedly', TOOL_FAILED, wrong or empty result, broken flow), which helps distinguish it from feature-request or general feedback tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description is explicit about when to use it: after unexpected tool failure, when the user agrees, and when the user says 'ça ne marche pas' or 'report this'. It does not explicitly contrast with the sibling feedback_request_feature, but the bug-specific framing makes the intended context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
feedback_request_featureFeedback: Request featureAInspect
Send a feature request or improvement idea to the Nilyo team as a tracked issue: a missing action, provider or capability, a workflow that needs too many steps, a confusing result. Use when the user asks for something Nilyo cannot do yet, or explicitly wants to suggest an improvement, and agrees to send it. Describe the user's goal and why current tools fall short. Ask the user for consent first (user_consent=true).
| Name | Required | Description | Default |
|---|---|---|---|
| tool | No | Nilyo tool name involved, if any. | |
| title | Yes | Short, specific title in English (what fails or what is wanted), e.g. 'email_list_messages fails on OVH IMAP mailbox with 501'. | |
| provider | No | Provider involved when relevant: linkedin, whatsapp, instagram, telegram, gmail, outlook, imap, calendar. | |
| use_case | No | Concrete scenario the user wanted to achieve and how often it happens. | |
| workaround | No | What the user does today instead, if anything. | |
| description | Yes | What the user was trying to do, in their words plus your observations. No passwords, tokens, message contents or third-party personal data. | |
| user_consent | Yes | Must be true: the user explicitly agreed to send this report to the Nilyo team. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that this sends a tracked issue to the Nilyo team and requires explicit user consent, which is useful behavioral context beyond the annotations. However, it does not explain what happens after submission, whether anything is reversible, or the lack of immediate resolution, so the behavioral picture is partial.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three focused sentences front-load the core purpose, then the trigger conditions and consent requirement, with no filler or repetition. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, the description covers purpose, trigger conditions, content expectations, and consent. The main gap is the lack of explicit guidance distinguishing this from the bug-reporting sibling and any description of the outcome after submission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the structured schema already documents all seven parameters in detail. The description adds general guidance about capturing the user's goal and why current tools fall short, but it does not add parameter-level meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool sends a feature request or improvement idea to the Nilyo team as a tracked issue, with concrete examples of what qualifies. It is specific about the resource and action, but it does not explicitly contrast this with the sibling feedback_report_bug tool, so differentiation is implied rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use conditions: when the user asks for something Nilyo cannot do yet or explicitly wants to suggest an improvement, plus the consent requirement. It does not state when-not-to-use it or mention the alternative bug-reporting sibling, so it falls just short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
imap_connectIMAP: ConnectAInspect
Connect a generic IMAP/SMTP mailbox directly from the conversation with the mailbox credentials (alternative to the account_connect browser link, which is preferred when the user does not want to type a password in the chat). Nilyo forwards the credentials once to the connection service and never stores them. Start with user + password only (servers are auto-detected); if the result says the IMAP or SMTP configuration is invalid, ask the user for the servers (e.g. OVH: imap ssl0.ovh.net:993 ssl, smtp ssl0.ovh.net:465 ssl; Gmail/Microsoft mailboxes should use the Google/Outlook connection instead). Use account_id to re-authenticate an existing disconnected IMAP account.
| Name | Required | Description | Default |
|---|---|---|---|
| user | Yes | Mailbox login, usually the full email address. | |
| password | Yes | Mailbox password or app password, exactly as given by the user. | |
| imap_host | No | ||
| imap_port | No | ||
| smtp_host | No | ||
| smtp_port | No | ||
| account_id | No | Nilyo connection ID (unipile_account_id from list_connected_accounts) of an EXISTING account to re-authenticate. Omit to connect a new account. | |
| initial_sync | No | Enable the initial mailbox synchronization so account-wide listing/search (email_list_messages, email_resolve_message) works; without it, use email_list_folders + email_list_folder_messages. Default false (faster connection). | |
| imap_encryption | No | ||
| smtp_encryption | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all false (not read-only, not idempotent, not destructive), so the description must carry behavioral disclosure. It states that credentials are forwarded once and never stored, which is a security transparency. It also discloses the auto-detection behavior, the failure handling (ask for servers), and the re-authentication use case. This goes beyond the annotations and gives the agent a clear picture of side effects and expectations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence adds value: purpose, alternative, security note, step-by-step guidance, and special cases. It is well-structured with clear flow, and the key information (user+password first) is front-loaded. No fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (10 parameters, no output schema, no annotations), the description covers many aspects: purpose, alternative, security, usage flow, and re-auth. However, it does not describe the success return value or what the agent should expect after a successful connection (e.g., connection ID or status). It implies a result by mentioning 'if the result says invalid', but doesn't explain the successful outcome. This is a minor gap for a tool with no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40%, so the description must compensate. It does clarify that user+password are the primary required fields and that servers are auto-detected, implying host/port are optional. It provides example server settings for OVH and mentions account_id for re-auth. However, it does not explain imap_encryption, smtp_encryption, or other parameters, leaving their semantics unclear. It partially compensates but not fully.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: connecting a generic IMAP/SMTP mailbox with credentials. It distinguishes itself from the account_connect browser link as an alternative, and specifies it is for generic mailboxes, not Gmail/Outlook. The verb 'connect' and resource 'mailbox' are explicit, and it is differentiated from sibling connect tools like telegram_connect and whatsapp_connect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: it is the alternative to account_connect when the user prefers typing credentials in chat. It also gives an exclusion: Gmail/Microsoft mailboxes should use Google/Outlook connection instead. It further instructs to start with user+password only and to ask for servers if configuration is invalid, plus how to re-authenticate via account_id. This is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_get_my_profileInstagram: Get my profileARead-onlyIdempotentInspect
Get the profile of the owner of the connected Instagram account.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, so the safety profile is covered. The description adds no behavioral details beyond the purpose (e.g., no mention of return shape or authentication requirements), but it doesn't contradict annotations either. It provides minimal additional context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single concise sentence that precisely captures the tool's function. There is no wasted text, and the key qualifier ('owner of the connected Instagram account') is front-loaded, making it immediately clear what this tool does.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only getter with an optional parameter fully documented in the schema, the description is adequately complete. It doesn't specify the return format (e.g., current profile fields), but that is often implied for a 'get profile' tool, and the annotations cover safety. Slight improvement could be mentioning that it returns the profile data, but not essential.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not mention the account_id parameter, but the schema has 100% coverage and a detailed description explaining when to provide it and how to handle multi-account cases. Since the schema already carries that burden, the description doesn't need to add more.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get') and a precise resource ('the profile of the owner of the connected Instagram account'), which clearly distinguishes it from sibling instagram_get_profile. The phrasing 'owner of the connected Instagram account' signals this is the authenticated user's own profile, not an arbitrary profile lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage by stating 'owner of the connected Instagram account' – this suggests the tool is for retrieving the connected account's own profile, but it doesn't explicitly contrast with instagram_get_profile (which presumably fetches other profiles) or provide when/when-not advice. The guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_get_profileInstagram: Get profileARead-onlyIdempotentInspect
Get an Instagram user profile by provider user ID/username where supported. Use before follow/unfollow or identity-sensitive actions.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Exact provider user ID returned by the relevant profile/contact resolver; never a display name or profile URL. For LinkedIn, use the stable system ID. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds the 'where supported' caveat and the intended pre-action usage, which adds minimal but relevant context. It does not disclose error behavior or rate limits, but given the annotation coverage, a mid-range score is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exactly two sentences with zero fluff. The purpose is front-loaded, and the usage note follows directly. It is appropriately sized for a simple read operation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read tool with no output schema, the description and schema together provide sufficient information: how to call it, what input to provide, and when to use it. Missing details like return format or error handling are not critical for a read-only, idempotent operation, so it is complete enough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: both parameters have detailed descriptions, including the user_id guidance (exact provider ID, never display name/URL) and account_id disambiguation logic. The tool description itself does not add parameter-specific details, but since the schema already carries the full burden, the baseline of 3 is warranted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Get an Instagram user profile') and the target resource (Instagram user), and specifies the input type ('provider user ID/username'). It also adds a usage context ('Use before follow/unfollow or identity-sensitive actions') that distinguishes it from the sibling instagram_get_my_profile and list tools. The verb-resource pair is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: before follow/unfollow or identity-sensitive actions. It implies the need for a provider user ID rather than a display name, which is reinforced by the schema description. However, it does not explicitly name alternatives (e.g., instagram_get_my_profile for own profile), though the sibling tool names make that differentiation obvious.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_list_conversationsInstagram: List conversationsARead-onlyIdempotentInspect
List Instagram DM conversations from the user's own account. Use to locate a chat before reading/replying.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive behavior, so the safety profile is covered. The description adds the 'from the user's own account' scoping detail, which is useful, but it does not disclose pagination, ordering, or response format beyond that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The action and scope are front-loaded, and the second sentence earns its place by stating the intended use case.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple optional-parameter list operation with strong safety annotations, the description provides enough to call it correctly: what is listed, in which account context, and for what purpose. It does not describe output shape or pagination, but no output schema exists and 'locate a chat' implies the returned identifiers are sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%, with account_id fully described and limit only having type/bounds. The description does not add parameter-level detail, though 'limit' is fairly self-explanatory. This lands at the baseline since the schema carries most of the meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List Instagram DM conversations from the user's own account.' The added phrase 'Use to locate a chat before reading/replying' clearly separates this from read, send, and profile tools in the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when to use this tool: 'Use to locate a chat before reading/replying.' It does not name alternative tools or give a when-not-to-use condition, but the intended workflow context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_list_followersInstagram: List followersCRead-onlyIdempotentInspect
List followers of the connected Instagram account or a known Instagram user where supported.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | ||
| offset | No | ||
| user_id | Yes | Use 'me' for the connected account owner, otherwise the exact provider user ID returned by a profile/contact resolver; never a display name or profile URL. | me |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, establishing a safe read operation. The description adds a small behavioral caveat with 'where supported', implying that some user queries may not be supported, but it does not disclose pagination behavior, rate limits, or what happens with large follower lists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no redundant words and is front-loaded with the verb and resource. It is appropriately concise, though it is brief enough to omit useful context about pagination or parameter usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a list tool with five parameters and no output schema, the description is too sparse. It does not explain pagination via cursor/offset/limit, what data is returned, or how to handle the 'where supported' limitation. The read-only annotations cover safety, but not the mechanics of using the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40% (user_id and account_id have descriptions), while limit, cursor, and offset lack descriptions. The tool description adds no parameter meaning and does not compensate for the low coverage, leaving the agent without guidance on how pagination parameters work or how they relate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List followers' of the connected account or a known Instagram user. It implicitly distinguishes from the sibling instagram_list_following by the resource type (followers vs. following), though it does not explicitly name that alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to use this tool versus alternatives like instagram_list_following or linkedin_list_followers. It also does not clarify when to use the connected account vs. a known user beyond the phrase 'where supported', which is vague. No exclusions or prerequisites are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_list_followingInstagram: List followingBRead-onlyIdempotentInspect
List Instagram accounts followed by the connected account/user where supported.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | ||
| offset | No | ||
| user_id | Yes | Use 'me' for the connected account owner, otherwise the exact provider user ID returned by a profile/contact resolver; never a display name or profile URL. | me |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds the 'where supported' caveat, which is useful behavioral context, but it does not disclose pagination behavior, rate limits, or what happens when following data is unavailable. Overall, the description adds some value beyond annotations but not substantial detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence delivers the core purpose with no filler. The key scoping detail, 'connected account/user where supported,' is front-loaded and directly actionable. This is an example of appropriate minimalism rather than under-specification.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list with annotations covering safety, the description is mostly adequate. However, with multiple pagination parameters (limit, cursor, offset) and no output schema, the agent lacks guidance on how results are returned or how to paginate. The 'where supported' caveat helps, but the absence of pagination and result-format context leaves a meaningful gap for a tool that can potentially return large lists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40%, and the tool description does not compensate for the undocumented parameters. It mentions the connected account/user, which relates to user_id, but it gives no explanation of limit, cursor, or offset, leaving the agent to infer pagination mechanics. The description adds little meaning beyond what the schema already provides for the two documented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'List Instagram accounts followed by the connected account/user.' It clearly distinguishes from the sibling instagram_list_followers by stating it lists 'following' rather than followers. The phrase 'where supported' adds an appropriate scoping caveat without obscuring the primary action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives no guidance on when to choose this tool over alternatives such as instagram_list_followers or instagram_list_conversations. 'Where supported' hints at a platform limitation but does not explain when this tool should or should not be used, nor does it mention any prerequisites or fallback options.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_read_conversationInstagram: Read conversationARead-onlyIdempotentInspect
Read an Instagram DM conversation and recent messages for context, lead qualification or follow-up workflows.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID returned by conversation/inbox listing. Never pass a person name or provider user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare the tool is read-only, idempotent, and non-destructive, so the description's 'Read' adds no contradiction. It does add the behavioral hint that only 'recent messages' are returned, which is useful, but it does not clarify what 'recent' means, pagination behavior, or other response characteristics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no redundant words. Every part contributes to understanding the tool's purpose and typical use cases.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with only two parameters and rich schema descriptions, the description is largely complete. The only minor gap is the lack of detail about the shape or contents of the returned data, but annotations and the tool name cover the core behavior adequately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with detailed guidance for both chat_id and account_id. The description itself adds no parameter-level meaning, so the baseline score of 3 applies: the schema carries the parameter semantics and the description does not need to compensate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Read'), a specific resource ('an Instagram DM conversation and recent messages'), and an explicit purpose ('context, lead qualification or follow-up workflows'). This clearly distinguishes it from sibling tools like instagram_list_conversations or instagram_send_message.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when the tool is useful (for context, lead qualification, or follow-up workflows) but does not explicitly state when to use this tool versus alternatives such as instagram_list_conversations, messaging_list_messages, or linkedin_read_conversation. Usage context is present but no exclusions or alternative guidance is offered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_send_messageInstagram: Send messageADestructiveInspect
Send an Instagram DM in an existing conversation from the user's own account. Locate chat_id first if necessary and only send after clear user approval.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| chat_id | Yes | Exact chat/conversation ID returned by conversation/inbox listing. Never pass a person name or provider user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as a destructive, non-idempotent write. The description adds a meaningful guardrail: 'only send after clear user approval,' and clarifies that the send happens from the user's own account. It does not detail other side effects, but annotations plus the approval note cover the main behavioral risk.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core action and the required preliminary step. No filler or repetition; every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a send operation with existing annotations and a detailed schema, the description covers the key prerequisites: existing conversation, chat_id lookup, user approval, and account ownership. It could add failure or duplicate-send guidance, but the information needed to invoke correctly is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents chat_id and account_id thoroughly; the description only reiterates locating chat_id first. The text parameter lacks a schema description, but its name is self-explanatory. At 67% schema coverage, the description adds no real parameter meaning beyond what the schema provides, so a mid score is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action verb and resource: 'Send an Instagram DM in an existing conversation from the user's own account.' This distinguishes it from sibling send tools for WhatsApp/LinkedIn and from Instagram read/list tools. 'Existing conversation' and 'own account' add scoping that prevents misuse.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context: requires an existing conversation, locate chat_id first if needed, and only send after explicit user approval. It stops short of naming alternative tools or stating when not to use it, but the Instagram-specific scope and approval requirement provide enough operational guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_update_my_profileInstagram: Update my profileBInspect
Update supported fields on the user's own Instagram profile. Only pass fields explicitly requested; availability is provider-dependent.
| Name | Required | Description | Default |
|---|---|---|---|
| bio | No | ||
| picture | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true). The description adds real context with 'availability is provider-dependent,' implying some fields may silently fail, but it omits anything about idempotency or what a partial update does.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and followed by the operative constraint. Zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an update tool with a nested object parameter and no output schema, the description gives only partial coverage — it flags provider-dependence but leaves field-level semantics and the picture payload unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33% (only account_id is documented), so the description is expected to compensate, but it doesn't enumerate bio or picture nor explain the nested picture object (content/content_type/filename). 'Supported fields' leaves the agent guessing at the two most important parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Update) and resource (the user's own Instagram profile), implicitly distinguishing it from the read siblings instagram_get_my_profile / instagram_get_profile. The 'supported fields' framing is slightly vague about which fields, but the core purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Adds a useful constraint ('Only pass fields explicitly requested') but no when-to-use vs alternatives routing and no prerequisites. With no true sibling doing the same write, usage is only implied rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_accept_invitationLinkedIn: Accept invitationADestructiveInspect
Accept a received LinkedIn connection request. Requires request_id from linkedin_list_invitations(type='received').
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| request_id | Yes | Exact pending invitation request ID returned by linkedin_list_invitations. Never pass the other person's user ID. Relation request ID: ID of a pending sent/received invitation request. Obtain with: linkedin_list_invitations(type=received|sent) -> request.id Never pass: LinkedIn user ID, profile URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=false and destructiveHint=true, so the mutation/destructive nature is covered. The description adds the useful constraint that only pending received requests should be accepted, but does not disclose further behavioral details such as irreversibility or effects on the connection state. This is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence states the action first and the prerequisite second, with no filler. Every word earns its place, making it easy for an agent to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter tool with rich schema descriptions and annotations covering destructive behavior, the description provides enough context to call the tool correctly. No output schema exists, but the operation is straightforward and return format is not critical for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and both parameters already have detailed schema descriptions, especially request_id with explicit instructions on what to pass and what never to pass. The description repeats the source instruction for request_id without adding significant new meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Accept') and a specific resource ('received LinkedIn connection request'). It also names the exact source of the required ID, linkedin_list_invitations(type='received'), which clearly distinguishes this from sibling tools like linkedin_cancel_or_refuse_invitation or linkedin_send_invitation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs the agent to obtain the request_id from linkedin_list_invitations(type='received'), giving a clear precondition and data source. It does not explicitly name alternatives or say when not to use this tool, but the context makes the intended use unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_cancel_or_refuse_invitationLinkedIn: Cancel or refuse invitationADestructiveInspect
Withdraw a sent LinkedIn invitation or refuse a received invitation. First list the relevant invitations to obtain request_id unless it is already known.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| request_id | Yes | Exact pending invitation request ID returned by linkedin_list_invitations. Never pass the other person's user ID. Relation request ID: ID of a pending sent/received invitation request. Obtain with: linkedin_list_invitations(type=received|sent) -> request.id Never pass: LinkedIn user ID, profile URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, which covers the mutation and irreversibility. The description adds the specific action types (withdraw/refuse) and the prerequisite for the request_id. However, it doesn't mention potential side effects (e.g., notification to the other party) or that the action is irreversible beyond what annotations imply. With annotations carrying the safety profile, the description adds some but not rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no redundancy. The purpose is stated first, followed by the key prerequisite. Every word earns its place, and the structure is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, but the description need not explain return values. It covers the two operations and the required parameter acquisition. It omits any guidance on account_id handling, but that is already detailed in the schema. For a two-parameter mutation tool with clear annotations, the description is sufficiently complete for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds a valuable instruction for obtaining request_id via linkedin_list_invitations, which is not fully explicit in the schema's parameter description (though schema does mention 'Obtain with: linkedin_list_invitations'). This actionable guidance improves the semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verbs ('Withdraw', 'refuse') with a clear resource ('sent LinkedIn invitation', 'received invitation'). It distinguishes between the two operations and implicitly differentiates from siblings like linkedin_accept_invitation and linkedin_send_invitation. The phrase 'First list the relevant invitations' also clarifies the workflow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states when to use this tool: to withdraw a sent or refuse a received invitation. It gives a practical prerequisite (obtain request_id via linkedin_list_invitations) but does not explicitly name alternatives or exclusions (e.g., 'use linkedin_accept_invitation for accepting'). The context is clear enough for an agent to decide, so not a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_classic_get_applicant_resumeLinkedIn: Classic get applicant resumeARead-onlyIdempotentInspect
Download/retrieve the resume of one applicant to a LinkedIn Classic job. Never infer applicant_id from name; list applicants first and reuse exact applicant.id.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | Exact LinkedIn job posting ID. Classic: obtain from owned Classic job postings. Recruiter: obtain from the selected Recruiter project's jobs. Never use title/URL as job_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| applicant_id | Yes | Exact applicant profile ID returned by the corresponding applicants listing. Keep it paired with the Classic job_id or Recruiter project_id that produced it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive behavior, so the safety profile is covered. The description adds an applicant_id selection caution but does not disclose details like authentication requirements, rate limits, or response format. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, with the action front-loaded and a high-value warning second. Every word earns its place; there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with rich annotations and fully documented parameters, the description covers the invocation essentials. The only notable gap is the absence of return format details (e.g., URL vs binary vs base64), which matters slightly more because there is no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already describes applicant_id as an exact ID from the corresponding listing, job_id acquisition rules, and account_id selection. The description restates the applicant_id caution but does not add meaning beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states an exact action ('Download/retrieve'), a specific resource ('the resume of one applicant to a LinkedIn Classic job'), and clear singular scope ('one applicant'). This distinguishes it from listing tools and from the Recruiter resume variant visible in sibling tool names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit operational guidance: never infer applicant_id from name, list applicants first, and reuse exact applicant.id. It does not explicitly name an alternative tool for Recruiter contexts, but the Classic scope and the 'never infer' rule provide clear context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_classic_get_job_applicantLinkedIn: Classic get job applicantARead-onlyIdempotentInspect
Get one applicant to a LinkedIn Classic job. Required chain: owned Classic job -> job_id -> list applicants -> applicant.id -> this tool.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | Exact LinkedIn job posting ID. Classic: obtain from owned Classic job postings. Recruiter: obtain from the selected Recruiter project's jobs. Never use title/URL as job_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| applicant_id | Yes | Exact applicant profile ID returned by the corresponding applicants listing. Keep it paired with the Classic job_id or Recruiter project_id that produced it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds the chain context (owned job -> list applicants -> applicant.id), which is behavioral but not exhaustive (e.g., no mention of error conditions or return format). It adds value beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. The core purpose is front-loaded, and the prerequisite chain is stated compactly. Everything present earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with annotations covering safety and a fully described schema, the description is nearly complete. It includes the essential chain that an agent must know to call it correctly. The only missing context is the exact return format, but that is not critical given the tool's simplicity and no output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all parameters are documented in the schema. The description itself does not add parameter-level meaning beyond the schema, which is appropriate given the high coverage. Baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get one applicant to a LinkedIn Classic job.' It also provides the prerequisite chain that distinguishes it from sibling tools like linkedin_classic_list_job_applicants (list) and linkedin_classic_get_applicant_resume (resume). The purpose is unambiguous and distinct.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Required chain' explicitly tells the agent when to use this tool: after listing applicants and having applicant.id. It implies it should not be used before that step. While it doesn't explicitly mention alternatives, the chain is a clear usage guideline for sequencing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_classic_list_job_applicantsLinkedIn: Classic list job applicantsARead-onlyIdempotentInspect
List applicants for a LinkedIn Classic job owned by the connected account. Resolve the exact Classic job_id first. Filters are passed as V2 applicant filters (for example ratings/experience) and must use provider enums/IDs rather than guessed display values.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | Exact LinkedIn job posting ID. Classic: obtain from owned Classic job postings. Recruiter: obtain from the selected Recruiter project's jobs. Never use title/URL as job_id. | |
| filters | No | Optional V2 Classic applicant filters. Use documented enum/filter IDs; omit unknown filters rather than guessing. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the base safety profile is covered. The description adds non-redundant behavioral context: a hard prerequisite ('Resolve the exact Classic job_id first') and the constraint that filter values must be provider enums/IDs, which aligns with openWorldHint=false without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler: purpose, prerequisite, and filter semantics each get exactly one sentence in priority order. The description is front-loaded with what the tool does, then gives only the call-critical caveats.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter tool with a nested filters object and no output schema, the description plus fully-covered schema supplies everything call-critical: scope, prerequisite, and filter semantics. The only gap is that return shape or pagination behavior is never hinted, which is a minor omission for a straightforward list tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% — job_id, filters, and account_id each have substantive descriptions — so the baseline is 3. The description adds marginal semantic value by naming example filter dimensions ('ratings/experience') and re-emphasizing the enum/ID requirement, which helps an agent shape the nested filters object beyond the generic schema wording.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a specific resource ('applicants for a LinkedIn Classic job owned by the connected account'), and the 'Classic' qualifier plus ownership scope distinguishes it from linkedin_recruiter_list_applicants and linkedin_classic_get_job_applicant. An agent can tell what this tool does and what it is not without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives genuine usage context: 'Resolve the exact Classic job_id first' states a prerequisite, and the V2-filter guidance explains how to construct the call. However, it never explicitly names alternatives or states when-not-to-use (e.g., linkedin_recruiter_list_applicants for Recruiter projects), leaving sibling differentiation to the tool name and schema notes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_comment_on_postLinkedIn: Comment on postADestructiveInspect
Publish a comment/reply on a LinkedIn post on behalf of the user. Requires post_id. Use after reading the post/comments and only when the user has asked to publish the final reply.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| post_id | Yes | Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true and readOnlyHint=false, covering the side-effect nature. The description adds 'on behalf of the user' and 'only when the user has asked,' which are useful behavioral cues. However, it does not mention potential irreversibility, permission requirements, or rate limits. Given the annotations cover the core safety profile, the description adds moderate value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The purpose is stated first, followed by a clear usage condition. Every word earns its place, and the key constraint (use after reading, only on user request) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a straightforward write operation with no output schema, the description covers the essential aspects: what it does, when to use it, and the requirement for post_id. It omits error conditions or prerequisites, but these are not critical for a simple comment action. The schema handles parameter details adequately for most cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not elaborate on any parameters. Schema coverage is 67% (post_id and account_id have descriptions, text does not). The description does not compensate for the undocumented 'text' parameter or add any additional semantic clarity. It merely restates that post_id is required, which is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action 'Publish a comment/reply on a LinkedIn post' with a clear resource. It distinguishes from siblings like linkedin_create_post (which creates a new post) and linkedin_reply_to_comment (which replies to a comment), though it doesn't explicitly name them. The title 'Comment on post' reinforces the intent, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance: 'Use after reading the post/comments and only when the user has asked to publish the final reply.' This tells the agent when to invoke it and implies it should not be used prematurely or without user consent. It does not explicitly mention alternatives, but the 'after reading' context effectively sets the appropriate trigger.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_create_postLinkedIn: Create postADestructiveInspect
Publish a LinkedIn post from the user's own account, optionally on a managed company page using post_as. This is a public side effect; use only after the user has clearly approved the final content and target identity.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| post_as | No | Exact managed page/company identity returned by linkedin_list_managed_pages; omit to post as the connected person. Never pass a company name or URL. | |
| can_read | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| can_comment | No | ||
| quoted_post_id | No | Exact provider post ID to quote, returned by post search/list/get. Never pass post text or a URL. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, destructiveHint=true, openWorldHint=true), the description explicitly labels the operation a 'public side effect' and requires user approval, which adds consent and visibility context. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two front-loaded sentences state function, scope, side effect, and approval requirement without redundancy. Every sentence adds information needed for safe invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Combined with the schema's detailed parameter descriptions and the annotations, the description covers target identity, approval, and public side effects. It does not describe return values or defaults for can_read/can_comment, but those are minor for invoking this tool successfully.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The main description only elaborates post_as ('managed company page' and 'target identity'), while the schema already carries strong descriptions for post_as, account_id, and quoted_post_id. With 50% schema coverage, the tool definition gives enough parameter meaning overall, but the free-text description itself does little to compensate for the undocumented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Publish') with a concrete resource ('a LinkedIn post') and clarifies the account scope: the user's own account or a managed company page via post_as. This clearly separates it from nearby social/list/comment tools even without naming a sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description sets an explicit precondition: use only after the user has clearly approved the final content and target identity. It does not name an alternative tool, but the approval trigger and public side-effect warning are enough to guide appropriate invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_endorse_skillLinkedIn: Endorse skillAInspect
Endorse one skill on a LinkedIn relation. Resolve member_id first, fetch that profile with linkedin_skills, and reuse the exact returned endorsement skill_id; never pass a skill name.
| Name | Required | Description | Default |
|---|---|---|---|
| skill_id | Yes | Exact endorsement skill ID from the member profile's linkedin_skills section; not the display name. | |
| member_id | Yes | Exact LinkedIn member profile ID returned by the profile resolver; not a URL/name. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is a write operation (readOnlyHint=false) and non-idempotent. The description adds behavioral context beyond annotations by requiring the skill_id to be the exact endorsement ID from linkedin_skills and forbidding skill-name input, which is critical for correct invocation. It does not disclose side effects or failure modes, but the workflow constraint is a meaningful addition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero filler. The core action is stated first, followed by the two critical procedural constraints. Every clause adds necessary information; there is no redundant or vague wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple write tool with no output schema, the description provides the essential preconditions, the source of each required ID, and the primary pitfall to avoid. It could explain what happens if the skill_id is invalid or if the member is not a relation, but the current guidance is sufficient for correct invocation in the common case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage with detailed parameter descriptions, so the baseline is 3. The description adds value by prescribing the order of operations: member_id must be resolved first)SkipLinkedIn_profile via linkedin_skills, and the returned endorsement skill_id must be reused exactly. It reinforces the most important semantic rule (never pass a skill name) and explains the provenance of both required parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Endorse one skill on a LinkedIn relation.' It also distinguishes the action from related profile operations by specifying the endorsement skill context, and states the required workflow (resolve member_id, fetch profile, reuse skill_id), leaving no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear procedural context: resolve member_id first, fetch the profile with linkedin_skills, and reuse the exact returned endorsement skill_id, plus a hard constraint to never pass a skill name. It does not explicitly name an alternative tool or state when not to use it, but the workflow is specific enough for an agent to know exactly when and how to invoke it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_follow_userLinkedIn: Follow userAInspect
Follow a LinkedIn user from the connected personal account. Resolve the exact provider user_id first.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Exact provider user ID returned by the relevant profile/contact resolver; never a display name or profile URL. For LinkedIn, use the stable system ID. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false, so the agent knows it's a mutation. The description adds that it operates on the 'connected personal account,' which provides some scope context. It does not disclose side effects like notifications or rate limits, but given the annotations cover the safety profile, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero filler. The primary action is stated first, followed by the critical prerequisite. It is efficiently structured and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description, combined with detailed parameter descriptions and annotations, covers the essentials: what the tool does, the required prerequisite, and how to supply parameters. It omits handling of edge cases like already-followed users, but that is minor given the simplicity and the schema's thoroughness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 100% schema coverage, the description for user_id adds substantial meaning: it explains what constitutes a valid ID (stable system ID), how to obtain it via three specific resolver tools, and what to avoid (URLs, names, company IDs). account_id also clarifies when to omit vs. pass it. This goes far beyond the schema's basic type and is highly actionable.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb+resource: 'Follow a LinkedIn user from the connected personal account.' It is unambiguous and distinguishes from sibling tools like linkedin_unfollow_user and linkedin_send_invitation by specifying the action of following.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs to 'Resolve the exact provider user_id first,' which is a crucial prerequisite. However, it does not explicitly contrast with alternatives (e.g., connecting vs. following) or mention when not to use the tool. The user_id parameter description adds rich detail on how to obtain the ID, but the main description lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_companyLinkedIn: Get companyARead-onlyIdempotentInspect
Get a LinkedIn company profile by numeric/provider company ID. Use after linkedin_search_companies when full company data is needed.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| company_id | Yes | Exact LinkedIn company ID returned by company search/resolution. Never pass a company name, URL or slug. LinkedIn company ID: Provider numeric/company ID. For mentions LinkedIn requires numeric company ID, not the company URL slug. Obtain with: linkedin_search_companies -> selected result.id; linkedin_get_company after resolving a company Never pass: linkedin.com/company/google URL, company slug such as google, company name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, which covers the safety profile. The description adds workflow context but no additional behavioral details such as response shape, error behavior, or auth expectations. This is acceptable given strong annotations, but the description itself contributes only modest extra context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first states the action and identifier type, the second provides the workflow trigger. Every word earns its place, and the core information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a simple 2-parameter read tool with heavy schema coverage and strong annotations, the description is largely complete: it tells the agent what to call, with which ID type, and after which preceding tool. No output schema exists, and the description could briefly mention return fields, but 'company profile' plus the workflow context is sufficient for confident invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema thoroughly documents both parameters, including account_id disambiguation and the strict company_id format rules. The description itself mostly echoes 'numeric/provider company ID' and does not add parameter meaning beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb ('Get'), a clear resource ('LinkedIn company profile'), and the exact identifier type ('numeric/provider company ID'). It distinguishes itself from search/resolve siblings by framing the call as the follow-up that returns full company data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description explicitly says to use it after linkedin_search_companies when full company data is needed, giving a clear workflow context and selection condition. It does not list explicit exclusions or alternative tools beyond the search step, so it stops short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_inmail_creditsLinkedIn: Get InMail creditsARead-onlyIdempotentInspect
Get LinkedIn InMail credit information for the connected account. Use when the user asks whether an InMail can be sent or how many credits remain.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds connected-account scope and trigger semantics, but doesn't disclose additional behavior such as error conditions, stale data, or whether a connection must first exist. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with no filler. The core action is front-loaded and the usage trigger is given immediately, making it easy for an agent to scan and apply.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A read-only tool with one optional parameter is fully covered by the description plus the rich account_id schema. There is no output schema, but 'credit information' and 'how many credits remain' give enough semantic context for an agent to know what the tool returns.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the account_id parameter already includes detailed guidance about omitting it, listing accounts, and disambiguation. The description does not need to repeat parameter details, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Get'), resource ('LinkedIn InMail credit information'), and scope ('for the connected account'). The second sentence adds the user-facing trigger, making it easy to distinguish from sending or invitation tools like linkedin_send_message.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use when the user asks whether an InMail can be sent or how many credits remain' is explicit and actionable context. It doesn't name an alternative tool or state exclusions, but the use case is sufficiently distinct from siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_job_postingLinkedIn: Get job postingARead-onlyIdempotentInspect
Get one job posting owned by the user's LinkedIn account. job_posting_id MUST come from linkedin_list_job_postings, not a title/company or an unrelated discovery result. LinkedIn job ID: Exact LinkedIn job/job-posting ID returned by the corresponding search/list endpoint. Obtain with: linkedin_search_jobs -> result.id for discovery; linkedin_list_job_postings -> result.id for jobs owned by the account Never pass: job title, company ID.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| job_posting_id | Yes | Exact owned job posting ID returned by linkedin_list_job_postings -> result.id. LinkedIn job ID: Exact LinkedIn job/job-posting ID returned by the corresponding search/list endpoint. Obtain with: linkedin_search_jobs -> result.id for discovery; linkedin_list_job_postings -> result.id for jobs owned by the account Never pass: job title, company ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is known. The description adds context beyond annotations by clarifying that this tool only retrieves job postings owned by the user's account and that the ID must be sourced from the list endpoint. This adds behavioral understanding of scope and ID provenance, valuable for correct invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise—two sentences—and front-loads the core purpose before the critical constraint. Every word adds value, with no extraneous content. The structure clearly separates 'what it does' from 'how to get the ID,' making it easy for an agent to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only get operation with no output schema, the description provides sufficient context: what it retrieves, the required ID source, and exclusions. It doesn't detail return format or error handling, but given the simplicity and the annotations covering safety, the definition is complete enough for correct use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, meaning both parameters already have detailed descriptions. The tool description largely repeats the schema's guidance on job_posting_id (e.g., must be from linkedin_list_job_postings, never title/company). Since the schema already documents the parameters thoroughly, the description adds minimal new semantic value beyond reinforcement, matching the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Get'), the resource ('one job posting'), and the scope ('owned by the user's LinkedIn account'). It explicitly distinguishes from discovery tools by specifying that the ID must come from linkedin_list_job_postings, not unrelated results. This differentiates it from siblings like linkedin_search_jobs and linkedin_list_job_postings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit instructions on the correct ID source: it MUST come from linkedin_list_job_postings, not a title/company or unrelated discovery. It also warns 'Never pass: job title, company ID.' This clearly guides when to use this tool versus alternatives and what to avoid, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_job_posting_budgetLinkedIn: Get job posting budgetARead-onlyIdempotentInspect
Get budget/pricing information for a LinkedIn Classic job posting owned by the connected account. Resolve job_id with linkedin_list_job_postings first.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | Yes | Exact Classic job ID returned by linkedin_list_job_postings; not title or URL. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered. The description adds only the prerequisite resolution step, which is more usage context than behavioral trait disclosure. It does not contradict annotations and does not need to repeat them, but it also does not add extra behavioral detail beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero filler. The primary purpose is front-loaded in the first sentence, and the second sentence gives the only necessary usage note. Every word contributes value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only getter with full schema coverage and annotations, the description is nearly complete. It includes the key prerequisite for job_id and the owned-by-connected-account scoping. The only minor gap is not describing the return value, but with no output schema and the tool name indicating budget info, this is acceptable for the complexity level.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The schema already explains job_id as 'Exact Classic job ID returned by linkedin_list_job_postings; not title or URL' and provides detailed instructions for account_id. The description's mention of resolving job_id with linkedin_list_job_postings is redundant with the schema, adding no new parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource: 'Get budget/pricing information for a LinkedIn Classic job posting.' It also names the prerequisite tool linkedin_list_job_postings, which differentiates it from sibling tools like linkedin_get_job_posting. An agent can clearly identify what this tool does and how it relates to nearby functions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit prerequisite guidance: 'Resolve job_id with linkedin_list_job_postings first.' This tells agents when to use this tool (after listing job postings) and establishes the correct input source. It does not explicitly mention when not to use it, but the name and purpose make the use case clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_my_profileLinkedIn: Get my profileARead-onlyIdempotentInspect
Get the profile of the owner of the connected LinkedIn account. Use for 'my LinkedIn profile', identity/context, or before actions that need the account owner's provider user ID.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds useful context about the profile belonging to the account owner and that the provider user ID is relevant, but it does not disclose additional behaviors such as auth requirements, rate limits, or return behavior beyond what annotations already imply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loads the core purpose, and adds precise usage guidance without any filler. Every sentence contributes meaningful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one optional parameter, rich annotations, and clear sibling differentiation, the description is complete. It tells an agent what the tool returns (the owner's profile), when to use it, and why the provider user ID matters, which is sufficient despite the absence of an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% coverage with a detailed account_id description, including when to omit it and how to handle multiple accounts. The tool description adds no additional parameter-level semantics, so the baseline of 3 applies because the schema already carries the explanatory burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get the profile of the owner of the connected LinkedIn account.' This clearly distinguishes it from sibling tools like linkedin_get_profile and linkedin_get_profile_from_url by specifying 'owner of the connected account.' It also names concrete use cases, leaving no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit use cases: 'for my LinkedIn profile, identity/context, or before actions that need the account owner's provider user ID.' This provides clear context for when to use the tool. However, it does not explicitly mention alternatives or exclusion conditions, though the 'owner' phrasing implicitly separates it from other LinkedIn profile lookup tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_postLinkedIn: Get postARead-onlyIdempotentInspect
Get a LinkedIn post by Nilyo/Unipile post_id. Use when you already know a post_id and need full post context.
| Name | Required | Description | Default |
|---|---|---|---|
| post_id | Yes | Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description does not contradict these and adds minimal behavioral context—just that it fetches a post. It does not add details about edge cases, errors, or rate limits, but with annotations carrying the load, the bar is lower. The description provides no additional behavioral value beyond the annotations, so a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no fluff: the first states the action and identifier type, the second gives the usage context. It is front-loaded and every word earns its place. This is a model of conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one required parameter, the description is sufficiently complete. It explains the purpose, when to use it, and the schema documents parameters thoroughly. There is no output schema, but the phrase 'full post context' hints at the return. The tool is simple enough that no further guidance is essential, though it could mention error behavior, which is not required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: both post_id and account_id have detailed descriptions, including guidance on obtaining post_id from search/list tools and when to provide account_id. The tool description itself adds no parameter-specific information beyond the schema. According to the rubric, with high schema coverage, the baseline is 3, and the description does not elevate it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb-resource pair: 'Get a LinkedIn post by Nilyo/Unipile post_id.' It clearly distinguishes this from sibling tools like linkedin_search_posts or linkedin_list_user_posts by specifying the retrieval method (by post_id) and the condition of already having the ID. This is not a tautology and provides a clear, singular purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit usage condition: 'Use when you already know a post_id and need full post context.' This implies when not to use it (e.g., when you need to search or list posts) and distinguishes it from alternatives. However, it does not explicitly name alternative tools or state exclusion criteria beyond the presence of an ID, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_profileLinkedIn: Get profileARead-onlyIdempotentInspect
Get a LinkedIn person's full profile from a LinkedIn provider user ID, public identifier, or linkedin.com/in/... URL using the user's own account. This is the preferred resolver before an action when the user supplied only a profile URL. The result contains the stable user id needed by linkedin_start_conversation and linkedin_send_invitation. Optional sections can retrieve experience, skills, interests and other profile details.
| Name | Required | Description | Default |
|---|---|---|---|
| variant | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| with_sections | No | Classic-only optional sections such as linkedin_experience, linkedin_skills or preview variants. | |
| user_id_or_url | Yes | LinkedIn user ID (for example ACo...), public identifier, or full linkedin.com/in/... profile URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, non-destructive, idempotent behavior. The description adds meaningful context beyond those annotations: the operation runs 'using the user's own account,' it resolves multiple identifier forms, and its output supplies the stable user id needed by follow-up actions. This gives the agent a clearer behavioral model than the annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The core action and accepted identifier forms are front-loaded, followed by when to prefer it, what the result enables, and optional sections. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only resolver with no output schema, the description gives enough context to call it correctly: identifier forms, account context, preferred usage, downstream dependency, and optional sections. It could be more complete by explaining the variant parameter or naming the direct sibling alternative, but nothing essential for a correct call is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, and the description adds some value by explaining the accepted identifier forms for user_id_or_url and the purpose of with_sections. However, the variant parameter has no schema description and is not addressed in the tool description, and much of the description repeats what the schema already documents. This is adequate but not exceptional.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get a LinkedIn person's full profile' from a user ID, public identifier, or profile URL. It also carves out a distinct role as 'the preferred resolver before an action when the user supplied only a profile URL' and ties the result to the stable user id needed by other tools, which clearly differentiates it from sibling tools like linkedin_get_profile_from_url or linkedin_search_people.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: use it as a resolver before an action when the user supplied only a profile URL, and it calls out downstream tools that need the stable user id (linkedin_start_conversation, linkedin_send_invitation). It does not explicitly name alternatives or state when not to use it, so it stops just short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_profile_from_urlLinkedIn: Get profile from URLARead-onlyIdempotentInspect
Resolve a full LinkedIn person profile URL into the real LinkedIn profile and stable system user ID required by downstream actions. Example: https://www.linkedin.com/in/john-doe-123/?trk=foo -> extract ONLY 'john-doe-123' from the /in/{public_identifier}/ pathname, ignore query parameters/fragments/trailing slash, call Get User Profile, and return the profile including result.id. Use result.id for connection requests, new conversations and other actions requiring user_id. Never pass the full URL to those action tools. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. LinkedIn public identifier: Slug after /in/ in a LinkedIn profile URL. Example https://www.linkedin.com/in/john-doe/?trk=x -> john-doe. Obtain with: extract only pathname segment immediately after /in/; ignore query string, fragment and trailing slash Never pass: full URL, ACo system ID when a public identifier is specifically required.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| profile_url | Yes | Full linkedin.com/in/... person profile URL. Query parameters are ignored. | |
| with_sections | No | Optional LinkedIn Classic profile sections such as linkedin_experience, linkedin_education or linkedin_skills. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnly/openWorld/idempotent annotations, the description discloses parsing behavior (ignore query params/fragments/trailing slash, extract only the slug), the call to Get User Profile, and that the response includes result.id. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentence is an effective front-loaded purpose statement, but the description is long and repeats the path extraction rule and 'Never pass' guidance in separate sections. Most content is useful, but it could be trimmed without loss.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description rightly explains that the result includes result.id and how that ID should be used downstream. It also covers the account/public identifier distinction and alternatives. It is complete for an agent deciding to call this tool and use its result correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema coverage is 100%, so the baseline is 3. The description adds value for profile_url by explaining exactly how it is normalized and why result.id matters, although it does not add semantics for account_id or with_sections beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation: resolve a full LinkedIn profile URL into the real profile and stable system user ID via extraction of the /in/{public_identifier}/ path segment. It is clearly distinguished from linkedin_get_profile by the URL-to-profile behavior and by explaining that result.id is needed downstream. The example makes the input/output relationship unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly gives three routes to obtain result.id (linkedin_get_profile_from_url, linkedin_get_profile, linkedin_search_people) and warns never to pass full URLs, person names, or company IDs downstream. It does not explicitly state 'use this when you have a full URL and not a user ID,' but that condition is strongly implied by the purpose and examples.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_get_search_parametersLinkedIn: Get search parametersARead-onlyIdempotentInspect
Resolve human LinkedIn filter values such as a location, company, industry, job function, relation, project, saved search or Sales Navigator list into the provider parameter IDs required by LinkedIn search endpoints. Typical sequence: call this with type + query, then pass the chosen returned id into linkedin_search_people / Sales Navigator / Recruiter search.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | LinkedIn parameter type, e.g. LOCATION, COMPANY, INDUSTRY, RELATION, JOB_FUNCTION, PROJECT, SAVED_SEARCH, LEAD_LIST. | |
| query | No | Human text to resolve, such as Paris, Stripe or Software. Required for Classic search parameters; optional for Sales Navigator/Recruiter lists. | |
| product | Yes | classic | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context: it resolves human values into provider parameter IDs, and it explicitly states that Nilyo never guesses when multiple accounts exist, instructing the agent to list and ask. This goes beyond the annotations and helps the agent understand the tool's non-deterministic account-selection behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the core purpose, the second gives the typical usage sequence, and the account_id guidance is placed in the schema where it belongs. Every sentence earns its place, and there is no redundant restating of the tool name or title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only resolution tool with no output schema, the description covers the main workflow, the parameter relationships, and the multi-account edge case. It doesn't describe the exact shape of the returned IDs or how to handle multiple matches for a query, but the 'choose the returned id' phrasing implies a selection step. Given the tool's moderate complexity and the strong schema coverage, this is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 75%, so the schema already documents type, query, and account_id. The description adds meaning by explaining the relationship between type and query ('call this with type + query') and by clarifying that query is optional for Sales Navigator/Recruiter lists. It also adds the crucial account_id disambiguation rule, which is not fully captured by the schema's 'Optional Nilyo connection ID' phrasing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Resolve') and resource ('human LinkedIn filter values... into provider parameter IDs'), and clearly distinguishes this from search tools by naming the downstream consumers (linkedin_search_people / Sales Navigator / Recruiter search). It also enumerates the filter value types, making the tool's scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Typical sequence: call this with type + query, then pass the chosen returned id into linkedin_search_people / Sales Navigator / Recruiter search.' This tells the agent exactly when to use this tool and how it fits into a workflow. The account_id parameter description also provides clear guidance on when to omit vs. provide it, including a fallback instruction to list and ask.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_comment_repliesLinkedIn: List comment repliesARead-onlyIdempotentInspect
List replies under one exact LinkedIn comment. Chain: resolve post -> post.id -> list comments -> comment.id -> replies. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| post_id | Yes | Exact post ID from post search/list. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| comment_id | Yes | Exact comment ID from comments of the resolved post. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal a safe read-only, idempotent call. The description adds meaningful behavioral context: the call is strictly scoped to one exact comment, the IDs must be obtained via a resolution chain, and non-ID inputs are rejected. It does not cover pagination or response behavior, but the safety profile is already declared by annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear one-line purpose and uses useful 'Post ID:' and 'Comment ID:' sections. However, those sections duplicate the schema descriptions nearly verbatim, and the inclusion of instagram_list_user_posts and instagram_list_post_comments as sources for a LinkedIn tool is confusing and likely erroneous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter tool with no output schema, the description plus schema covers the essential invocation path: exact IDs, where to get them, what not to pass, and account disambiguation in the schema's account_id description. It lacks a description of return values and does not explain the optional offset parameter, which is a minor gap since the tool name and first sentence imply a list result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 75%, and the tool description mostly repeats the schema's own guidance for post_id and comment_id rather than adding new parameter-level information. The offset parameter is undocumented in both the schema and the description, and account_id guidance lives only in the schema. The chain clarifies the relationship between parameters but adds little beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence, 'List replies under one exact LinkedIn comment,' states a specific action and resource. It also distinguishes itself from sibling list tools like linkedin_list_post_comments by scoping the call to a single comment ID and showing the required chain: resolve post -> post.id -> list comments -> comment.id -> replies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit chain for obtaining required IDs and names the exact preceding tools (linkedin_search_posts, linkedin_list_post_comments). It also states hard exclusions: 'Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it.' It does not, however, explicitly contrast this tool with alternatives like social_list_comment_reactions for deciding which operation to call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_contractsLinkedIn: List contractsARead-onlyIdempotentInspect
List LinkedIn premium contracts available on the user's account. Returned contract.id is the ONLY value to pass as contract_id to linkedin_select_contract. contract_id is distinct from inbox_id. LinkedIn premium contract ID: Exact Sales Navigator/Recruiter contract id. Obtain with: linkedin_list_contracts -> contract.id Never pass: inbox_id, product name. Inbox ID: Provider inbox/product inbox identifier. LinkedIn Classic may use CLASSIC; premium products expose their own inbox IDs. Obtain with: linkedin_list_inboxes -> inbox.id Never pass: contract_id unless returned as the inbox id, guessing SALES_NAVIGATOR or RECRUITER.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish the safety profile (readOnlyHint=true, idempotentHint=true, destructiveHint=false), so the description only needs to add context beyond that. It adds meaningful scoping ('available on the user's account') and cross-tool ID semantics, though it does not disclose details like pagination, empty-result behavior, or authentication requirements. Given the strong annotations, this is solid but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main purpose is front-loaded, and the labeled sections for contract ID vs inbox ID are structurally clear. There is some redundancy—'contract.id' and 'Never pass: inbox_id' appear more than once—so it is slightly less concise than ideal, but every block carries important disambiguation value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, read-only, zero-required-parameter list tool with no output schema, the description plus input schema covers everything an agent needs: what is listed, how to obtain the relevant IDs, what not to pass, and how the optional account_id should be handled. The sibling context also makes the tool's role in the broader LinkedIn workflow clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the input schema already fully documents account_id, including the 'Nilyo never guesses' fallback behavior. The tool description's ID-related warnings concern contract_id/inbox_id values used by other tools, not this tool's own parameters, so the description adds no additional parameter semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List LinkedIn premium contracts available on the user's account.' It clearly differentiates from linkedin_select_contract and linkedin_list_inboxes by emphasizing that contract.id is distinct from inbox_id and is the only valid value for contract_id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the returned data: 'contract.id is the ONLY value to pass as contract_id to linkedin_select_contract.' It also names the alternative for inbox IDs ('Obtain with: linkedin_list_inboxes -> inbox.id') and gives negative guidance ('Never pass: inbox_id, product name'), leaving no ambiguity about when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_conversationsLinkedIn: List conversationsARead-onlyIdempotentInspect
List LinkedIn private conversations. By default only the Classic primary inbox (CLASSIC_PRIMARY); pass inbox_ids from linkedin_list_inboxes to read other inboxes (archived, spam, Sales Navigator, Recruiter, company pages). Inboxes are read one after another to respect LinkedIn rate limits; unreadable ones are reported with unavailable instead of failing. Preserve inbox_id and chat.id. Use before linkedin_read_conversation when chat_id is unknown.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| inbox_ids | No | Exact inbox IDs from linkedin_list_inboxes (e.g. CLASSIC_PRIMARY, SALES_NAVIGATOR_PRIMARY). Default: CLASSIC_PRIMARY only. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering safety. The description adds valuable behavioral context: reading inboxes sequentially to respect rate limits, reporting unreadable inboxes as 'unavailable' instead of failing, and preserving inbox_id and chat.id. This goes beyond annotations and helps the agent understand expected behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no fluff. It front-loads the core purpose, then explains default behavior, extension options, rate-limit handling, and a specific usage instruction. Every sentence contributes meaning, making it highly efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with no output schema, the description covers key operational aspects: default inbox, how to specify other inboxes, rate-limit behavior, error handling for unreadable inboxes, and a usage hint. However, it does not explain the output structure beyond mentioning preserving inbox_id and chat.id, nor clarify whether limit applies per inbox or total, and lacks pagination details. Given the tool's complexity, these are minor gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67%. The description text reinforces the inbox_ids usage but does not add significant detail for limit or account_id beyond what the schema already provides. The account_id parameter has a detailed schema description, and the limit parameter lacks description in both places. The description adds minimal value for parameters beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'List LinkedIn private conversations' with a specific verb and resource. It also explains the default inbox and how to access other inboxes, which adds specificity. However, it does not differentiate from the sibling tool 'linkedin_list_inbox_chats', which likely has a similar purpose, so the distinction is unclear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear guidance on when to use this tool: 'Use before linkedin_read_conversation when chat_id is unknown' and explains how to pass inbox_ids for other inboxes. It provides context on default behavior and how to extend it, but does not explicitly state when NOT to use it or mention alternatives like linkedin_list_inbox_chats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_followersLinkedIn: List followersARead-onlyIdempotentInspect
List followers of the account owner or a known LinkedIn user. Use user_id='me' for the connected account owner.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| user_id | Yes | Use 'me' for the connected account owner, otherwise an exact stable LinkedIn system user ID returned by a profile/person resolver. Never pass a name or profile URL. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | me |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the operation as read-only, open-world, idempotent, and non-destructive. The description consistently portrays a simple list operation and adds the target scope, but it does not mention response format or pagination behavior. With annotations covering safety, this is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The core operation is front-loaded and the 'me' convention is stated immediately after, making the essential usage instruction immediately visible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list operation with detailed parameter descriptions in the schema, the description covers the main invocation choice: account owner versus known user. It omits explicit return-value or pagination context, but these are not critical for a straightforward list tool with safe annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description only echoes what the schema already states about user_id='me'. It adds no meaning for offset or account_id, and since schema coverage is 67%, the description does not compensate for the partially uncovered parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'List followers of the account owner or a known LinkedIn user.' It clearly identifies the target account and differentiates from the sibling tool linkedin_list_following by naming the followers relationship explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context by stating that user_id='me' refers to the connected account owner and that a known LinkedIn user can also be used. It lacks explicit when-not-to-use guidance or named alternatives, but the basic selection rule is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_followingLinkedIn: List followingARead-onlyIdempotentInspect
List LinkedIn users followed by the connected account owner. Prefer user_id='me'; provider availability may restrict following data for other users.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| user_id | Yes | Use 'me' for the connected account owner, otherwise an exact stable LinkedIn system user ID returned by a profile/person resolver. Never pass a name or profile URL. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | me |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false, so the safety profile is covered. The description adds a behavioral caveat about provider restrictions, but it does not disclose pagination behavior or result format, and with no output schema some behavior remains implicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short, purposeful sentences with no filler. The main action is front-loaded, and the usage caveat follows immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool, the schema carries the heavy parameter guidance and the description gives the key scope and provider caveat. The main gap is the undocumented offset parameter and lack of explicit comparison to linkedin_list_followers, but nothing essential is missing for a routine call with user_id=me.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides rich, detailed descriptions for user_id and account_id, and the description reinforces the user_id default with prefer user_id=me. However, offset has no description in the schema or the tool description, and the description does not explain its pagination usage, so it only partially compensates for the 67% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and object: it lists LinkedIn users followed by the connected account owner. This unambiguously distinguishes the tool from sibling linkedin_list_followers by direction, and the follow-up preference for user_id=me reinforces the intended scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context by instructing the agent to prefer user_id=me and warns that provider availability may restrict data for other users. It does not explicitly name when-not-to-use cases or alternatives such as linkedin_list_followers, so it misses the top bar by a small margin.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_inbox_chatsLinkedIn: List inbox chatsARead-onlyIdempotentInspect
List chats from a specific LinkedIn inbox. Prefer this over generic chat listing for LinkedIn V2 and premium Sales Navigator/Recruiter inboxes. Get inbox_id from linkedin_list_inboxes. Pages are capped at 20; follow every cursor and list each intended inbox separately. A page is not an exhaustive digest. With cursor, the page size of the first page is kept (limit is ignored).
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | ||
| limit | No | ||
| before | No | ||
| cursor | No | ||
| inbox_id | Yes | Exact LinkedIn inbox ID returned by linkedin_list_inboxes. Preserve Classic/Sales Navigator/Recruiter selection; never pass contract_id or product name. Inbox ID: Provider inbox/product inbox identifier. LinkedIn Classic may use CLASSIC; premium products expose their own inbox IDs. Obtain with: linkedin_list_inboxes -> inbox.id Never pass: contract_id unless returned as the inbox id, guessing SALES_NAVIGATOR or RECRUITER. | |
| is_unread | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the description correctly spends its budget on pagination behavior instead: pages capped at 20, a page is not an exhaustive digest, and the cursor rule that the first page's size is retained while limit is ignored. That is real operational context beyond the annotations, though the tension between the 20-page cap and the schema's limit maximum of 250 is left unexplained.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Six short sentences, no filler, and the core purpose plus the sibling preference lead the text. The pagination rules are dense but each sentence carries an actionable instruction; minor tightening is possible around the cursor/limit sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter, no-output-schema tool with low schema coverage, the description adequately covers pagination and inbox selection but omits the semantics of the after/before time filters and is_unread, and never hints at the shape of returned chat records. Adequate but with visible gaps for an agent composing a filtered request.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 29%, so the description carries a heavier burden, and it does clarify cursor semantics (limit ignored once a cursor is present) and that inbox_id must come from linkedin_list_inboxes. However, after, before, limit, and is_unread receive no explanation in either place, so the low-coverage gap is only partially closed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List chats from a specific LinkedIn inbox') and explicitly positions itself against the generic chat listing and against sibling inbox tools by naming the LinkedIn V2 / Sales Navigator / Recruiter context. An agent can distinguish it from messaging_list_chats and linkedin_list_conversations without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit preference rule ('Prefer this over generic chat listing for LinkedIn V2 and premium...'), a prerequisite ('Get inbox_id from linkedin_list_inboxes'), and a usage constraint ('list each intended inbox separately'), plus a pagination directive to follow every cursor. When-to-use, where-to-get-inputs, and how-to-iterate are all covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_inboxesLinkedIn: List inboxesARead-onlyIdempotentInspect
List LinkedIn messaging inboxes for Classic, Sales Navigator and Recruiter. Use before listing inbox chats or starting Sales Navigator/Recruiter conversations; premium products require the appropriate primary inbox.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint and idempotentHint true and destructiveHint false, the safety behavior is already declared in structured metadata. The description adds product-specific behavior: the listing spans Classic, Sales Navigator, and Recruiter and requires an appropriate primary inbox for premium products. Return-shape and pagination are not disclosed, but these omissions are less critical here.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: the first states the action and scope, the second gives the workflow and the premium caveat. No filler or repetition, and the key usage guidance is near the front.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-optional-parameter, read-only tool without an output schema, the description covers the operation, product scope, and downstream workflow. The main residual gap is not spelling out what an inbox object looks like or how primary inbox is determined, but the schema's account guidance and the simple list semantics make the tool usable.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully documents the only parameter, account_id, including when to omit it and how to disambiguate multiple accounts. The description contributes no parameter-specific semantics, but because schema coverage is 100% the description does not need to; baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a concrete action (List) and resource (LinkedIn messaging inboxes) and narrows it to Classic, Sales Navigator, and Recruiter. It also distinguishes the tool from nearby siblings by positioning it before listing inbox chats and starting premium conversations, which is a different step from linkedin_list_inbox_chats or conversation-starting tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly places the call in a workflow: use before listing inbox chats or starting Sales Navigator/Recruiter conversations, so an agent knows the temporal context. The premium-primary-inbox sentence is a concrete prerequisite, but the description does not explicitly state when not to use this tool or name alternative list tools, so it is one step below fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_invitationsLinkedIn: List invitationsARead-onlyIdempotentInspect
List pending LinkedIn connection/relation requests sent or received by the account owner. Use before accepting/refusing a received invitation or withdrawing a sent invitation so you have the required request_id.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds context by specifying that only pending requests are returned and that the output supplies the request_id used by follow-up mutation tools, which is useful behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The purpose is stated first, then the actionable usage context, and every clause contributes to correct invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool, the description covers the operation, the required type parameter, and the downstream use of request_id. It could be more complete by hinting at the response shape or pagination, but nothing essential for a safe call is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%; the rich account_id guidance is already in the schema, and the 'sent or received' wording adds minimal meaning beyond the enum on the required 'type' parameter. The description does not substantially compensate for the enum parameter having no schema-level description, but the enum itself is fairly self-explanatory.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('List'), a specific resource ('pending LinkedIn connection/relation requests'), and a clear scope ('sent or received by the account owner'). This clearly distinguishes it from adjacent invitation tools like linkedin_accept_invitation and linkedin_cancel_or_refuse_invitation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to call this tool: before accepting/refusing a received invitation or withdrawing a sent one, in order to obtain the request_id. It provides clear context but does not explicitly state when-not-to-use or name alternative listing tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_job_postingsLinkedIn: List job postingsARead-onlyIdempotentInspect
List LinkedIn job postings OWNED by the user's account. Use this to resolve job_posting_id for management/budget operations. This differs from linkedin_search_jobs, which discovers jobs across LinkedIn.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| state | Yes | ||
| offset | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint=false, so the safety profile is covered structurally. The description adds a genuinely useful behavioral fact not in the annotations: only postings owned by the account are returned. However, it says nothing about pagination behavior, result ordering, or caps (limit max 100, offset present).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with zero filler; scope, purpose and sibling disambiguation are all front-loaded in the first two sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description should carry more of the return story; telling the agent it yields job_posting_ids for management/budget operations helps, but nothing is said about pagination, state filtering semantics, or result shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 25%; the only documented parameter is account_id. The description never explains state filtering (DRAFT/OPEN/CLOSED/REVIEW/SUSPENDED), the default all-states behavior, or how limit/offset pagination works, so it does not compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) plus resource (LinkedIn job postings) and a scope qualifier (OWNED by the user's account) that immediately distinguishes it from discovery-style listing. It also names the sibling it is not.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit use case ('resolve job_posting_id for management/budget operations') and an explicit alternative with its own condition ('linkedin_search_jobs, which discovers jobs across LinkedIn'). The agent can pick between the two without opening either schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_managed_company_pagesLinkedIn: List managed company pagesARead-onlyIdempotentInspect
List LinkedIn company pages managed by the connected user. Use before publishing as a company page so you can resolve the required post_as company ID.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description does not need to restate safety. It adds the scope ('managed by the connected user') and the output's role in resolving post_as, which is useful context, but it does not disclose return format, pagination, or provider-specific behavior. This is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the operation and followed by the key use case. There is no filler or repetition of schema/annotation content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list operation with zero required parameters and rich annotations, the description provides enough context to call it correctly and explains why the returned pages matter (resolving post_as). It does not enumerate the exact response shape, but the absence of an output schema is mitigated by the simplicity and the stated purpose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single optional parameter is fully documented in the schema (100% coverage), including when to omit it and how to disambiguate multiple accounts. The description itself adds no parameter-level detail, so it stays at the schema-backed baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('List LinkedIn company pages managed by the connected user') and clarifies scope, distinguishing it from generic company lookup tools like linkedin_get_company and linkedin_search_companies. It also states the downstream purpose, which removes ambiguity about what this tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit timing/context: 'Use before publishing as a company page so you can resolve the required post_as company ID.' It does not explicitly list when-not-to-use or alternatives, but the stated use case is clear enough for an agent to select it appropriately among LinkedIn siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_my_connectionsLinkedIn: List my connectionsARead-onlyIdempotentInspect
List/search the LinkedIn connections of the account owner. Use for questions such as 'who do I know at this company?', 'find Sarah in my network', introductions, relationship mapping and connection-aware prospecting. This reads the user's personal network rather than a company page.
| Name | Required | Description | Default |
|---|---|---|---|
| cursor | No | ||
| search | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry the safety profile (readOnlyHint=true, idempotentHint=true, destructiveHint=false), so the bar is lower. The description adds the data-scope trait that this operates on the account owner's personal network rather than a company page. It does not address pagination via the cursor parameter, rate limits, or result limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, purpose front-loaded in the first sentence, use cases in the second, scope clarification in the third. Every sentence earns its place with zero filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with strong annotations and well-documented account_id, the description covers purpose, use cases, and scope. However, there is no output schema, so return format is unexplained, and the cursor (pagination) behavior is nowhere documented. An agent calling with search or paginating results gets no guidance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33% — cursor and search are bare strings with no descriptions in the schema. The description partially compensates by implying search semantics through 'List/search' and examples like 'find Sarah in my network', but cursor/pagination behavior is never explained. account_id is already well documented in the schema, so the description adds little there.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource: 'List/search the LinkedIn connections of the account owner.' The use-case list ('who do I know at this company?', 'find Sarah in my network') and the closing 'This reads the user's personal network rather than a company page' clarify scope. It doesn't explicitly distinguish from near-siblings like linkedin_list_user_relations or linkedin_list_followers, though 'connections' is a precise LinkedIn relationship type.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use examples ('Use for questions such as...', introductions, relationship mapping, connection-aware prospecting). It offers only an implied exclusion ('rather than a company page') and does not name alternative tools such as linkedin_search_people or linkedin_list_followers. This is clear context but lacks explicit when-not and named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_post_commentsLinkedIn: List post commentsARead-onlyIdempotentInspect
List comments on a LinkedIn post. Requires post_id from search/list/get post. Use before deciding which comments need a reply.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| post_id | Yes | Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile with readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds workflow context and post_id provenance, but does not disclose pagination behavior or whether replies are excluded. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences with no filler. The main operation is front-loaded, followed by a prerequisite and a usage context. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list operation, the description plus schema is mostly sufficient, but it does not clarify whether only top-level comments are returned versus replies, and it does not describe pagination/offset behavior. With no output schema, an agent would benefit from additional boundary or return-shape context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides detailed descriptions for post_id and account_id, and the tool description mostly restates post_id provenance already present in the schema. It adds no meaning for offset or account_id, and offset has no schema description. With 67% schema coverage, the description does not compensate for the undocumented parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific operation and resource: 'List comments on a LinkedIn post.' It also identifies the required input source for post_id. It does not explicitly contrast with sibling tools like linkedin_list_comment_replies, but the resource scope is unambiguous enough for an agent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a concrete prerequisite ('Requires post_id from search/list/get post') and a practical workflow cue ('Use before deciding which comments need a reply'). It does not name alternatives or give when-not-to-use conditions, but the context is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_post_reactionsLinkedIn: List post reactionsARead-onlyIdempotentInspect
List people/reactions on a LinkedIn post. Use for engagement analysis or to identify who reacted.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| post_id | Yes | Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds no additional behavioral detail (e.g., pagination, rate limits, error handling), and it is fully consistent with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no waste. The core action is front-loaded and the use case is given in the second sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with rich annotations and detailed schema descriptions for the key parameters, the description covers the essential purpose. It does not describe the return shape or pagination, but that is partly inferable from the tool name and offset parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides thorough descriptions for post_id and account_id, but offset is only defined by type/min/max. Schema coverage is 67%, and the tool description adds no parameter-level semantics beyond the schema, leaving offset's purpose implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb-resource pair: list reactions on a LinkedIn post, and gives a practical use case ('engagement analysis or to identify who reacted'). It does not explicitly name sibling tools, but 'people/reactions on a LinkedIn post' distinguishes it from listing comments or reacting to a post.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It offers clear context for when to use the tool ('Use for engagement analysis or to identify who reacted'). It does not mention when not to use it or point to alternatives like social_list_comment_reactions for comment reactions, but the intended use is explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_user_postsLinkedIn: List user postsARead-onlyIdempotentInspect
List posts authored by the connected LinkedIn user or a known provider user ID. Use to locate a recent post and obtain its post_id before reading comments/reactions or replying.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| user_id | Yes | Use 'me' for the connected account owner, otherwise an exact stable LinkedIn system user ID returned by a profile/person resolver. Never pass a name or profile URL. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | me |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, non-destructive, and idempotent behavior. The description adds the scope nuance (connected user or external provider user ID) but does not disclose pagination, rate limits, or return-shape details. This is acceptable given the annotations but not especially rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The first sentence states what the tool does and the second gives the practical workflow, front-loading the main action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool, the description covers its main purpose and the downstream use of post_id. It omits details about pagination or return format, but the annotations and schema cover the essential safety and parameter context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is roughly 67%: user_id and account_id are well described in the schema, while offset is not. The tool description reinforces the user_id meaning but adds no parameter-level detail, especially for offset.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: listing posts authored by the connected user or a provided user ID. It also states the operational purpose (locating a recent post to get its post_id), which distinguishes it from sibling post-reading and post-writing tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear workflow context: use this before reading comments/reactions or replying, because it supplies the post_id. It does not explicitly name alternatives or when not to use it, so it stops short of the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_list_user_relationsLinkedIn: List user relationsARead-onlyIdempotentInspect
List a LinkedIn user's visible relations by provider user ID. Use when network graph context is requested for a known profile.
| Name | Required | Description | Default |
|---|---|---|---|
| cursor | No | ||
| search | No | ||
| user_id | Yes | Stable LinkedIn system user ID returned by a profile/person resolver. Never pass a name or linkedin.com/in/... URL. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds the scoping constraint ('visible relations by provider user ID') and the 'known profile' prerequisite, which is useful. It doesn't disclose pagination or rate-limit behavior, but with annotations covering safety, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core action and scope are front-loaded, and the usage context is stated in the second sentence. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with strong annotations and a rich user_id schema description, the description is nearly complete. It doesn't explain return values, but there is no output schema and the tool is simple enough that an agent can infer the list of relations. The main gap is not mentioning pagination via cursor, but the schema covers that parameter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 50%, and the description adds meaning by clarifying that user_id is a 'provider user ID' and that the tool operates on 'visible relations.' The user_id parameter description in the schema is already rich, but the tool description reinforces the ID-type requirement and the 'known profile' context, compensating for the cursor/search parameters that lack schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and resource ('a LinkedIn user's visible relations by provider user ID'), which clearly identifies the operation. It distinguishes from siblings like linkedin_list_connections and linkedin_list_following by focusing on 'relations' and 'provider user ID', though it doesn't explicitly name those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says 'Use when network graph context is requested for a known profile,' which gives clear context. It doesn't explicitly state when not to use it or name alternatives like linkedin_list_connections, but the context is specific enough for an agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_react_to_messageLinkedIn: React to messageADestructiveInspect
Add a reaction to a specific LinkedIn message. Requires chat_id and message_id, normally discovered by reading the conversation.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID returned by conversation/inbox listing. Never pass a person name or provider user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| reaction | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the selected chat. Keep it paired with chat_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=true, so the description need not restate that this is a write operation. The description adds no extra behavioral context beyond the act of adding a reaction, such as idempotency implications, limits, or side effects, but it is consistent with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the action and resource, with no filler or redundant restatements. It is appropriately sized for the information it conveys.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is too thin for a state-changing tool with no output schema Asi He. It does not describe what a successful response looks like, how reactions are represented (e.g., emoji vs. code), or any error conditions. The absence of reaction value guidance is a critical gap for an agent invoking this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides detailed descriptions for chat_id, message_id, and account_id, but the required reaction parameter has no schema description and the tool description does not specify valid values or format. With 75% schema coverage, the description fails to compensate for the completely undocumented reaction parameter, leaving the agent without guidance on what to pass.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb ('Add') and resource ('a specific LinkedIn message'), which distinguishes it from post and comment reaction tools. The provider and target are clear both in the description and the tool name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description names required parameters (chat_id, message_id) and how to obtain them ('normally discovered by reading the conversation'). However, it does not explicitly state when to choose this tool over related siblings like linkedin_react_to_post or message_add_reaction, nor does it mention exclusions or prerequisites beyond parameter discovery.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_react_to_postLinkedIn: React to postADestructiveInspect
Add a LinkedIn reaction to a post on behalf of the user. Use a supported LinkedIn reaction value and only when the user's intent to react is clear.
| Name | Required | Description | Default |
|---|---|---|---|
| post_id | Yes | Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| reaction | Yes | LinkedIn reaction type (a plain 'like' or an emoji is rejected by LinkedIn). | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true, which the description matches by describing a mutation ('Add'). It adds context: acts on behalf of the user, requires clear intent, and notes LinkedIn's rejection of plain 'like'/emoji. This goes beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with no filler. The primary action is stated first, followed by a critical usage condition. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and the schema covers all parameters thoroughly. The description adds the intent-clarity requirement and reaction validation note. No output schema exists, so return-value explanation is not required. Slight gap: no mention of authentication or account prerequisites, but these are implied by the platform context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with detailed descriptions for post_id, reaction, and account_id, including how to obtain IDs and avoid common mistakes. The tool description adds little beyond the schema, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Add'), a resource ('post'), and the on-behalf-of-user scope. The supported reaction values and the intent-clearance condition are explicit, clearly distinguishing it from sibling tools like linkedin_comment_on_post and linkedin_react_to_message.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a clear when-to-use condition: 'only when the user's intent to react is clear' and warns that plain 'like' or emoji is rejected. It doesn't explicitly name alternatives or when not to use, but the intent condition and reaction enum give practical guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_read_conversationLinkedIn: Read conversationARead-onlyIdempotentInspect
Read a LinkedIn private conversation plus recent messages. Use before replying so the agent understands prior context, commitments and tone.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID returned by conversation/inbox listing. Never pass a person name or provider user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry the safety profile (readOnlyHint=true, idempotentHint=true, destructiveHint=false), lowering the bar. The description adds that the tool returns conversation content plus recent messages and characterizes them as context-bearing ('commitments and tone'). It does not disclose how many messages are returned or whether reading affects read-receipt status, so it settles at baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero waste. The core action and scope are front-loaded in sentence one, and the usage context follows immediately in sentence two. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity tool (2 params, 1 required, no enums, no nested objects) with rich annotations and 100% schema coverage, the description is nearly complete: it covers the operation, the returned content at a high level, and the usage context. The only gap is that no output schema exists and 'recent messages' leaves the message-count/Time window unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema carries the full parameter burden: chat_id details acquisition ('Obtain with: provider list conversations/inbox chats -> chat.id'), URL visibility, and anti-patterns ('Never pass: person name, user_id, message_id'), while account_id explains multi-account disambiguation. Per the baseline rule, the description itself adds no parameter semantics beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read a LinkedIn private conversation') with a defined scope ('plus recent messages'). This distinguishes it from siblings like linkedin_list_conversations (which lists conversation metadata) and linkedin_send_message (which writes). An agent can tell what this tool does without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear usage context: 'Use before replying so the agent understands prior context, commitments and tone,' which positions it squarely in the read-context-then-respond workflow. However, it does not explicitly name alternative tools or state when not to use it, so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_recruiter_get_applicantLinkedIn: Recruiter get applicantARead-onlyIdempotentInspect
Get one Recruiter applicant. Required chain: list/select Hiring Project -> project.id -> list applicants -> applicant.id. applicant_id is scoped to the selected project context.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| project_id | Yes | Exact LinkedIn Recruiter Hiring Project ID from linkedin_recruiter_list_projects. Never pass project name. | |
| applicant_id | Yes | Exact applicant profile ID returned by the corresponding applicants listing. Keep it paired with the Classic job_id or Recruiter project_id that produced it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds useful context about applicant_id being scoped to the selected project context, which goes beyond the structured annotations. However, it does not describe response contents or account/auth behavior, so the added behavioral insight is moderate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with no filler. The first sentence states the core purpose, and the second concentrates the essential workflow constraint. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The required navigation chain is fully specified, the schema covers parameter semantics thoroughly, and the scoping constraint is stated. The only gap is that no output schema exists and the description does not describe return values, but for a simple getter this is a minor omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents all three parameters with 100% coverage, including exact ID requirements and account_id disambiguation. The description reinforces the project/applicant ID relationship but adds little new per-parameter meaning, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get one Recruiter applicant.' The word 'one' distinguishes it from listing tools, 'Recruiter' distinguishes it from Classic LinkedIn tools, and 'applicant' distinguishes it from resume-specific fetches among the siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit required chain: list/select Hiring Project -> project.id -> list applicants -> applicant.id. This tells an agent exactly when in the workflow the tool is valid. It does not explicitly name alternatives or exclusions, but the workflow guidance is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_recruiter_get_applicant_resumeLinkedIn: Recruiter get applicant resumeARead-onlyIdempotentInspect
Retrieve a Recruiter applicant resume. Resolve exact project_id and applicant_id first; never use candidate name or LinkedIn URL as applicant_id.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| project_id | Yes | Exact LinkedIn Recruiter Hiring Project ID from linkedin_recruiter_list_projects. Never pass project name. | |
| applicant_id | Yes | Exact applicant profile ID returned by the corresponding applicants listing. Keep it paired with the Classic job_id or Recruiter project_id that produced it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior. The description adds valuable operational context: IDs must be exact, resolved values, and name/URL inputs are invalid for applicant_id. This goes beyond the annotations and helps prevent retrieving the wrong resume.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences: the first states the action, the second gives the essential safety constraint. No filler or repetition; every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, idempotent tool with only three parameters and a fully described schema, the definition is functionally complete. It covers prerequisites, ID pairing, invalid inputs, and the core action. No output schema exists, but the tool name and description make the returned resource sufficiently clear.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already documents each parameter thoroughly. The description adds a meaningful extra constraint—never use candidate name or LinkedIn URL as applicant_id—and emphasizes resolving IDs first. This adds value beyond the schema, though it is partially redundant.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Retrieve a Recruiter applicant resume.' The 'Recruiter' qualifier distinguishes it from the sibling linkedin_classic_get_applicant_resume, and the added constraint about not using candidate name or LinkedIn URL gives precise scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly instructs the agent to resolve exact project_id and applicant_id before calling, and explicitly forbids using candidate name or LinkedIn URL as applicant_id. It does not explicitly compare alternatives like linkedin_classic_get_applicant_resume or linkedin_recruiter_get_applicant, but the provided preconditions are clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_recruiter_list_applicantsLinkedIn: Recruiter list applicantsARead-onlyIdempotentInspect
List applicants from a LinkedIn Recruiter Hiring Project talent pool. Resolve project_id first. Recruiter applicants are project-scoped; never substitute a Classic job_id for project_id.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | Opaque next_cursor returned by previous page; never invent. | |
| filters | No | Recruiter talent-pool applicant filters such as sort/seniority/current-company using documented V2 enums/parameter IDs. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| project_id | Yes | Exact LinkedIn Recruiter Hiring Project ID from linkedin_recruiter_list_projects. Never pass project name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only and non-destructive/idempotent behavior; the description adds the project-scoped constraint and the resolve-first prerequisite. This is useful but not a rich disclosure of pagination, return shape, or provider-side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences place the action first, state the prerequisite, and add the critical warning without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The most important contextual trap—project_id versus Classic job_id—is explicitly addressed, and the schema covers account disambiguation and pagination. Given five parameters and no output schema, a brief note on return data would push this to a 5.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, so the schema already explains project_id, cursor, filters, and account_id. The description reinforces project_id exactness but does not add new meaning for limit, cursor, filters, or account selection.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a resource ('LinkedIn Recruiter Hiring Project talent pool'), and explicitly contrasts Recruiter applicants with Classic job_ids, making it easy to distinguish from linkedin_classic_list_job_applicants.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells the agent to resolve project_id first and warns never to substitute a Classic job_id, which is a clear when-not signal. It stops short of naming the alternative tool explicitly, so it misses a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_recruiter_search_peopleLinkedIn: Recruiter search peopleARead-onlyIdempotentInspect
Search LinkedIn Recruiter candidates using the user's Recruiter-capable account. Use for candidate sourcing, recruiting projects/talent pools and Recruiter-specific filters. Resolve filter IDs with linkedin_get_search_parameters(product='recruiter') when necessary. This read tool cannot save searches or custom filters.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| save_search | No | ||
| save_custom_filter | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly/idempotent/openWorld/non-destructive, and the description adds value beyond them by disclosing the Recruiter-capable-account authorization requirement and the inability to persist searches or custom filters. It does not describe result shape or pagination, which is the main remaining gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core action and account constraint, then usage scope, then the helper and the capability limitation. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read tool with annotations plus a partially documented schema and no output schema, the description is nearly sufficient: it covers purpose, scope, account requirement, and the unsupported single-shot save behavior. It could add a note on result return/pagination, but nothing critical for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is low (33%), and the two save_* properties carry an opaque 'not: {}' schema that actively conveys nothing. The description compensates by explaining that saving searches/custom filters is unsupported and by pointing at linkedin_get_search_parameters for filter IDs, while account_id is already well documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Search LinkedIn Recruiter candidates') and qualifies the required account type ('Recruiter-capable account'), which cleanly separates it from the general-persona siblings like linkedin_search_people, linkedin_sales_navigator_search_people, and linkedin_search_from_url.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use contexts (candidate sourcing, recruiting projects/talent pools, Recruiter-specific filters) and a when-not capability constraint ('cannot save searches or custom filters'), plus the prerequisite tool for filter IDs. It stops short of explicitly naming the non-Recruiter alternatives to use instead, so it is clear but not fully routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_remove_connectionLinkedIn: Remove connectionADestructiveInspect
Remove an existing LinkedIn relation/connection. Resolve the exact provider user_id first. This changes the user's network and requires explicit intent.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Exact provider user ID returned by the relevant profile/contact resolver; never a display name or profile URL. For LinkedIn, use the stable system ID. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false. The description adds context beyond this by stating the impact ('changes the user's network') and the requirement of explicit intent. This is useful behavioral context that is not in the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with no filler. The first sentence states the action, the second gives the key precondition, and the third communicates the impact and intent requirement. Every sentence earns its place and the purpose is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two parameters, full schema coverage, and annotations covering safety/destructive behavior, the description provides the essential purpose, precondition, and consequence. No output schema exists, but the description still gives enough operational context for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema fully documents both parameters. The main description adds only a sequence hint ('Resolve the exact provider user_id first'), which is minor. Baseline of 3 is appropriate since the schema carries the semantic weight.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Remove an existing LinkedIn relation/connection.' This clearly distinguishes it from related sibling tools like linkedin_send_invitation, linkedin_accept_invitation, and linkedin_unfollow_user. The purpose is immediately understandable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for use by instructing to 'Resolve the exact provider user_id first' and warning that the action 'changes the user's network and requires explicit intent.' It does not explicitly name alternatives or exclusions, but it sets the appropriate precondition and intent requirement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_reply_to_commentLinkedIn: Reply to commentADestructiveInspect
Reply DIRECTLY to one exact LinkedIn comment, not create a new top-level comment. Required chain from human reference: resolve post -> post.id -> list comments -> comment.id -> optionally read replies -> reply. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Final reply text explicitly requested/approved by the user. | |
| post_id | Yes | Exact post ID from post search/list. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| comment_id | Yes | Exact comment ID from comments of the resolved post. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare destructiveHint=true and readOnlyHint=false, so the write nature is covered. The description adds that it replies 'DIRECTLY' and not a top-level comment, which is more about purpose than side effects. It doesn't disclose what happens on success (e.g., whether a reply object is returned) or any failure modes. Given the annotations cover the safety profile, the description adds moderate value but not rich behavioral detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured: it front-loads the core purpose, then presents the required chain, then gives ID-specific guidance. It is dense with actionable information and avoids filler. However, it repeats the ID guidance that already exists in the schema, which adds redundancy. Still, given the tool's complexity, the length is justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is complex, requiring exact IDs from a multi-step chain. The description covers the full chain, how to obtain each ID, and what not to pass. It also includes the optional account_id in the schema (though not in the description). No output schema exists, but for a write operation that's acceptable. The description lacks explicit error handling or success indication, but given the complexity, it is substantially complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema already contains the exact guidance for post_id and comment_id, duplicating the description's text. The description adds the overall resolution chain, but for individual parameters it provides no new information beyond the schema. The account_id parameter is not mentioned in the description at all, but the schema covers it. Thus, the description adds minimal value over the schema, earning the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: to reply directly to one exact LinkedIn comment, explicitly distinguishing it from creating a new top-level comment. It names the verb 'reply' and the resource 'comment', and differentiates from the sibling linkedin_comment_on_post by its 'not create a new top-level comment' clause. This is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: it gives the required resolution chain (resolve post -> list comments -> reply), states what to obtain and how (via linkedin_search_posts, linkedin_list_user_posts, etc.), and explicitly forbids passing post text, author user ID, or URL unless a resolver accepts them. It also distinguishes from the top-level comment tool. This is thorough and leaves no ambiguity about when to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_resolve_companyLinkedIn: Resolve companyARead-onlyIdempotentInspect
Resolve a human company name to LinkedIn company results and exact company IDs. Use before employee searches, company profile reads or company mentions. LinkedIn company mentions require the numeric company ID; the slug from /company/google/ is not sufficient. LinkedIn company ID: Provider numeric/company ID. For mentions LinkedIn requires numeric company ID, not the company URL slug. Obtain with: linkedin_search_companies -> selected result.id; linkedin_get_company after resolving a company Never pass: linkedin.com/company/google URL, company slug such as google, company name.
| Name | Required | Description | Default |
|---|---|---|---|
| filters | No | ||
| keywords | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| save_search | No | ||
| save_custom_filter | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds genuinely non-obvious context: LinkedIn mentions require the numeric ID, the /company/google/ slug is insufficient, and which input forms are invalid. It does not cover auth, rate limits, or result shape, but the ID-vs-slug constraint is real added value beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence is well front-loaded, but the remainder repeats the same numeric-ID-vs-slug point three times and includes a schema-like fragment ('LinkedIn company ID: Provider numeric/company ID') that reads like leftover template text rather than guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description should describe what comes back; it only gestures at 'company results and exact company IDs' without structure or fields. Annotations cover the safety profile and the ID constraint is stated, so the core need is met, but the return shape and the bare 'filters' object remain unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, so the description must carry the load, but it never explains 'filters', 'save_search' or 'save_custom_filter'. Worse, the 'Never pass: ... company name' instruction directly muddles the semantics of the required 'keywords' parameter, which the first sentence implies is a human company name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: 'Resolve a human company name to LinkedIn company results and exact company IDs.' It also distinguishes itself from siblings by naming linkedin_search_companies and linkedin_get_company as the routes to the ID, so an agent can place this tool in the LinkedIn lookup flow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use before employee searches, company profile reads or company mentions' gives a clear triggering context, and the 'Obtain with:' line names the alternative tools. However, pointing to linkedin_search_companies for the ID is slightly confusing for a tool whose whole job is resolving an ID, and no explicit when-not-to-use case is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_resolve_my_postLinkedIn: Resolve my postARead-onlyIdempotentInspect
Resolve a user's description such as 'my latest post' into exact post IDs before comments/reactions/edit/delete. Returns the account owner's posts; choose the matching post and reuse result.id. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description adds valuable behavioral detail: it returns the account owner's posts, requires the agent to choose the matching post and reuse result.id, and clarifies that the post ID must be the exact provider/Unipile ID, often base64-style for LinkedIn. This materially helps the agent understand the resolution workflow and what to do with the result. No contradiction with annotations is present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and then moves through the result contract, ID format, acquisition sources, and input exclusions in a logical, compact sequence. Every sentence carries actionable information and there is no filler or tautological repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a resolver with no output schema, the description gives a clear result contract ('Returns the account owner's posts; choose the matching post and reuse result.id'), the expected ID format, and the exact ID sources. The main gap is that the offset parameter is left unexplained, and the instagram_list_user_posts source is slightly surprising in a LinkedIn-specific tool, but overall the agent has enough to call and use the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50%: account_id is well documented in the schema, but offset has no description. The tool description does not compensate by explaining offset or otherwise enriching the parameters. The 'Never pass' guidance is helpful but concerns non-parameters, while offset's pagination semantics remain undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it resolves a user's descriptive phrase such as 'my latest post' into exact post IDs, and clearly scopes it to the account owner's posts. It distinguishes itself from sibling resolvers like linkedin_resolve_company, linkedin_resolve_person, and social_resolve_comment by naming the target ('my post') and the downstream actions it feeds (comments/reactions/edit/delete).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit context for when to call the tool ('before comments/reactions/edit/delete') and strong input exclusions ('Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it'). It also tells the agent how to obtain valid IDs via linkedin_search_posts, linkedin_list_user_posts, and instagram_list_user_posts. However, it does not explicitly name an alternative for the case where an exact post ID is already known.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_resolve_personLinkedIn: Resolve personARead-onlyIdempotentInspect
Resolve a human description (name, role, employer, location keywords) to LinkedIn people and their stable system IDs before an action. Use when the user says 'message Sarah at Acme' or 'connect with the CTO of X' rather than providing an ID. If multiple plausible results remain, show/disambiguate them before any write. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| filters | No | Optional already-resolved LinkedIn search filters. If a filter needs a provider parameter ID, resolve it first with linkedin_get_search_parameters. | |
| keywords | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| save_search | No | ||
| save_custom_filter | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, openWorld, non-destructive), and the description adds genuinely useful behavior: it can return multiple plausible matches and must be disambiguated before any write. It also warns which value formats are invalid to pass. It does not describe ranking or result ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose and the trigger example before the ID mechanics. The trailing ID-sourcing block ('Obtain with: ... Never pass: ...') is dense and somewhat tangential to resolving, but each sentence carries usable instruction rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and a nested 'filters' object, the description should say more about what comes back (a ranked candidate list? how many?) and how 'limit' defaults. It hints at multiple results via the disambiguation rule but never specifies the return shape, leaving a real gap for a 6-param tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33%, so the description must compensate. It usefully explains what 'keywords' should contain and clarifies the ID format, but it says nothing about 'limit', 'save_search', or 'save_custom_filter' (which are schema-only, not-null constraints), leaving real ambiguity at low coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: resolves a free-text human description (name, role, employer, location) into LinkedIn people and stable system IDs, and clarifies it runs 'before an action'. It does not explicitly differentiate itself from closely-named siblings such as linkedin_search_people or linkedin_resolve_company, so an agent must infer the split.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete trigger ('Use when the user says message Sarah at Acme or connect with the CTO of X rather than providing an ID') and a disambiguation rule ('If multiple plausible results remain, show/disambiguate them before any write'). It does not name the sibling searches it should replace, so alternative selection is left partly implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_search_companiesLinkedIn: Search companiesARead-onlyIdempotentInspect
Search LinkedIn companies from the user's own account. Use to find a company ID/profile before looking for employees, checking network relationships or performing a people search scoped to that company.
| Name | Required | Description | Default |
|---|---|---|---|
| industry | No | ||
| keywords | No | ||
| location | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| save_search | No | ||
| has_job_postings | No | ||
| save_custom_filter | No | ||
| is_employing_relations | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered without description help. The description adds that the search runs against the user's own account, which is modest extra context, but says nothing about result volume, pagination, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, zero filler, with the primary action front-loaded and the workflow rationale immediately after. Nothing redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter, no-output-schema search tool, the description covers purpose and workflow but leaves the filter surface unexplained and gives no sense of what results contain or how the account_id ambiguity is resolved in practice. Adequate but with clear gaps given the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 13% (essentially account_id alone), so the description carries the burden of explaining industry, keywords, location, has_job_postings, is_employing_relations and the two oversized save_search/save_custom_filter params. It mentions none of them, leaving most filters undefined.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (search LinkedIn companies) plus the account scope it runs under, so the agent knows exactly what it returns. It does not differentiate itself from close siblings such as linkedin_get_company or linkedin_resolve_company, which also produce a company identity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete when-to-use: obtain a company ID/profile as a prerequisite for employee lookup, network checks, or a company-scoped people search. It stops short of naming an alternative tool or an exclusion condition (e.g. when to use get_company/resolve_company instead).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_search_from_urlLinkedIn: Search from URLARead-onlyIdempotentInspect
Run a native LinkedIn search from a LinkedIn search URL. Use when the user pastes a linkedin.com/search/results/... URL, Sales Navigator search URL or Recruiter search URL and wants the same filters/results available to the agent.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| product | Yes | classic | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the behavioral nuance that the search uses the URL's filters and makes results available to the agent, which is useful context. However, it does not disclose potential limitations like rate limits or authentication specifics, but those are not required given the annotation coverage. The description adds some value beyond the annotations, so a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero waste. The purpose is front-loaded, and the usage condition follows immediately. Every word contributes to understanding the tool's role and trigger.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only tool with a simple input (URL and product type), the description adequately covers the core use case: it states what it does and when to use it, and the phrase 'same filters/results available to the agent' implies the output. There is no output schema, but the description does not need to elaborate return formats. The account_id parameter is explained in the schema, so the description is complete enough for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33% (only account_id has a description). The description mentions the URL types but does not explicitly explain the 'url' or 'product' parameters. It implies that the product parameter corresponds to the URL type, but it never states that connection. The account_id parameter is not mentioned in the description at all, though it is well-documented in the schema. Given the low schema coverage, the description should compensate, but it fails to do so beyond indirect hints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Run a native LinkedIn search from a LinkedIn search URL' – a specific verb (run) and resource (search URL), and it immediately differentiates itself from sibling search tools (e.g., linkedin_search_people) by grounding the action in a URL. It enumerates the three URL types (classic, Sales Navigator, Recruiter), making the tool's scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence explicitly states the trigger condition: 'Use when the user pastes a linkedin.com/search/results/... URL, Sales Navigator search URL or Recruiter search URL and wants the same filters/results available to the agent.' This gives clear when-to-use guidance. It does not explicitly name alternatives for the when-not case, but the implicit contrast with other search tools is sufficient for an agent to infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_search_jobsLinkedIn: Search jobsARead-onlyIdempotentInspect
Search LinkedIn jobs with the user's own account. Use for job discovery by keywords, title, company, location, seniority, employment status or workplace type.
| Name | Required | Description | Default |
|---|---|---|---|
| keywords | No | ||
| job_title | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| date_posted | No | ||
| save_search | No | ||
| primary_location | No | Location parameter ID from linkedin_get_search_parameters(type=LOCATION); not a location name. | |
| save_custom_filter | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/openWorldHint, so the safety profile is covered. The description usefully adds that the search runs under the user's own account, but it is silent on two opaque parameters (save_search, save_custom_filter) that imply a persistent side effect, and says nothing about pagination or result limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the verb, resource and account scope front-loaded and the filter dimensions following. Nothing is repeated and no filler is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter, zero-required search tool with no output schema, the description covers purpose and filter dimensions but leaves the two save-related parameters and pagination behavior unaddressed. It is adequate to attempt a call but incomplete for confident invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at only 29%, the description does add filter semantics beyond the schema by naming company, seniority, employment status and workplace type (none of which appear as explicit properties). However it never explains the untyped save_search/save_custom_filter arguments or date_posted, leaving several parameters undocumented in both places.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Search LinkedIn jobs') and scopes it to the user's own account, which distinguishes it from recruiter/Sales Navigator searches. It does not, however, distinguish itself from sibling read tools like linkedin_list_job_postings or linkedin_get_job_posting, so it stops short of full sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use for job discovery by keywords, title, company, location, seniority, employment status or workplace type' gives a clear usage context. There is no when-not guidance, no mention of prerequisites (e.g. needing a location ID from linkedin_get_search_parameters), and no pointer to alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_search_peopleLinkedIn: Search peopleARead-onlyIdempotentInspect
Search LinkedIn Classic people with the user's own LinkedIn account. Use to find a person/provider user ID from a name, title, employer, location, industry, keywords or network distance. When the next requested action is message/invitation, take the chosen result's id and pass it to the action tool; never pass a profile URL directly to an action requiring user_id. Some filters require IDs; resolve them first with linkedin_get_search_parameters.
| Name | Required | Description | Default |
|---|---|---|---|
| cursor | No | ||
| school | No | ||
| service | No | ||
| industry | No | ||
| keywords | No | ||
| location | No | LinkedIn location IDs; call linkedin_get_search_parameters when starting from a human location name. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| save_search | No | ||
| followers_of | No | ||
| past_company | No | ||
| connections_of | No | ||
| current_company | No | LinkedIn company IDs, not company names, when the provider requires IDs. | |
| network_distance | No | ||
| profile_language | No | ||
| advanced_keywords | No | ||
| save_custom_filter | No | ||
| open_to_volunteering | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld, so the safety profile is covered. The description adds real behavioral context: it operates on the user's own account, some filters require resolved IDs, and result IDs must be forwarded (not URLs) to action tools. It omits pagination behavior despite a cursor parameter, so it is not a full 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the action and scope, followed by the ID-resolution prerequisite and the downstream hand-off rule. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 17-parameter tool with no output schema, the description covers the critical call-chain (search -> take id -> action tool) and the ID-resolution requirement. It still leaves pagination (cursor) and roughly half the filter parameters unexplained, so it is strong but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 18% across 17 parameters, so the schema does little heavy lifting. The description names several searchable facets (name, title, employer, location, industry, keywords, network distance) and the 'filters require IDs' rule, partially compensating, but leaves cursor, school, service, followers_of, connections_of, network distance encoding, and save_* undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource and ties it to the correct variant ('LinkedIn Classic people'), which distinguishes it from linkedin_recruiter_search_people and linkedin_sales_navigator_search_people in the sibling list. Also states whose account is used ('the user's own LinkedIn account').
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('find a person/provider user ID from a name, title, employer, location...'), an explicit downstream workflow rule (pass the chosen result's id to the action tool, never a profile URL to a tool requiring user_id), and an explicit prerequisite alternative (resolve filters first with linkedin_get_search_parameters). This is well beyond typical guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_search_postsLinkedIn: Search postsARead-onlyIdempotentInspect
Search LinkedIn posts using the user's own account. Use to find a post before reading comments, checking reactions or replying. Returns post IDs required by comment/reaction tools.
| Name | Required | Description | Default |
|---|---|---|---|
| sort_by | No | ||
| keywords | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| date_posted | No | ||
| save_search | No | ||
| content_type | No | ||
| save_custom_filter | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description adds genuine context (it operates on the user's own account, and returns post IDs consumed by comment/reaction tools) but says nothing about pagination, result limits, or result ordering despite sort_by existing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each doing distinct work: what it is, when to use it, and what it returns. The identity sentence is front-loaded and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The chaining story (search first, then comment/react tools) is complete, but for a 7-parameter tool with 14% schema coverage and no output schema, the description omits any parameter guidance on filtering, sorting, or date scoping, which is where an agent most needs help.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 14% (only account_id is documented, and it is documented in the schema, not the description). Six of seven parameters (keywords, sort_by, date_posted, content_type, save_search, save_custom_filter) get no meaning from either source, and the description does not compensate at all.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Search LinkedIn posts") and scopes it to the user's own account, which separates it from company-page search paths. It does not name the nearest siblings (linkedin_get_post, linkedin_list_user_posts, linkedin_resolve_my_post), so differentiation is left partly to inference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear chain of use: "Use to find a post before reading comments, checking reactions or replying," which routes the agent into the comment/reaction tools. No explicit when-not or exclusion cases are stated, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_select_contractLinkedIn: Select contractAInspect
Select a LinkedIn Sales Navigator/Recruiter premium contract. First call linkedin_list_contracts and reuse exact contract.id. Do not pass product name or inbox_id. LinkedIn premium contract ID: Exact Sales Navigator/Recruiter contract id. Obtain with: linkedin_list_contracts -> contract.id Never pass: inbox_id, product name.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| contract_id | Yes | Exact premium contract ID returned by linkedin_list_contracts -> contract.id. LinkedIn premium contract ID: Exact Sales Navigator/Recruiter contract id. Obtain with: linkedin_list_contracts -> contract.id Never pass: inbox_id, product name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and idempotentHint=false, indicating a state-changing operation. The description adds behavioral context by explaining the dependency on a prior list call and explicitly forbidding certain parameters, which helps the agent understand the expected preconditions. It does not contradict the annotations and provides useful operational details beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the primary action, followed by the prerequisite and exclusions. There is some redundancy with the schema descriptions (repeating the contract ID source), but it remains efficient and does not waste words. The structure is logical: purpose first, then usage guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple selection tool with only two parameters, the description fully covers what is needed: the action, the prerequisite call, the exact ID source, and explicit exclusions. The account_id parameter is thoroughly explained in the schema, and the description ensures the agent knows not to guess when multiple accounts exist. No essential information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for both parameters, with the contract_id description already repeating the same guidance about obtaining it from linkedin_list_contracts and the account_id description being quite detailed. The tool description adds no new semantic meaning beyond what the schema already contains, so it does not elevate the score beyond the baseline for full coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Select') and resource ('LinkedIn Sales Navigator/Recruiter premium contract'), clearly distinguishing the action from list/get operations. It also explicitly instructs to first call linkedin_list_contracts and reuse the exact contract.id, which clarifies the intended workflow. This differentiates it from any potential sibling selection tool and makes the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance by requiring a prerequisite call to linkedin_list_contracts and mandating the reuse of the exact contract.id. It also gives clear exclusions ('Do not pass product name or inbox_id'), preventing common misuse. This is comprehensive usage direction beyond what the schema alone provides.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_send_invitationLinkedIn: Send invitationADestructiveInspect
Send a LinkedIn connection/relation request from the user's own account. Requires a provider user_id, not a profile URL. If the user supplied a URL or name, FIRST call linkedin_get_profile or linkedin_search_people and use the returned id. Include a note only when explicitly requested or clearly provided by the user.
| Name | Required | Description | Default |
|---|---|---|---|
| message | No | ||
| user_id | Yes | Stable LinkedIn provider user ID obtained from linkedin_get_profile/search_people. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry destructiveHint=true and idempotentHint=false, so the mutation risk is known. The description adds that the request is sent from the user's own account and that a note should only be included when explicitly requested, but does not disclose consequences such as duplicate invitations, rate limits, or errors when already connected.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler. The core action is front-loaded, the key ID requirement is stated immediately, and the note policy is a concise final sentence. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description plus schema covers the essential preconditions, ID resolution workflow, and optional account disambiguation. It does not describe return values or failure modes, but given no output schema and the presence of destructive/idempotent annotations, the missing information is not critical for invoking the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67%, and the description adds meaning beyond the schema: it clarifies that user_id must be a provider ID, not a URL, and constrains the 'message' parameter by saying a note should only be included when explicitly requested or clearly provided. account_id is already well documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('send') and resource ('LinkedIn connection/relation request'), and clarifies it acts from the user's own account. This distinguishes it from sibling tools like linkedin_accept_invitation or linkedin_send_message.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states the required input form ('provider user_id, not a profile URL') and gives a direct pre-call workflow: if only a URL/name is available, first call linkedin_get_profile or linkedin_search_people. It does not explicitly name alternatives like linkedin_send_message for already-connected users, but the context is fairly clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_send_messageLinkedIn: Send messageADestructiveInspect
Send a message in an EXISTING LinkedIn chat. Requires chat_id, normally obtained from linkedin_list_conversations. Use only when the user has clearly asked to send/approved the final text.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| chat_id | Yes | Exact chat/conversation ID returned by conversation/inbox listing. Never pass a person name or provider user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, destructiveHint=true), the description adds the critical behavioral safeguard that the user must have clearly asked or approved the final text. This is a meaningful behavioral guideline not present in structured data, ensuring the agent understands this is a real-world, consent-required action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each with a distinct purpose: core action, prerequisite, and approval condition. The description is front-loaded with the primary action and contains no filler, making it quick for an agent to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 3-parameter tool with annotations and no output schema, the description covers the essential context: what the tool does, how to obtain the required chat_id, and the approval requirement. It doesn't describe the return value, but that's not necessary given the absence of an output schema and the simplicity of the action.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds value by specifying that chat_id normally comes from linkedin_list_conversations, supplementing the already detailed schema description for chat_id. The phrase 'final text' also gives a slight hint about the text parameter's role. With 67% schema coverage, this partial compensation is adequate, though text itself could use more explicit semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Send a message') on a specific resource ('an EXISTING LinkedIn chat'), and the 'EXISTING' qualifier clearly distinguishes it from conversation-starting siblings like linkedin_start_conversation. It also names the prerequisite chat_id and its typical source, leaving no ambiguity about what this tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an explicit when-to-use condition: 'Use only when the user has clearly asked to send/approved the final text.' It also instructs that chat_id is normally obtained from linkedin_list_conversations, giving a clear workflow. It does not explicitly name alternatives or exclusions, but the 'EXISTING' constraint implicitly steers away from new-chat tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_start_conversationLinkedIn: Start conversationADestructiveInspect
Start a new LinkedIn conversation and send a message. Requires the stable LinkedIn provider user_id. IMPORTANT: if the user gives a LinkedIn URL, name or search criteria, first call linkedin_get_profile or linkedin_search_people, extract the returned user id, then call this tool. Do not put a LinkedIn URL into linkedin_user_id.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| inbox_id | No | LinkedIn inbox to start from (default CLASSIC_PRIMARY). Use a Sales Navigator/Recruiter inbox ID from linkedin_list_inboxes for InMail-style messages. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| linkedin_user_id | Yes | Stable provider user id resolved by linkedin_get_profile/search_people; not a linkedin.com URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnlyHint=false, destructiveHint=true, and idempotentHint=false, so the mutation profile is known. The description adds a useful input precondition and URL warning, but it does not disclose additional side effects such as InMail credit usage, irreversibility, or conversation creation behavior beyond what the annotations imply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: purpose first, then the critical precondition, then the warning. Every sentence earns its place without filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The workflow for resolving user IDs is complete and the schema fills in account and inbox behavior. It lacks an explicit return-value note since there is no output schema, and it does not route around sibling messaging tools, but the invocation path is otherwise well covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 75%, so the schema already documents linkedin_user_id, inbox_id, and account_id in detail. The description reinforces the linkedin_user_id resolution rule, but it adds nothing about the text parameter, which has no schema description, and no new semantics for inbox_id or account_id beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Start a new LinkedIn conversation and send a message') and a clear resource, so an agent can tell it is a messaging mutation tool. It doesn't explicitly contrast with siblings like linkedin_send_message or linkedin_start_conversation_from_inbox, so sibling differentiation is incomplete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit workflow: if the user provides a URL, name, or search criteria, first call linkedin_get_profile or linkedin_search_people, extract the user id, then call this tool, and never pass a URL to linkedin_user_id. It does not say when to prefer linkedin_send_message or linkedin_start_conversation_from_inbox, so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_start_conversation_from_inboxLinkedIn: Start conversation from inboxADestructiveInspect
Start a LinkedIn Classic, Sales Navigator or Recruiter conversation from an explicit inbox. Resolve recipient user IDs first and obtain inbox_id with linkedin_list_inboxes. For Sales Navigator include the required subject in specifics; Recruiter may require subject and signature. Supports one-to-one or group recipients and attachments.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| text | Yes | ||
| inbox_id | Yes | Exact LinkedIn inbox ID returned by linkedin_list_inboxes. Preserve Classic/Sales Navigator/Recruiter selection; never pass contract_id or product name. Inbox ID: Provider inbox/product inbox identifier. LinkedIn Classic may use CLASSIC; premium products expose their own inbox IDs. Obtain with: linkedin_list_inboxes -> inbox.id Never pass: contract_id unless returned as the inbox id, guessing SALES_NAVIGATOR or RECRUITER. | |
| specifics | No | ||
| users_ids | Yes | One exact provider user ID for a direct chat, or exact provider user IDs for a group; resolve every recipient first. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| attachments | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a mutating, destructive operation, so the description does not need to restate that. It adds value by disclosing that Sales Navigator and Recruiter have specific subject/signature requirements, which is behavioral context beyond the annotation flags. No contradiction with annotations is present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no fluff. It front-loads the core purpose and packs in the key operational steps (resolve users, get inbox) and product-specific nuances efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with 7 parameters, nested objects, and no output schema, the description is relatively brief. It covers the main flow but omits details on return values, error conditions, or the semantics of optional parameters like 'name' and 'attachments.' It provides a functional overview but not complete coverage for an agent to use all parameters confidently.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is low (43%), and the description partially compensates by explaining that inbox_id comes from linkedin_list_inboxes and users_ids must be resolved. It also mentions specifics for subject/signature. However, it does not clarify the 'text' or 'name' parameters, nor does it detail the attachments structure, leaving gaps given the low schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Start') and resource ('conversation') with the key qualifier 'from an explicit inbox,' which distinguishes it from sibling tools like linkedin_start_conversation. It also mentions the supported product types (Classic, Sales Navigator, Recruiter) and capabilities (one-to-one, group, attachments), making the purpose immediately clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit prerequisites: resolve recipient user IDs and obtain inbox_id via linkedin_list_inboxes. It also gives product-specific guidance (Sales Navigator requires subject, Recruiter may require subject and signature). However, it does not explicitly contrast with linkedin_start_conversation or state when to use this tool instead, so it lacks a clear exclusion clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_submit_company_member_otpLinkedIn: Submit company member OTPAInspect
Complete LinkedIn company-member verification. Reuse the same email and exact challenge_id returned by linkedin_verify_company_member_email, and submit only the real user-provided code; never invent or loop over codes.
| Name | Required | Description | Default |
|---|---|---|---|
| code | Yes | Actual verification code received by the user. Never invent. | |
| Yes | |||
| product | Yes | classic | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| company_id | Yes | Exact LinkedIn company ID from company search/profile resolution; never use company name or slug unless a resolver explicitly converts it. | |
| challenge_id | Yes | Exact challenge_id returned by linkedin_verify_company_member_email. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With only generic annotations available, the description adds valuable behavioral guardrails: the submission must be bound to the prior challenge_id/email, and code guessing or looping is disallowed. This is especially important because the annotations already mark the operation as non-read-only and non-idempotent. The description does not disclose error/retry behavior, but it provides the most critical behavioral constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense sentence that front-loads the purpose and then lists the two most important constraints. Every clause earns its place, and there is no filler or repetition of obvious information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter verification-completion tool with no output schema, the description plus parameter schema covers the essential calling contract: required fields, the source of challenge_id, and the prohibition on guessing codes. The main gap is the lack of response/error semantics, but the invocation guidance is otherwise sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool description adds cross-parameter semantics beyond the schema: email must be the same email used before, challenge_id must be the exact value returned by the prior tool, and code must be the real user-provided value. This is operationally important and not fully inferable from individual schema fields. The unmentioned product and account_id parameters are already reasonably documented by the enum, default value, and account_id description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Complete LinkedIn company-member verification', which names a specific verb and resource. The title explicitly says 'Submit company member OTP', and the workflow relationship to linkedin_verify_company_member_email is clear, so the agent can distinguish this tool from its sibling without deeper inspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the precondition and sequence explicit: reuse the same email and exact challenge_id from linkedin_verify_company_member_email. It also gives a clear anti-pattern: never invent or loop over codes. It does not explicitly state when not to use this tool versus an alternative, but the two-step workflow dependency is strong enough to guide correct use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_unfollow_userLinkedIn: Unfollow userAInspect
Unfollow a LinkedIn user from the connected account. Resolve the exact provider user_id first.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Exact provider user ID returned by the relevant profile/contact resolver; never a display name or profile URL. For LinkedIn, use the stable system ID. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is not read-only, not idempotent, and not destructive. The description adds context by noting the action happens on the connected account and requires a prior resolution step. It does not disclose side effects or edge cases, but the annotation coverage carries much of the burden and the description is consistent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The primary action is front-loaded, and the only added sentence gives an actionable prerequisite. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple action with a fully described schema, the description plus parameter documentation is nearly complete. It covers the necessary resolution step and account context. The only minor omission is explicit guidance about expected outcomes or failure behavior, but that is not critical for this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema itself fully documents both user_id and account_id. The description contributes little beyond the instruction to resolve the provider user_id first, but the schema already provides rich detail on how to obtain it and what to never pass. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Unfollow a LinkedIn user from the connected account.' It clearly distinguishes the action from the sibling follow tool and makes the core operation immediately understandable. The added instruction to resolve the exact provider user_id also sharpens the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear prerequisite: 'Resolve the exact provider user_id first.' However, it does not state when to use this tool versus alternatives such as linkedin_remove_connection or linkedin_follow_user, nor does it explain under what conditions unfollowing is appropriate. The guidance is useful but incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_update_my_profileLinkedIn: Update my profileBInspect
Update supported fields of the user's own LinkedIn profile. Only pass fields explicitly requested by the user; provider support varies by field.
| Name | Required | Description | Default |
|---|---|---|---|
| bio | No | ||
| picture | No | ||
| summary | No | ||
| headline | No | ||
| location | No | ||
| specifics | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| background_picture | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare write semantics (readOnlyHint=false), non-idempotency, and non-destructiveness, so the safety profile is covered. The description adds one piece of genuine behavioral context — 'provider support varies by field,' implying partial/possibly-silent field application — but does not say what happens to unsupported fields, auth requirements, or whether a partial update is atomic.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler, and the load-bearing constraint ('only pass fields explicitly requested') is placed prominently. Nothing is redundant or padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter mutation tool with no output schema and near-zero schema documentation, the description is far too thin. It omits which fields are supported, how nested objects should be shaped, and what the agent should do when a field is unsupported — the exact gaps that matter before an agent calls a profile-write tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 13% (basically only account_id is documented in-schema), so the description is expected to compensate and does not. It never names the updatable fields (bio, headline, summary, location, picture, background_picture, specifics) nor explains the nested picture/background_picture or specifics structure, leaving 7 of 8 parameters semantically thin.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a clear verb+resource: 'Update supported fields of the user's own LinkedIn profile.' The 'own profile' scope distinguishes it from the many sibling read/search tools and from profile-viewing tools. It could be sharper about which fields are 'supported,' but the core purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives one real usage rule — 'Only pass fields explicitly requested by the user' — which constrains behavior and prevents unwanted edits. However, it names no alternatives (e.g., how it differs from other profile-writing flows) and offers no when-not-to-use guidance, so usage is implied rather than fully specified.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_verify_company_member_emailLinkedIn: Verify company member emailAInspect
Start LinkedIn company-member identity verification when a job/company action fails with insufficient permissions. Resolve company_id first and submit the actual verification email. Preserve the returned challenge_id for linkedin_submit_company_member_otp.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | Email address to submit for company-member verification. | ||
| product | Yes | classic | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| company_id | Yes | Exact LinkedIn company ID from company search/profile resolution; never use company name or slug unless a resolver explicitly converts it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false, confirming this is a mutation. The description adds the workflow detail of resolving company_id first and submitting the email, as well as preserving the challenge_id. However, it doesn't disclose potential side effects like sending an email to the user or requiring specific account permissions. With openWorldHint=true, providing more behavioral context (e.g., that this triggers an email) would be beneficial. The description is not contradictory but could be more transparent about the external effect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, three sentences, and front-loads the purpose and trigger. It efficiently packs critical instructions without fluff. However, it could be slightly more structured by separating the 'when' from the 'how', but it's already quite good. Minor deduction for density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (verification flow) and no output schema, the description adequately covers the essential steps, prerequisites (resolve company_id), and handoff to the next tool. It doesn't mention what happens after success (you'll receive a challenge_id) but that's implied by preserving it. The lack of response format is mitigated by the explicit instruction to preserve challenge_id. Overall, quite complete for an agent to execute correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75%, covering company_id, email, and account_id. The description adds crucial guidance for account_id (omit when one account, list when several, never guess) and company_id (use exact ID, never name/slug). This goes beyond basic schema descriptions. The product parameter is well-defined by enum. The description compensates well for the uncovered parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool starts LinkedIn company-member identity verification when a job/company action fails with insufficient permissions. It specifies the action, resource, and condition for use, effectively distinguishing it from sibling tools like linkedin_submit_company_member_otp which continues the flow.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool: when a job/company action fails with insufficient permissions. It also gives a clear workflow instruction: resolve company_id first, submit the verification email, and preserve the challenge_id for the next step (linkedin_submit_company_member_otp). This provides strong context and sequencing, though it doesn't mention when not to use it against all other Linkedin tools, but the trigger condition is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
linkedin_visit_profileLinkedIn: Visit profileAInspect
Report a LinkedIn profile visit using notify_visit_token returned by the resolved profile. The token is provider-issued and must not be replaced with user_id, profile URL or public identifier.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| notify_visit_token | Yes | Exact notify_visit_token returned by linkedin_get_profile_from_url/linkedin_get_profile for the profile being visited; never invent it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate the tool is not read-only (readOnlyHint=false) and has external side effects (openWorldHint=true). The description adds the provider-issued token constraint but does not elaborate on the side effects of 'reporting' a visit (e.g., notifications, rate limits, or data persistence). It does not contradict annotations, but it adds limited behavioral context beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core purpose and the critical token constraint. Every word earns its place; no filler or repetition. It is highly concise and well-structured for quick parsing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter tool with no output schema, the description is largely complete. It covers the essential purpose, the token origin, and the primary pitfall. It does not explain what happens on success or failure, but given the tool's simplicity and the rich schema descriptions, this is not a critical gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with both parameters well-described. The tool description adds a crucial semantic warning: the notify_visit_token must be the exact token from a resolved profile and must not be replaced with other identifiers. This goes beyond the schema's basic description and helps prevent misuse.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Report a LinkedIn profile visit' using a specific token. It identifies the resource (LinkedIn profile visit) and the required input (notify_visit_token), distinguishing it from profile-fetching siblings by emphasizing the token from a resolved profile. It avoids ambiguity and effectively sets it apart from tools like linkedin_get_profile.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool: after a profile has been resolved and a notify_visit_token is available. It explicitly warns against substituting user_id, profile URL, or public identifier, which is a key usage constraint. However, it does not name alternative tools or provide explicit 'when not to use' guidance, leaving the context slightly implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_connected_accountsConnected accountsARead-onlyIdempotentInspect
List the user's own accounts connected to Nilyo with provider, owner display name, identifier (LinkedIn public id, phone, email), connection status and reconnection hints. Use when the user asks what is connected, when several accounts of one provider exist and the user names one ("with Julia's LinkedIn"), or after a choose_account result. Nilyo never guesses between accounts: pick the entry matching what the user said and pass its unipile_account_id as account_id to the action tool.
| Name | Required | Description | Default |
|---|---|---|---|
| provider | No | Optional provider filter such as linkedin, whatsapp, instagram, google, outlook or imap. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context: it lists the fields returned and communicates the 'never guesses between accounts' policy, which helps an agent know how to map results to downstream actions. It doesn't detail pagination or limits, but those are not critical for this read-only list tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: the first sentence states the purpose and output content, the second gives concrete usage conditions, and the third provides the critical selection rule. Every sentence earns its place and no words are wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-optional-parameter, read-only list tool, this description is complete. It tells the agent what is returned, when to call it, and how to use the results (identify the matching account and pass unipile_account_id to the action tool). No output schema exists, but the description compensates by naming the key fields. There is no important missing context for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with the single optional provider parameter already described as 'Optional provider filter such as linkedin, whatsapp, instagram, google, outlook or imap.' The description adds no additional parameter-level semantics beyond mentioning 'provider' in the output list, so the schema carries the burden. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List') and resource ('the user's own accounts connected to Nilyo') and enumerates the returned attributes (provider, owner display name, identifier, connection status, reconnection hints). It clearly differentiates from related account tools by focusing on listing the user's own connected accounts rather than connecting, changing plans, or checking status.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage guidance is provided: use when the user asks what is connected, when multiple accounts of one provider exist and the user names one, or after a choose_account result. It also gives a strong behavioral rule: never guess between accounts, match the user's description and pass the unipile_account_id to the action tool. This is model-level routing guidance, not just a generic statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_add_reactionMessage: Add reactionADestructiveInspect
Add an emoji reaction to one exact WhatsApp, Instagram, Telegram or LinkedIn message (e.g. 👍, ❤️). Resolve chat/message first; keep chat_id + message_id paired. Use message_remove_reaction to withdraw it. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| reaction | Yes | Emoji to react with, e.g. 👍. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the description is not burdened to repeat those. The description adds context about pairing IDs for mutation tools and mentions the removal method, but does not detail side effects like notification changes or permanence beyond the removal option. It adds modest value without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat long but well-organized, with clear sections for Chat ID and Message ID. It front-loads the purpose and then provides necessary ID-resolution details. Some repetition exists between the description and schema text, but the structure is efficient and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with 4 parameters and no output schema, the description covers how to obtain IDs, keep them paired, and what not to pass. It also names the removal alternative. Missing details like error handling or rate limits are not critical for correct invocation. The description is sufficient for an agent to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents each parameter. However, the description adds actionable retrieval guidance (e.g., 'Obtain with: provider list conversations/inbox chats -> chat.id') and warns against passing certain values, which goes beyond the schema's bare 'Exact chat/conversation ID' phrasing. This is meaningful added value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Add an emoji reaction to one exact WhatsApp, Instagram, Telegram or LinkedIn message'. It also names the sibling tool message_remove_reaction for withdrawal, distinguishing this tool from the removal counterpart. No ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs to resolve chat/message first and keep chat_id + message_id paired, and names message_remove_reaction as the alternative for withdrawal. It also provides clear 'Never pass' guidance for each parameter, giving the agent concrete rules for correct usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_deleteMessage: DeleteADestructiveInspect
Delete one exact message. Resolve and verify chat/message first; destructive. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so the description adds value beyond those. It warns to 'Resolve and verify chat/message first', explains the uniqueness constraint (providers may only guarantee uniqueness inside a chat, so keep chat_id with message_id), and gives concrete sources for the IDs. It also explicitly lists 'Never pass' items, which prevents common errors. This is useful behavioral context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose ('Delete one exact message') and then gives a caution. However, it repeats the same 'Never pass' directives both in the main description and again inside the parameter descriptions, and the phrasing is somewhat redundant (e.g., 'Resolve and verify' and later 'In V2 always keep chat_id together'). While not excessively long, it could be tightened by removing duplicated guidance without losing substance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool with 3 parameters (2 required) and no output schema, the description provides thorough guidance: it explains how to obtain both IDs, the importance of pairing chat_id and message_id, and what not to pass. It also warns about the destructive nature. The only minor gap is that it does not describe the expected response (e.g., success/failure) or any post-deletion effects, but since there is no output schema and the task is straightforward, this is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%: the schema descriptions for chat_id and message_id already contain the full text about how to obtain them, the uniqueness note, and the 'Never pass' lists. The tool description essentially repeats this content, adding no new meaning beyond what the schema already provides. The account_id parameter is described only in the schema, and the description does not comment on it. Thus the description adds marginal value over the schema, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Delete one exact message.' It clearly states the action and the target (a message), and emphasizes precision ('exact') which distinguishes it from fuzzy or batch deletes. The warning 'Resolve and verify chat/message first; destructive' reinforces the specific scope. While it doesn't compare itself to siblings, the unique action (delete vs. edit, forward, react) is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: you delete a message after resolving and verifying the chat and message IDs, and it warns that deletion is destructive. It provides explicit instructions on how to obtain the correct IDs (via list conversations and read messages) and what not to pass. However, it does not explicitly name alternative tools or describe when not to use this tool (e.g., when you might want to edit rather than delete). The guidance is strong for execution but lacks explicit rutting vs. siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_editMessage: EditAInspect
Edit one previously sent message where supported. Recommended chain: resolve chat -> list messages -> message_get -> edit. Keep exact chat_id + message_id pair. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Final replacement message text explicitly requested/approved by the user. | |
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a mutation (readOnlyHint=false) and non-idempotent behavior. The description adds the 'where supported' caveat and the requirement to keep chat_id+message_id paired, which are useful behavioral constraints. However, it doesn't disclose potential side effects like edit time limits or failure modes, and much of the text repeats schema parameter descriptions rather than providing deep behavioral insight.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose and repetitive. The Chat ID and Message ID sections largely duplicate the schema parameter descriptions, and the two paragraphs repeat similar warnings. The first sentence and recommended chain are useful, but the rest could be condensed significantly. It is not front-loaded beyond the initial purpose, and the lengthy explanations hurt clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema and is a mutation. The description covers how to obtain IDs and the recommended chain, but it doesn't explain what the tool returns, what happens on failure, or any limitations like edit windows or irreversible effects. Given the openWorldHint and mutation nature, this is incomplete for an agent to understand the full effect of calling the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds extra guidance on how to obtain chat_id and message_id, and explicitly states 'Never pass: person name, user_id, message_id' for chat_id and 'Never pass: message text, chat_id, message ID without its chat context' for message_id. This goes beyond the schema by clarifying common mistakes and provenance, earning a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Edit one previously sent message where supported.' This is a specific verb+resource and distinguishes it from siblings like message_delete or message_forward. It also notes 'where supported' to indicate provider limitations, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a recommended chain: 'resolve chat -> list messages -> message_get -> edit,' which tells the agent when to use this tool. It also emphasizes keeping the chat_id+message_id pair and warns against passing person names or user_ids. However, it doesn't explicitly state when not to use this tool or name alternatives like message_forward or message_delete, so it's not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_forwardMessage: ForwardADestructiveInspect
Forward an existing message to another EXISTING chat. Resolve source chat + message and destination chat independently. target_chat_id is a chat ID, never recipient user_id/name. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. | |
| target_chat_id | Yes | Exact destination chat ID from message_resolve_chat/list conversations. Never pass a person name/user_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as a destructive, non-read-only mutation, and the description adds behavioral context by emphasizing the 'EXISTING chat' requirement and that providers may only guarantee message-ID uniqueness within a chat, so chat_id must be kept paired with message_id. This goes beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The top-level description is heavily redundant with the parameter descriptions, repeating the same Chat ID and Message ID paragraphs almost verbatim. While the front-loaded opening sentence is strong, the repetition across description and schema bloats the definition and makes it less scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with no output schema, the description covers the essential invocation concerns: where to get chat/message IDs, how to pair them, and what values to avoid. It is sufficiently complete for an agent to resolve and pass the three required parameters correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds meaningful guidance beyond the schema: it explicitly forbids passing user names/user_ids for chat parameters, requires chat_id/message_id pairing, and instructs where to obtain IDs. This real-world resolution guidance is valuable for an agent selecting correct parameter values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Forward an existing message to another EXISTING chat,' naming the specific verb, resource, and the key constraint that both source and destination chats must already exist. It further disambiguates from sibling messaging tools by stressing that target_chat_id is a chat ID, never a recipient user_id/name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clear context is provided: resolve source chat/message and destination chat independently, and obtain IDs from conversation/message listing resolvers. It warns against passing person names, user_ids, or bare message IDs, but it does not explicitly name alternative tools like messaging_send_message or linkedin_send_message for when forwarding is not appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_getMessage: GetARead-onlyIdempotentInspect
Get one exact message. BOTH chat_id and message_id are required because V2 message identity is contextual to its chat. If starting from a person/topic, resolve chat first, list messages, then reuse both IDs. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds useful behavioral context: it explains the V2 contextual identity requirement and that providers may only guarantee uniqueness inside a chat. This goes beyond the annotations and helps the agent understand why both IDs are needed, without contradicting the safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose, repeating the parameter descriptions almost verbatim. It is front-loaded with the core purpose and then covers both ID types, but it could be trimmed significantly without losing value. It is structured in clear paragraphs, but the redundancy with the schema hurts conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema, the description sufficiently explains how to call the tool correctly: it details how to resolve chat_id and message_id, including the optional account_id handling. It covers the prerequisites and flow, so an agent has what it needs to invoke the tool. The lack of return-format details is acceptable for a read-only retrieval tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% – each parameter has a detailed description. The tool description largely repeats the same information (e.g., chat_id and message_id definitions, how to obtain them). It adds minimal new meaning beyond the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Get one exact message' – a specific verb and resource. It clearly states the tool retrieves a single message, and the requirement for both chat_id and message_id distinguishes it from listing or mutation tools. The purpose is unambiguous and distinct from siblings like messaging_list_messages or message_delete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit flow guidance: 'If starting from a person/topic, resolve chat first, list messages, then reuse both IDs.' It also specifies what not to pass ('Never pass: person name, user_id, message_id'). However, it does not name alternatives or explicitly state when not to use this tool, though the implied workflow covers that.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_get_attachmentMessage: Get attachmentARead-onlyIdempotentInspect
Download one exact attachment from a WhatsApp, Instagram, Telegram or LinkedIn message (for example a voice note or an image) as base64 bytes with its content type. Required chain: resolve/list chat -> chat_id -> get/list message -> attachment.id -> retrieve. All three IDs (chat_id, message_id, attachment_id) are required because attachment identity is scoped to its message. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. Attachment ID: Exact attachment id returned inside a specific email/message. Obtain with: read the parent email/message first -> attachment.id Never pass: filename, URL.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. | |
| attachment_id | Yes | Exact attachment ID from the already-read parent message (e.g. a WhatsApp/Telegram voice note or image). Never use filename or a provider URL as attachment_id. Attachment ID: Exact attachment id returned inside a specific email/message. Obtain with: read the parent email/message first -> attachment.id Never pass: filename, URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint true and destructiveHint false, so there is no safety contradiction. The description adds useful behavior beyond annotations: return format (base64 bytes plus content type), exactness of the attachment, and the scoping requirement for IDs. It does not mention rate limits or auth, but those are not necessary given the annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence is front-loaded and clear, and the chain is useful. But the Chat ID / Message ID / Attachment ID blocks are near-verbatim copies of the schema property descriptions, and the 'Never pass' lists are repeated, making the description longer than needed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a retrieval tool with no output schema, the description covers the return format, prerequisites, required IDs, and common invalid inputs. The only gaps are minor: account_id is left to the schema and the message_id guidance includes an irrelevant mutation-tool caveat. Overall, an agent has enough to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds the required-chain and scoping rationale plus 'Never pass' warnings. However, the per-parameter text largely duplicates the schema descriptions verbatim, and the message_id section contains a confusing 'for mutation tools' artifact that is irrelevant to this read-only tool. The optional account_id is only described in the schema, not in the main description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence names a specific verb ('Download'), a precise resource ('one exact attachment'), the supported channels (WhatsApp, Instagram, Telegram, LinkedIn), and the output form (base64 bytes with content type). It also establishes the ID-scoping constraint, which distinguishes it from generic message/email retrieval tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit required chain ('resolve/list chat -> chat_id -> get/list message -> attachment.id -> retrieve') and states all three IDs are required because attachment identity is scoped to its message. It provides per-ID 'Obtain with' and 'Never pass' guidance, though it does not name sibling alternatives such as email_get_attachment for explicit exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_list_reactionsMessage: List reactionsBRead-onlyIdempotentInspect
List detailed reactions on one exact message. Preserve its chat_id + message_id pair. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safe/read-only nature is covered. The description adds a behavioral requirement to 'Preserve its chat_id + message_id pair,' which is useful context beyond annotations. However, it does not disclose response characteristics, error behavior, or any rate limits, so it adds modest value but does not fully cover the behavioral burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose and largely repeats the schema's property descriptions verbatim. While the opening line is concise, the subsequent Chat ID and Message ID sections are redundant given the 100% schema coverage, making the description feel bloated rather than earn its length. The structure is organized with labels, but the content is not streamlined.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only listing tool, the description covers parameters thoroughly and annotations confirm safety, but it does not describe the expected return shape or any additional context like pagination of reactions. Without an output schema, a brief note on what 'detailed reactions' includes would improve completeness. The description is adequate for basic invocation but not fully rich.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description duplicates the parameter guidance already present in the input schema (e.g., 'Never pass: person name' for chat_id). It reiterates the importance of pairing chat_id and message_id, but this is also found in the schema's message_id description. The description adds no new meaning beyond the schema, so a baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'List detailed reactions on one exact message,' which clearly specifies the verb (list), the resource (reactions), and the scope (one exact message). This differentiates it from siblings like message_add_reaction and social_list_comment_reactions by focusing on reading reactions for a single chat message, not modifying them or targeting comments/posts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for reading reactions on a message but does not explicitly state when to use it over alternatives such as social_list_comment_reactions or when not to use it. It focuses on parameter acquisition rather than providing usage context relative to sibling tools, so the guidance is only implied, not explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_mark_readMessage: Mark readAInspect
Mark one exact message read. Resolve chat_id then message_id; do not pass person/user ID as chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=false, idempotentHint=false, destructiveHint=false, and openWorldHint=true, so the safety profile is mostly established. The description adds some behavioral context by labeling this as a mutation tool and warning that providers may only guarantee message uniqueness inside a chat, but it does not address side effects, rate limits, or auth requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with a clear purpose and is organized into Chat ID and Message ID sections, but it is verbose and largely duplicates the schema property descriptions. Phrases like 'Never pass: person name, user_id, message_id' and 'Never pass: message text, chat_id, message ID without its chat context' are repetitive and could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple state-changing tool, the description covers the key complexity: how to obtain and pair chat_id and message_id, and common mistakes to avoid. It does not explain the return value or broader side effects, but the annotations supply the safety and mutability signals, making this adequate for a correctly scoped call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds a useful resolution order ('Resolve chat_id then message_id') and reinforces the exact-ID requirement with explicit 'never pass' examples. It does repeat much of what is in the schema, but the added workflow guidance helps the agent call the tool correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence, 'Mark one exact message read,' names a specific verb, resource, and scope, and the emphasis on 'exact' distinguishes it from bulk operations or unread-marking. Provider-related examples and 'chat/conversation ID' further clarify it is for chat messages rather than email, despite email_mark_read existing among siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear guidance on how to call the tool: resolve chat_id first, then message_id, and never pass person/user IDs as chat_id. It also tells the agent where to obtain valid IDs. It does not explicitly name alternatives or exclusions, but the context is detailed enough to avoid the most common misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_remove_reactionMessage: Remove reactionADestructiveInspect
Remove the user's reaction from one exact message. Resolve chat/message first. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID from a conversation/chat listing or resolver. A person name/user_id is NOT a chat_id. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| reaction | Yes | The emoji/reaction to remove (the same value that was added, e.g. 👍); list reactions first when unknown. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| message_id | Yes | Exact message ID returned inside the specified chat. Keep it paired with chat_id for all V2 message mutations/reactions. Message ID: Exact message id inside a specific chat. In V2 always keep chat_id together with message_id because providers may only guarantee uniqueness inside the chat. Obtain with: provider read/list conversation messages -> message.id Never pass: message text, chat_id, message ID without its chat context for mutation tools. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, and the description adds useful operational context: providers may only guarantee message uniqueness inside a chat, and certain values must never be passed. It does not describe effects like what happens if the reaction is absent, but the annotation safety profile lowers the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose and repetitive: the Chat ID and Message ID blocks follow the same 'Obtain with... Never pass...' pattern and are duplicated verbatim in the schema parameter descriptions. The opening sentence is clear, but the overall length is disproportionate to the tool's simple purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description covers the critical knowledge an agent needs: how to resolve and pair chat_id/message_id, provider-specific caveats, and explicit negative examples. The account_id disambiguation lives in the schema and is well handled there. Minor gaps like the effect of removing a non-existent reaction are negligible.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The main description mostly duplicates the schema text for chat_id and message_id rather than adding new meaning; reaction and account_id are only documented in the schema. No significant parameter clarification is added beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb, resource, and scope: 'Remove the user's reaction from one exact message.' This cleanly differentiates it from siblings like message_add_reaction, message_list_reactions, and social_remove_post_reaction. No ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit resolution steps ('Resolve chat/message first') and precise provenance for IDs ('Obtain with: provider list conversations/inbox chats -> chat.id'). It does not explicitly name alternatives or state when-not-to-use, but the context is strong enough for an agent to apply it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_resolve_chatMessage: Resolve chatARead-onlyIdempotentInspect
List/search conversations so a human recipient/topic can be mapped to exact chat_id before reading/replying or resolving message_id. Do not use a person name as chat_id. For LinkedIn use linkedin_list_inboxes then linkedin_list_inbox_chats because account-wide chat listing is not supported. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | ||
| provider | Yes | ||
| is_unread | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds useful context about how chat IDs are obtained and that account-wide chat listing is not supported for LinkedIn, but this LinkedIn guidance is somewhat irrelevant since the schema only accepts whatsapp, instagram, and telegram.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized and front-loaded with the core purpose, but it is repetitive ('Do not use a person name as chat_id' appears alongside 'Never pass: person name, user_id, message_id') and spends significant space on LinkedIn behavior for a tool whose schema excludes LinkedIn as an option.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has no output schema, so the description should more fully describe what the response contains; it only implies chat IDs via 'Obtain with: provider list conversations/inbox chats -> chat.id'. It also leaves several parameters unexplained, making the definition adequate but incomplete for reliable invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, and the description does not compensate for the undocumented limit, cursor, or is_unread parameters. It explains how to obtain a chat_id but does not clarify the meaning or expected values of most input parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource combination ('List/search conversations' to map to exact chat_id) and clearly distinguishes the tool's purpose from simple chat reading or messaging. It also names the exact alternative flows for LinkedIn, preventing confusion with sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool ('before reading/replying or resolving message_id'), what not to pass ('Never pass: person name, user_id, message_id'), and gives a precise alternative path for LinkedIn. This gives an agent actionable routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_send_native_mediaMessage: Send native mediaADestructiveInspect
Send one media/file attachment using the provider's native rendering mode where supported. Resolve chat_id first. Useful for inline image/video/native media; for WhatsApp multiple attachments may become separate provider messages, so this tool intentionally sends one attachment per call for predictable behavior.
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | ||
| chat_id | Yes | Exact chat.id resolved/listed for the destination conversation; never pass a person name/user_id here. | |
| filename | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| content_type | Yes | ||
| content_base64 | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as non-read-only and destructive. The description adds behavioral value by explaining native rendering support caveats and the WhatsApp multi-attachment-to-separate-messages behavior, which is not visible in the schema or annotations. It could go further in specifying which providers support native rendering, but the added context is meaningful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and front-loaded with the core action. The three sentences each add useful information, though 'native media' in the third sentence is somewhat redundant with the first sentence. Overall it is appropriately sized and readable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose and a key provider-specific nuance, but it omits essential invocation details such as the format of content_base64, the role of content_type and filename, and what response or outcome to expect. With no output schema and low parameter coverage, these omissions leave the agent under-equipped for correct calls.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 33%, so the description must compensate, but it does not explain the key parameters content_base64, content_type, filename, or text. It only implies that these relate to a media/file attachment. The agent is left guessing about base64 encoding format, MIME type expectations, and whether text is a caption. This is a significant gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: 'Send one media/file attachment using the provider's native rendering mode where supported.' This distinguishes it from text or voice messaging tools by emphasizing media, native rendering, and one-attachment-per-call behavior. However, it does not explicitly name or contrast any sibling tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives useful context: 'Resolve chat_id first' is a prerequisite, 'Useful for inline image/video/native media' identifies a use case, and the WhatsApp note explains when and why to prefer this tool for predictable one-attachment behavior. It does not explicitly mention alternatives or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_send_voice_noteMessage: Send voice noteADestructiveInspect
Send an audio attachment as a native/playable voice note where the connected provider supports it (notably WhatsApp/Telegram). Resolve chat_id first. Provide base64 content + exact MIME type/filename. Do not send the same voice note repeatedly after an uncertain timeout; read chat state first.
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | Optional caption/text only when supported/requested. | |
| chat_id | Yes | Exact chat.id resolved/listed for the destination conversation; never pass a person name/user_id here. | |
| filename | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| content_type | Yes | Audio MIME type. WhatsApp voice notes expect Opus in OGG: audio/ogg (codecs=opus); MP3 is sent as a regular audio file. | |
| content_base64 | Yes | Base64-encoded audio bytes, not a URL/path. | |
| duration_seconds | No | Duration of the audio in seconds when known (shown by the provider on the voice note). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false. The description adds a specific caution: 'Do not send the same voice note repeatedly after an uncertain timeout; read chat state first', which is valuable operational guidance beyond the structured hints and does not contradict them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loads the main purpose, and includes the key operational caveat without any filler. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
It covers the essential usage points: provider support, prerequisite of resolving chat_id, content format, and duplicate-avoidance. It could benefit from explicitly contrasting with message_send_native_media or other senders, but the description is sufficiently self-contained for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 86% (6/7 params have descriptions). The description reiterates 'base64 content + exact MIME type/filename' but adds little beyond schema. It adds a note about resolving chat_id, which is already in the schema. The description does not compensate for the one undocumented parameter (duration_seconds is described in schema, so actually 100%? Wait, duration_seconds has a description, so coverage is actually 100%? The signal says 86% but all properties have descriptions? Let's re-check: text, chat_id, filename, account_id, content_type, content_base64, duration_seconds all have descriptions. So coverage is 100%? But signal says 86% maybe because text is optional? Anyway, schema covers all. So description adds marginal value, baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Send an audio attachment as a native/playable voice note', and immediately specifies provider support (WhatsApp/Telegram). This clearly distinguishes it from generic send tools like messaging_send_message or message_send_native_media.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit usage conditions: 'where the connected provider supports it', and prerequisites: 'Resolve chat_id first', 'Provide base64 content + exact MIME type/filename', and 'read chat state first'. It does not name alternative tools for when not to use it, but the provider-support caveat is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_find_chat_by_userMessaging: Find chat by userARead-onlyIdempotentInspect
Find the existing one-to-one chat for a known LinkedIn, WhatsApp, Instagram or Telegram provider user ID. Use after resolving the user; user_id is not chat_id.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Exact provider user ID returned by a profile/contact resolver; never a name or profile URL. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the crucial warning that user_id is not chat_id, preventing misuse. It does not mention behavior when no chat exists, but the annotation coverage lowers the bar, and the warning adds meaningful context beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no fluff. The primary purpose is front-loaded, and the usage note is attached at the end. Every word earns its place; it is both concise and structured effectively.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple signature (2 params, no output schema, no nesting), the description covers the core purpose, the prerequisite, and a key distinction. It does not describe the return value or the case when no chat exists, which is a minor gap but not critical for a read-only lookup tool. The annotations fill in the safety aspects, so overall it is reasonably complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already well documented. The description reiterates the user_id vs chat_id distinction, but the schema's own description of user_id already covers this ('never a name or profile URL'). No additional semantic value beyond what the schema provides, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (find), the target (existing one-to-one chat), and the scope (for known LinkedIn, WhatsApp, Instagram, or Telegram provider user IDs). It also clarifies a common confusion ('user_id is not chat_id'), making it unambiguous against sibling tools like messaging_start_chat or message_resolve_chat.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs to use after resolving the user, giving a clear precondition. It does not name alternative tools outright, but the phrase 'existing one-to-one chat' implies it is for retrieval rather than creation. Slight gap in not mentioning when NOT to use it (e.g., when you already have the chat_id).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_list_chatsMessaging: List chatsARead-onlyIdempotentInspect
List chats for WhatsApp, Instagram or Telegram, most recently active first; use it to find a chat_id. LinkedIn requires inbox-specific listing. V2 filters: type, before/after (on the chat's last activity), archived and unread; WhatsApp pages by offset, other providers by cursor. For 'messages received between X and Y' call messaging_list_recent_messages, which also reads the messages.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | ||
| after | No | ||
| limit | No | ||
| before | No | ||
| cursor | No | ||
| offset | No | ||
| provider | Yes | ||
| is_unread | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| is_archived | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description adds substantial behavioral context: sort order (most recently active first), filter semantics (before/after based on last activity, archived, unread), pagination differences (WhatsApp offset vs. cursor for others), and provider scope (LinkedIn excluded). It also clarifies that this tool does not read message content by pointing to the alternative. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, compact paragraph with three sentences, each carrying essential information: primary purpose and scope, filter and pagination details, and the alternative tool. It front-loads the core purpose, and every sentence earns its place without redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of 10 parameters, no output schema, and multiple providers, the description is remarkably complete. It covers the main use case, provider-specific differences, pagination behavior, and the alternative for message retrieval. It does not explicitly list return fields, but the agent can infer that chat objects with chat_ids are returned, and the description clearly states the tool's purpose is to find a chat_id. Nothing essential for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 10% schema description coverage, the description compensates by explaining the purpose of key parameters: type, before/after, archived, unread, and pagination (offset vs. cursor). It clarifies that before/after refer to the chat's last activity. However, it does not explicitly describe the 'limit' parameter or the exact output shape, leaving some inference needed. Still, it adds meaningful semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the tool lists chats for WhatsApp, Instagram, or Telegram, most recently active first, and explicitly says its purpose is to find a chat_id. It differentiates from siblings by noting LinkedIn requires inbox-specific listing and by pointing to messaging_list_recent_messages for a different use case. The verb and resource are specific, and the scope is clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit when-to-use guidance: use to find a chat_id, and clearly states an alternative: for messages between X and Y, call messaging_list_recent_messages. It also warns that LinkedIn requires inbox-specific listing, implying this tool is not for LinkedIn. These exclusions and alternatives are direct and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_list_messagesMessaging: List messagesARead-onlyIdempotentInspect
List messages in a known chat, newest first, with V2 filters/pagination (before/after on the message timestamp). Message IDs are scoped to their chat: keep chat_id for any later get/edit/delete/forward/reaction action.
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | ||
| limit | No | ||
| before | No | ||
| cursor | No | ||
| offset | No | ||
| chat_id | Yes | Exact chat/conversation ID from the appropriate chat/inbox listing or resolver. Never pass a person name or user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| user_id | No | Exact provider user ID returned by the relevant profile/contact resolver; never a display name or profile URL. For LinkedIn, use the stable system ID. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the agent knows this is a safe read. The description adds genuine behavioral value beyond that: newest-first ordering, V2 pagination scoped to message timestamps, and the chat-scoped ID caveat. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two front-loaded sentences with zero filler: purpose, ordering, and pagination model first, then the critical ID-scoping caveat. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the core contract: what is listed, ordering, pagination model, and the chat-scoped ID warning. But there is no output schema to compensate, and the description never addresses return shape or the cursor/offset distinction, which an agent would need to paginate correctly. Adequate but with clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 38%, so the description carries extra burden. It does add meaning by explaining that before/after are V2 filters on the message timestamp, which helps for otherwise undocumented string params. But cursor, offset, and limit semantics are left unexplained, and the schema has no descriptions for them either.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List), resource (messages), and scope (a known chat), plus distinguishing behaviors: newest-first ordering and V2 timestamp-based pagination. An agent can readily tell it apart from siblings like messaging_list_chats, messaging_list_recent_messages, and message_get.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'in a known chat' precondition implies the agent must first obtain a chat_id from a chat-listing or resolver tool, and the closing note instructs it to keep chat_id for later get/edit/delete/forward/reaction actions. However, no alternative sibling is named and there is no explicit when-to-use vs when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_list_recent_messagesMessaging: List recent messagesARead-onlyIdempotentInspect
Digest of the messages RECEIVED across every WhatsApp/Instagram/Telegram chat in a time window: 'what did I get on WhatsApp since yesterday noon?', 'summarize my Telegram messages of the last 2 hours', scheduled inbound digests. Enumerates chats without a creation-date filter, reads each one with message-level after/before and returns inbound messages grouped by chat, newest first — one call instead of paginating messaging_list_chats + messaging_list_messages. When complete is false (enumeration or read limits, or unknown message direction), say so instead of presenting the digest as exhaustive. Returns chat_id + message id pairs usable with message_get / messaging_send_message.
| Name | Required | Description | Default |
|---|---|---|---|
| after | Yes | Start of the window, ISO 8601 with Z or offset (exclusive). Convert 'since yesterday noon' with the user's timezone. | |
| before | No | End of the window (exclusive); omit for 'until now'. | |
| provider | Yes | Messaging provider named by the user. LinkedIn recipients use linkedin_resolve_person + linkedin_start_conversation instead. | |
| chat_type | Yes | Restrict to direct chats or groups. | all |
| max_chats | Yes | Maximum number of chats read for messages (most recently active first). | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Required when the user has several accounts for the provider: pick the one the user named. | |
| include_sent | Yes | Also return messages sent by the user (default: inbound only). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so safety is covered. The description adds genuinely non-obvious behavioral contract: the `complete` flag semantics (false on enumeration or read limits or unknown direction) and the instruction to disclose non-exhaustiveness, plus that results are grouped by chat, newest first.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and scope are front-loaded in the first clause, and the examples and fallback guidance each carry real informational weight. It is dense and slightly run-on, but almost no clause is expendable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does so reasonably: grouped by chat, newest first, chat_id + message id pairs usable with message_get / messaging_send_message, plus the completeness flag. A little more on pagination/limit interaction with max_chats would close the remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents every parameter including timezone handling, provider, chat_type, and max_chats. The description reinforces the time-window and inbound-only framing but adds little parameter syntax beyond what the schema provides, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (digest of RECEIVED messages) with an explicit scope (WhatsApp/Instagram/Telegram chats within a time window) and concrete query examples. It also names the sibling tools it replaces (messaging_list_chats + messaging_list_messages), letting an agent distinguish it without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames when to use it (inbound digests, 'what did I get since yesterday noon', scheduled digests) and when alternatives apply — one call instead of paginating two siblings, and LinkedIn recipients route to linkedin_resolve_person + linkedin_start_conversation. Both the selection and exclusion conditions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_resolve_recipientMessaging: Resolve recipientARead-onlyIdempotentInspect
Turn a person's name, nickname, phone number or handle into the exact WhatsApp/Instagram/Telegram recipient BEFORE sending: searches the user's 1-to-1 chats (ranked by most recent exchange) and contacts. Returns incomplete (lookup could not be fully enumerated; do not send automatically), resolved (one clear match: send immediately with the recommended next tool, no extra confirmation needed when the user already gave the message), ambiguous (several people: ask which one, most recent conversation first) or not_found. Use for 'send a WhatsApp to Julien', 'reply to Marie on Instagram', 'message +33 6…'. Never pass a name as chat_id or user_id.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | How the user refers to the person: first name, full name, phone number or handle. | |
| provider | Yes | Messaging provider named by the user. LinkedIn recipients use linkedin_resolve_person + linkedin_start_conversation instead. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Required when the user has several accounts for the provider: pick the one the user named. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only, idempotent, non-destructive profile, and the description adds real behavioral context beyond them: the search scope (1-to-1 chats ranked by most recent exchange plus contacts), the four possible outcomes, and per-outcome handling policy (ambiguous → ask, incomplete → do not auto-send, resolved → send immediately without extra confirmation).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the core purpose lands in the first clause, followed by search behavior, outcomes, and examples. The outcome list is information-packed and each clause earns its place, though the single long paragraph could be structured for faster scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the return-value burden and does so fully by enumerating resolved/incomplete/ambiguous/not_found with the action for each. Combined with 100% schema coverage and clear annotations, nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds negative guidance ('never pass a name as chat_id or user_id') and clarifies the name field's accepted forms, which the schema also covers. It goes slightly beyond the schema without documenting provider/account_id edge behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (resolve a name/nickname/phone/handle into an exact messaging recipient) and scopes it precisely to WhatsApp/Instagram/Telegram 1-to-1 chats and contacts. An agent can immediately distinguish it from siblings like messaging_find_chat_by_user or message_resolve_chat, which operate on chats rather than people.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to use this BEFORE sending, gives concrete trigger phrases ('send a WhatsApp to Julien', 'reply to Marie on Instagram'), and routes LinkedIn cases to linkedin_resolve_person + linkedin_start_conversation. It also states a hard exclusion: never pass a name as chat_id or user_id.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_send_messageMessaging: Send messageADestructiveInspect
Send a message in an existing LinkedIn, WhatsApp, Instagram or Telegram chat. Supports text, base64 file attachments and provider-specific options. Locate/read the chat first if chat_id is not already known. This is a real external send action.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| chat_id | Yes | Exact chat/conversation ID from the appropriate chat/inbox listing or resolver. Never pass a person name or user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| specifics | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| attachments | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal destructiveHint and openWorldHint, and the description reinforces this with 'This is a real external send action.' That is valuable plain-language confirmation, but it mostly paraphrases the annotations rather than adding new behavioral details like irreversibility, rate limits, or failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences with no filler: action, capabilities, and prerequisite/side-effect are each clearly separated. The most important facts are front-loaded in the first sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a nested, side-effecting tool with no output schema, the description supplies the key selection facts and the chat-lookup prerequisite. It leaves nested attachment semantics and provider-specific option details largely to inference, making it adequate for selection but not fully complete for invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description names text, base64 file attachments, and provider-specific options, which loosely maps to the text, attachments, and specifics parameters. However, schema description coverage is only 40% and the description does not explain send_mode, voice_note, or how to structure provider-specific options, so it only partially compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb and resource: send a message in an existing chat, with the provider scope explicitly stated (LinkedIn, WhatsApp, Instagram, Telegram). The phrase 'existing chat' differentiates it from chat-starting tools, and the provider list distinguishes it from email and social tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs the agent to locate/read the chat first if chat_id is not already known, which is a clear precondition for correct use. It does not explicitly name alternatives like messaging_start_chat or provider-specific send_message tools, but the context strongly implies them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_send_to_contactMessaging: Send to contactADestructiveInspect
One-step send for voice-style requests: 'send a WhatsApp to Julien saying I'm 10 minutes late'. Resolves the recipient like messaging_resolve_recipient and sends the text ONLY when exactly one person matches (existing conversation or contact). When lookup is incomplete or several people match, nothing is sent and the candidates are returned so you can ask the user which one. The user must have stated the message content; do not invent it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | How the user refers to the recipient. | |
| text | Yes | Exact message text the user asked to send. | |
| provider | Yes | Messaging provider named by the user. LinkedIn recipients use linkedin_resolve_person + linkedin_start_conversation instead. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Required when the user has several accounts for the provider: pick the one the user named. | |
| recipient_user_id | No | Exact provider user ID chosen by the user after an ambiguous result; skips name matching. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false, and openWorldHint=true, so the mutation profile is known. The description adds genuinely non-derivable behavior: the send is atomic with resolution, nothing is sent when the lookup is incomplete or multiple people match, and candidates are returned instead so the agent can ask the user. It does not cover auth/account-selection failure modes or rate limits, keeping it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the use case in the first clause, then the resolution rule, then the failure branch, then the guard against invented content. Four dense sentences, none redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does explain the ambiguity return (candidates). It leaves the success response shape (e.g., message id, conversation reference) unspecified, but for a single-send tool with destructive annotations already present, that is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds cross-parameter semantics the schema only implies per-field: that 'name' is resolved like messaging_resolve_recipient and that a send only proceeds on a unique match, which explains the interaction between name, recipient_user_id, and the ambiguity branch.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('send' a messaging message) and pins the scope precisely: a one-step resolve-and-send for voice-style requests, distinct from the two-step messaging_resolve_recipient + messaging_send_message path. An agent can tell it apart from whatsapp_send_message, instagram_send_message, and messaging_send_message without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('one-step send for voice-style requests') with a concrete example, an explicit when-not ('do not invent' the content; user must have stated it), and an alternative path implied by the reference to messaging_resolve_recipient and the schema note routing LinkedIn recipients to linkedin_resolve_person + linkedin_start_conversation. The ambiguity branch is fully described.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_set_chat_stateMessaging: Set chat stateAInspect
Update supported chat state such as read/unread, archive/pin, label or mute metadata. Only send fields explicitly requested.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| label | No | ||
| chat_id | Yes | Exact chat/conversation ID from the appropriate chat/inbox listing or resolver. Never pass a person name or user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| pin_status | No | ||
| muted_until | No | ||
| read_status | No | True marks the chat read; false marks it unread. | |
| archive_status | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, and openWorldHint=true. The description adds the instruction 'Only send fields explicitly requested,' which hints at partial-update behavior but does not disclose what happens to unspecified fields (e.g., whether they are left unchanged or reset). It also does not mention whether the operation is reversible or what side effects occur. The description does not contradict the annotations, but it adds only modest behavioral context beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that front-loads the core purpose and ends with a practical usage rule. It is concise and every clause earns its place. It could be slightly improved by naming an alternative tool, but as written it is efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 8 parameters, no output schema, and only 38% schema description coverage, so the description carries a heavy burden. It covers the main state categories and the partial-update rule, but it does not explain the 'name' parameter, the muted_until union type, or the behavior of unspecified fields. For a mutation tool with no output schema, an agent would likely need more detail to call it correctly in edge cases, though the chat_id guidance in the schema helps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 38%, so the description must compensate. The description names the state dimensions (read/unread, archive/pin, label, mute metadata) which maps to several parameters (read_status, archive_status, pin_status, label, muted_until). It also adds the key guidance 'Only send fields explicitly requested,' which clarifies that parameters are optional and partial updates are intended. However, it does not explain the meaning of 'name' or the boolean/string union for muted_until, so it does not fully compensate for the low coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('Update') and resource ('supported chat state') and enumerates the state dimensions (read/unread, archive/pin, label, mute metadata). It is distinguishable from siblings like messaging_set_composing and messaging_set_presence, though it does not explicitly name them. The title 'Messaging: Set chat state' reinforces the purpose, so the description adds enough specificity to avoid confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a partial usage rule: 'Only send fields explicitly requested.' This implies the tool is for updating only the fields the user asked for, which is useful guidance. However, it does not explicitly state when to use this tool versus alternatives like messaging_set_composing, messaging_set_presence, or email_mark_read, nor does it mention prerequisites like needing a valid chat_id. The guidance is implied rather than explicit, so it earns a 3.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_set_composingMessaging: Set composingAInspect
Publish a typing or voice-recording composing signal in a known chat where supported (LinkedIn Classic and WhatsApp). This is ephemeral provider state; use only when an agent workflow explicitly needs it.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| chat_id | Yes | Exact chat/conversation ID from the appropriate chat/inbox listing or resolver. Never pass a person name or user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations indicate readOnlyHint=false (write), destructiveHint=false, and idempotentHint=false. The description adds that the signal is 'ephemeral provider state', which is a useful behavioral detail beyond the annotations, and implies no persistent effects. It does not contradict any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose and provider scope, followed by a concise usage caveat. No redundant words or information already in the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple write tool with good schema descriptions and annotations, the description covers what it does, when to use it, and its ephemeral nature. It does not describe return values or error handling, but with no output schema and low complexity, this is acceptable. The provider restriction and usage caution are valuable context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67% (two of three params have detailed descriptions, including strong guidance on chat_id and account_id). The action param is an enum with clear options (typing/recording) that requires no further explanation. The description itself adds no parameter detail, but the schema is sufficient, so this is above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('publish'), a precise resource ('typing or voice-recording composing signal'), and a scope ('in a known chat where supported (LinkedIn Classic and WhatsApp)'). This clearly distinguishes it from sibling tools like messaging_set_chat_state or messaging_set_presence, which handle different state/signals.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit guidance: 'use only when an agent workflow explicitly needs it' and notes it is ephemeral provider state. It does not explicitly name alternatives or state when not to use it, but the 'only when needed' instruction plus provider scope gives clear context for an agent deciding between this and similar messaging tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_set_presenceMessaging: Set presenceAInspect
Set the connected messaging account presence where the provider supports it (LinkedIn Classic, WhatsApp, Telegram). Use only for an explicit presence request.
| Name | Required | Description | Default |
|---|---|---|---|
| presence | Yes | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal this is a mutation (readOnlyHint=false) and non-idempotent, so the description's main added value is the provider-support qualifier and the explicit-request restriction. It does not detail what happens for unsupported providers or failed updates, and no annotation contradiction is present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and resource, followed by the usage restriction. Every clause earns its place; there is no redundant restating of the title or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple mutation tool with one enum parameter and a rich account_id description, the combination of schema and description is mostly sufficient. It includes the essential provider-support and explicit-request context, though it could have added a sentence about unsupported-provider behavior or the visible effect of the call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents account_id thoroughly, but the required 'presence' parameter has no description and the tool description adds no parameter-level meaning. With only 50% schema description coverage, the description should compensate for the undocumented required parameter; it does not explain the meaning of values like 'restricted_online'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'Set ... presence', and scopes it to providers that support it (LinkedIn Classic, WhatsApp, Telegram). It also states the narrow trigger ('explicit presence request'), which clearly distinguishes this from sibling tools like messaging_set_composing or messaging_set_chat_state.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear usage condition: only call for an explicit presence request, and only when the provider supports presence. It does not explicitly name alternative tools for chat state or composing, but the exclusionary 'only for an explicit presence request' is enough for an agent to select this tool correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messaging_start_chatMessaging: Start chatADestructiveInspect
Start a new WhatsApp, Instagram or Telegram one-to-one/group chat by sending its first message. Resolve users_ids first. A string starts 1-to-1; an array requests a group. LinkedIn requires the inbox-specific start tool.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| text | Yes | ||
| provider | Yes | ||
| specifics | No | ||
| users_ids | Yes | One exact provider user ID for a direct chat, or exact provider user IDs for a group; resolve every recipient first. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| attachments | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and readOnlyHint=false, so the mutating nature is established. The description adds useful context: it sends a message and creates a new chat, and it distinguishes one-to-one vs group behavior. It doesn't disclose what happens on failure, partial group creation, or whether sending is immediate, but annotations carry the core safety burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core purpose and providers. Every sentence adds useful routing or usage information. It is slightly terse given the optional parameters and complexity, but nothing is padded or redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters, no output schema, and nested attachment objects, the description covers the core start-chat flow and the critical string/array behavior, but leaves gaps. It does not explain return values, error behavior, or the meaning of specifics/name/attachments. The schema covers account_id and users_ids, but overall context is only moderately complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 29%, so the description must compensate. It does explain the critical users_ids distinction: string for 1-to-1, array for group. However, it adds nothing for text, name, specifics, or attachments, leaving several parameters semantically opaque. The schema documents users_ids and account_id well, but the description only partially fills the overall gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the operation: start a new WhatsApp, Instagram, or Telegram one-to-one/group chat by sending its first message. It distinguishes the tool from the broader messaging_send_message and provider-specific tools, and explicitly excludes LinkedIn. This is a specific verb + resource with scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear when-to-use guidance: use for starting new chats and resolving users_ids first. It also names an exclusion ('LinkedIn requires the inbox-specific start tool'), which routes the agent away from a sibling. It could be stronger by explicitly naming the LinkedIn sibling or distinguishing from messaging_send_message for existing chats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_delete_postPosts: Delete postADestructiveInspect
Delete an exact supported social post. Resolve/verify post_id first. Destructive: explicit deletion intent required. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it.
| Name | Required | Description | Default |
|---|---|---|---|
| post_id | Yes | Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true, and the description reinforces this with 'Destructive: explicit deletion intent required.' It adds useful behavioral context beyond annotations by warning to verify the ID beforehand and specifying what inputs are unacceptable, which helps an agent avoid irreversible mistakes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence carries operational weight: the core action, the destructive warning, ID format, sourcing commands, and exclusions. It is front-loaded with the primary purpose and does not waste words, though it does duplicate some schema text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive single-parameter tool with no output schema, the description covers everything an agent needs: what to delete, how to resolve the correct ID, which tools to use to obtain it, and how to handle account ambiguity via the optional account_id. The account_id guidance in the schema complements this fully.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both post_id and account_id thoroughly. The description restates the post_id sourcing guidance but adds little beyond the schema; it does not introduce new parameter-level semantics that the schema lacks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a precise verb-resource pair, 'Delete an exact supported social post,' which clearly distinguishes this from social_delete_comment and the many read/list tools in the sibling list. It also adds the precondition 'Resolve/verify post_id first,' making the scope unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear operational guidance: resolve the post first, obtain the ID through listed tools, and never pass post text, author ID, or URL unless a resolver accepts it. It does not explicitly contrast with social_delete_comment, but the 'exact supported social post' phrasing and detailed ID sourcing make the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_list_comment_reactionsPosts: List comment reactionsARead-onlyIdempotentInspect
List detailed reactions on an exact comment. First resolve post_id, then list comments and select comment.id. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | Pagination offset returned/used by this reaction listing. | |
| post_id | Yes | Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| comment_id | Yes | Exact comment ID belonging to the already resolved post_id. Obtain by listing comments on that post; never pass comment text or post_id here. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the behavioral requirement of resolving exact IDs before calling, and the 'Never pass' rules clarify input constraints beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is verbose and repetitive. The same 'Never pass' and 'Obtain with' instructions are duplicated in the description text and again inside the schema property descriptions for post_id and comment_id. It could be condensed significantly without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the main complexity—how to obtain the required IDs—and includes guidance on the optional account_id. It does not describe the return format, but given the absence of an output schema and the fact that this is a read/list operation, the essential information for correct invocation is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all parameters are documented in the schema. The description adds extra semantics by explaining how to obtain post_id and comment_id via specific sibling tools and by explicitly listing what not to pass, which is not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action 'List detailed reactions on an exact comment', specifying a verb, resource, and scope. It does not explicitly name sibling tools like linkedin_list_post_reactions, but the title and text make it unambiguous that this targets comment reactions, not post reactions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit workflow instructions: 'First resolve post_id, then list comments and select comment.id', and also tells the agent what not to pass (e.g., 'Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it'). It does not compare against alternatives, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_react_to_commentPosts: React to commentADestructiveInspect
React to one exact comment. Resolve post -> comment before acting. Do not confuse post_id and comment_id. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
| Name | Required | Description | Default |
|---|---|---|---|
| post_id | Yes | Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| reaction | Yes | Provider-supported reaction value; use the requested semantic reaction and do not invent unsupported values. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| comment_id | Yes | Exact comment ID belonging to the already resolved post_id. Obtain by listing comments on that post; never pass comment text or post_id here. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=true, so the mutation/destructive nature is covered. The description adds practical behavioral context: the need to resolve IDs first, the warning against confusing post_id and comment_id, and the caution against passing invalid values. It does not contradict annotations and provides additional process-level transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-organized, with the core purpose front-loaded. It uses line breaks to separate Post ID and Comment ID instructions, making it scannable. While it repeats some schema content, every sentence serves a purpose (resolution steps, exclusions, account_id handling). It is not overly verbose for a tool with such a high risk of ID confusion.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (requires resolving both post and comment) and the absence of an output schema, the description covers the essential steps to call it correctly: how to obtain both IDs, what not to pass, and how to handle the optional account_id. It does not describe return values, but that is not required without an output schema. The guidance is sufficient for an agent to execute the action correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description largely mirrors the schema's parameter descriptions for post_id and comment_id, adding little new meaning. However, it does reinforce the resolution workflow and explicitly warns against passing text/URLs, which is slightly more than the schema alone. Still, the added value is marginal, keeping the score at 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear verb+resource: 'React to one exact comment.' It explicitly distinguishes itself from related tools by focusing on comments rather than posts or reaction removal. Sibling tools like linkedin_react_to_post and social_remove_comment_reaction are implicitly differentiated by the 'exact comment' scope and the resolution steps.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: it requires resolving post -> comment before acting, and names specific resolver tools (linkedin_search_posts, linkedin_list_user_posts, etc.) and their output fields. It also gives clear 'never pass' exclusions for each ID, preventing common misuse. This goes beyond vague context to actionable rules.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_remove_comment_reactionPosts: Remove comment reactionADestructiveInspect
Remove the user's reaction from one exact comment. Resolve post_id/comment_id first. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
| Name | Required | Description | Default |
|---|---|---|---|
| post_id | Yes | Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| reaction | Yes | The reaction to remove: emoji or provider reaction type that was added. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| comment_id | Yes | Exact comment ID belonging to the already resolved post_id. Obtain by listing comments on that post; never pass comment text or post_id here. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare destructiveHint=true and readOnly=false, so the description is not required to restate the safety profile. It adds useful context that the operation is scoped to an exact, pre-resolved comment and warns against guessing from unstructured input, but it does not reveal much beyond what the annotations and name imply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The opening sentence is clear and the resolver guidance is well labeled, but much of the description duplicates the parameter descriptions in the schema nearly verbatim. This repetition makes the description longer than necessary without adding new information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive 4-parameter tool with full schema coverage, the description provides sufficient resolver chains and anti-misuse guardrails to call it correctly. It is slightly incomplete because one referenced comment resolver is missing from the sibling tool list, but the overall guidance is strong.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already contains the same detailed resolver and 'never pass' guidance for post_id and comment_id. The description therefore adds little new parameter meaning beyond what the input schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the exact action and target ('Remove the user's reaction from one exact comment'), clearly distinguishing this from related tools like social_remove_post_reaction and social_react_to_comment. It emphasizes the precise scope of the operation without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete resolver chains for obtaining the post_id and comment_id, and explicit 'Never pass' exclusions for text, author IDs, and URLs. It does not explicitly steer the agent toward this tool versus the sibling post-reaction removal tool, and it references instagram_list_post_comments, which is not present in the provided sibling list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_remove_post_reactionPosts: Remove post reactionADestructiveInspect
Remove the user's reaction from one exact post. Resolve post_id first; never use post URL/text unless another resolver explicitly converts it. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it.
| Name | Required | Description | Default |
|---|---|---|---|
| post_id | Yes | Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| reaction | Yes | The reaction to remove: the emoji for Instagram, or the LinkedIn reaction type that was added (e.g. LIKE). | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, so the description does not need to restate that this is a destructive operation. It adds contextual behavior about ID resolution, but does not disclose edge cases such as what happens if no reaction exists or whether the action is reversible beyond what destructiveHint implies.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core action and then provides focused, high-value ID resolution rules. There is some redundancy between the description and the schema, but the warnings about never passing URL/text/author ID are important and justify their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter destructive tool with no output schema, the description covers the critical invocation details: exact post ID format, how to obtain IDs, and account_id disambiguation. It is complete enough for an agent to select and call the tool correctly, though it does not describe response or no-op behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema coverage is 100%, and the schema already documents post_id, reaction, and account_id in detail, including the emoji vs. LinkedIn reaction format and account disambiguation. The description repeats much of the same post_id guidance rather than adding substantial new parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Remove the user's reaction from one exact post.' It also distinguishes this from related siblings like social_remove_comment_reaction and linkedin_react_to_post by explicitly scoping to posts and removal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage guidance: resolve post_id first, never pass URL/text/author ID, and use specific list/search tools to obtain the ID. It does not explicitly name sibling alternatives for deleting comment reactions or chat reactions, but the post-scoped instructions and exclusions make the intended context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_resolve_commentPosts: Resolve commentARead-onlyIdempotentInspect
List comments for an already-resolved post so the agent can map a human reference such as 'the comment from Sarah' to exact comment_id before replying/reacting/editing/deleting. First resolve post_id. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| post_id | Yes | Exact provider post ID returned by post search/list/get. Never pass post text, author ID or a post URL. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds useful behavioral context: the post must already be resolved, IDs must be exact and scoped, and LinkedIn IDs often use base64-style formatting. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose is front-loaded, which is good. However, the Post ID guidance is duplicated in the description and schema, 'Never pass' appears twice, and the comment-ID paragraph is somewhat convoluted. It could be tighter and better structured as bullets.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must carry the burden of saying what the tool returns. It says comments are listed and maps to comment.id, but it does not state which fields are returned (e.g., author info needed to identify Sarah's comment) or how offset/pagination behaves. The upstream resolver references are helpful but leave gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67%; post_id and account_id are described in the schema, while offset is not. The description adds provider-specific detail for post_id and names concrete resolver chains (linkedin_search_posts -> result.id), but it largely repeats the schema's post_id wording and does not explain offset semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action: 'List comments for an already-resolved post', and states the goal of mapping a human reference like 'the comment from Sarah' to an exact comment_id before reply/react/edit/delete. This distinguishes it from comment mutation tools such as social_delete_comment and social_update_comment, though it does not explicitly contrast with the platform-specific list tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear precondition ('First resolve post_id') and a clear use window ('before replying/reacting/editing/deleting'). It also provides strong negative guidance: never pass post text, author user ID, or URL unless a resolver explicitly accepts it. It stops short of explicitly naming when to prefer an alternative tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_update_commentPosts: Update commentADestructiveInspect
Edit an existing comment. Required chain when starting from human text: resolve post -> post.id -> list comments -> comment.id -> edit. post_id and comment_id are different ID namespaces. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Final replacement comment text explicitly requested/approved by the user. | |
| post_id | Yes | Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| comment_id | Yes | Exact comment ID belonging to the already resolved post_id. Obtain by listing comments on that post; never pass comment text or post_id here. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate this is not read-only and is destructive; the description adds meaningful context by explaining that post_id and comment_id belong to different ID namespaces and must be sourced through specific resolver/list tools. It also stresses that text must be 'explicitly requested/approved by the user', which is useful safety behavior beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is substantially repetitive: the full ID-sourcing guidance appears both in the main description and again verbatim inside the post_id and comment_id schema descriptions. The important workflow is front-loaded, but the bloated, run-on phrasing and duplicated content hurt readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter mutation tool with no output schema, the description covers the full invocation workflow, ID provenance, account disambiguation, and prohibited input types. It is nearly complete, though it never states what the caller should expect in the response after a successful edit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description repeats most of that information rather than adding unique parameter-level meaning; the only marginal addition is the explicit 'different ID namespaces' warning, but it is not enough to push beyond baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening phrase 'Edit an existing comment' names a specific verb and resource, and the title 'Posts: Update comment' reinforces the operation. It is clearly distinguished from siblings like social_delete_comment, linkedin_comment_on_post, and social_update_post by stating exactly which mutation it performs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit required chain: resolve post -> post.id -> list comments -> comment.id -> edit, and warns against passing post text, author IDs, or URLs. It does not explicitly name alternative create/delete comment tools, but the when-to-use and when-not-to-use guidance is clear enough for an agent to follow.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
social_update_postPosts: Update postAInspect
Edit an existing supported social post. Resolve the exact post first, then reuse post.id. Never infer an ID from post text or author. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it.
| Name | Required | Description | Default |
|---|---|---|---|
| text | No | Replacement/updated post text requested by the user. | |
| post_id | Yes | Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| can_comment | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal mutation (readOnlyHint=false) and non-destruction (destructiveHint=false), so the description mainly needs to add context beyond that. It adds important ID-resolution caveats, but does not disclose side effects, permission requirements, irreversibility, or failure behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and the critical never-infer-an-ID guidance is emphasized. The description is somewhat run-on and repeats ID guidance also present in the schema, but it remains appropriately sized and actionable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description does not specify which social providers are 'supported' or what a partial update behaves like. Still, the ID-resolution instructions plus the schema's account_id guidance cover the main invocation needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
post_id semantics are strongly enriched beyond the schema with provider-specific examples and resolver chains. Schema coverage is 75%, so baseline is near 3, but the detailed warning about never passing post text, author ID, or URL justifies a higher score. can_comment lacks semantic explanation beyond its enum values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Edit an existing supported social post.' This distinguishes it from sibling create, delete, and comment tools, and the title 'Posts: Update post' reinforces the intent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: resolve the exact post first and reuse post.id, never inferring an ID from text or author. It does not explicitly name alternatives or state when not to use this tool, but the 'existing' wording implies the update-vs-create/delete boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
team_add_seatsTeam: Add seatsADestructiveInspect
Add (or reduce) paid extra seats on the Team subscription so more colleagues can be invited. Billing owner only; prorated immediately on the saved payment method. FIRST call without confirm to get the price and a one-click Stripe confirmation link, then call with confirm=true after the user approves. extra_seats is the ADDED number of seats relative to the current paid extra seats (use 1 to add one seat).
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | Set true ONLY after the user explicitly confirmed the price shown to them. Without it, the tool returns the price, the proration explanation and a Stripe confirmation link instead of changing anything. | |
| extra_seats | Yes | Seats to add (positive) or remove (negative, only unused seats). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses critical behaviors beyond annotations: billing owner restriction, immediate proration on the saved payment method, and the non-destructive nature of the first call. The description also explains that extra_seats is relative to current paid extra seats)Skip, which prevents off-by-one mistakes. Annotations indicate destructiveHint=trueholen, and the description aligns by showing confirm is required for changes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three dense sentences deliver purpose, authorization, billing side effect, and the exact confirm workflow with no wasted words. The critical 'relative' parameter semantics are front-loaded after the workflow, and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive billing mutation with no output schema, the description covers prerequisites (billing owner), workflow (dry-run then confirm), side effects (proration on saved payment method), and parameter semantics. An agent can invoke this tool correctly without guessing, and the absence of an output schema is compensated by the explicit mention of the first-call response (price, proration explanation, Stripe link).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description adds meaning beyond the schema: extra_seats is 'the ADDED number of seats relative to the current paid extra seats (use 1 to add one seat),' clarifying that the value is delta, not total. It also reinforces the confirm semantics from the schema, making the workflow unambiguous.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Add (or reduce) paid extra seats on the Team subscription' with clear purpose 'so more colleagues can be invited.' It also distinguishes itself from team_invite_member by focusing on billing seats rather than inviting members, and clarifies the direction of change with 'add (or reduce).'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit operational usage through the two-step confirm workflow: first call without confirm to obtain price and Stripe link, then call with confirm=true after user approval. It also states the authorization requirement ('Billing owner only'). It does not explicitly name sibling alternatives, but the billing-vs-invite distinction is enough to prevent confusion with team_invite_member.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
team_invite_memberTeam: Invite memberADestructiveInspect
Invite a colleague to the user's Team workspace by email. Each member gets a separate login, isolated provider Scope and their own connected accounts; the team only centralizes billing and seats. Only team owners/admins can invite. When no seat is free, the result explains how to add a paid seat (team_add_seats). If the user is not on Team, propose account_change_plan(plan='team').
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | Email address of the person to invite. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses that it's a write operation (invite) and adds behavioral context: the result explains how to add a paid seat, and it suggests proposing a plan change if not on Team. Does not contradict annotations (destructiveHint=true, readOnlyHint=false). Adds value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the purpose, then scoping, permission, and fallback actions. No wasted words; every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with no output schema, the description covers the action, permission, conditional alternatives, and explains the team concept. An agent has everything needed to decide when and how to call it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a clear description for the email parameter. The tool description adds no extra parameter-specific details beyond 'by email', which is already implied. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (invite), resource (colleague to Team workspace), and method (by email). Clearly distinguishes from sibling tools by mentioning team_add_seats and account_change_plan as alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states permission requirements (only owners/admins can invite) and provides conditional guidance: when no seat is free, points to team_add_seats; when not on Team, points to account_change_plan. Gives clear when-to-use and when-not-to-use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
telegram_connectTelegram: ConnectAInspect
Connect or reconnect the user's Telegram account directly in the conversation: returns a QR code image to scan from Telegram > Settings > Devices > Link Desktop Device, then poll account_connection_status until connected. Accounts protected by a Telegram cloud password (2FA) must use the browser link returned by account_connect instead. Use account_id to re-authenticate an existing disconnected Telegram account.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Nilyo connection ID (unipile_account_id from list_connected_accounts) of an EXISTING account to re-authenticate. Omit to connect a new account. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With all annotations false, the description carries the behavioral burden. It discloses the full flow: returns QR code, then polling until connected. It also notes the 2FA limitation and re-auth path. While it doesn't mention potential side effects like creating a new connection record, it gives sufficient behavioral context beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately long but each sentence carries necessary information: the core action, the QR scanning path, the 2FA exclusion, and re-auth usage. It is front-loaded with the primary purpose and avoids fluff, though slightly more verbose than strictly needed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a connect tool with no output schema, the description covers the essential steps: returning a QR image, polling, the 2FA caveat, and account_id usage. It doesn't detail error handling or timeouts, but given the tool's simplicity and schema coverage, it is adequately complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already fully describes account_id with 100% coverage, including its purpose and how to obtain it. The description restates this usage but doesn't add new semantic meaning. Baseline 3 is appropriate since the schema handles parameter documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool connects or reconnects a Telegram account via QR code, which is a specific verb+resource. It distinguishes itself from account_connect (browser link for 2FA) and account_connection_status (polling), making it unambiguous among the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when NOT to use this tool: accounts with 2FA must use account_connect. Also provides guidance on using account_id for re-authentication of existing accounts and mentions polling account_connection_status. This gives clear decision rules for the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_create_destinationRealtime: Create destinationAInspect
Create a realtime event destination for this Nilyo user. Nilyo uses its global Unipile control-plane key server-side but ALWAYS restricts the Unipile endpoint to account IDs owned by this authenticated user. By default matching future accounts are automatically added. Explicit account_ids without a providers filter stay restricted to those accounts, even with auto_include_new_accounts=true. For n8n use its Test URL first, validate with a Development/Mock event, then update to Production URL. The endpoint signing secret is kept encrypted server-side and is never returned by MCP: never ask for it.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| events | Yes | Exact Unipile V2 event types. Call webhook_list_available_events first when unsure. Do not invent event names. | |
| runtime | Yes | ||
| providers | No | Optional provider filter. google includes Gmail and outlook includes Microsoft accounts. With auto_include_new_accounts=true, Nilyo keeps this Unipile endpoint's account_ids synchronized when the user connects matching accounts later. | |
| account_ids | No | Optional explicit Unipile account IDs returned by list_connected_accounts. Nilyo rejects the whole request if any ID is not owned by the authenticated user. | |
| request_url | Yes | Public HTTPS POST receiver URL supplied by the target runtime, without user:password@ credentials or #fragment. Never guess a URL. | |
| auto_include_new_accounts | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond the provided annotations: the global control-plane key is always restricted to account IDs owned by the authenticated user, future matching accounts are added by default, explicit account_ids without a providers filter stay restricted even with auto_include_new_accounts=true, and the signing secret is encrypted server-side and never returned by MCP. These are non-obvious operational and security constraints that materially affect safe invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, followed by dense but useful behavioral, security, and workflow guidance. Every sentence carries operational meaning, though the paragraph could be broken into shorter units for readability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter mutation tool with no output schema, the description covers the most important behavioral and security context, plus a workflow recommendation. It does not enumerate runtime options or explain event selection, but those are largely handled by the schema's event descriptions and the sibling webhook_list_available_events tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 57%, so the description must compensate. It clarifies the important interaction between account_ids, providers, and auto_include_new_accounts, and implies the request_url workflow via the n8n Test/Production URL guidance. It does not explain the name or runtime parameters, leaving some gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a realtime event destination') that clearly distinguishes it from sibling webhook_update_destination, webhook_delete_destination, and webhook_list_destinations. It lacks explicit sibling naming, but the create operation is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear procedural guidance for n8n users (Test URL, validate with a Development/Mock event, then update to Production URL) and a security warning not to ask for the signing secret. It does not explicitly state when to use this tool versus webhook_update_destination or when creation is inappropriate, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_delete_destinationRealtime: Delete destinationADestructiveInspect
Delete an Nilyo-owned Unipile webhook endpoint. This stops future realtime delivery to that destination; require explicit user intent.
| Name | Required | Description | Default |
|---|---|---|---|
| destination_id | Yes | Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true, so deletion is known. The description adds value by specifying what gets stopped ('future realtime delivery') and requiring explicit user intent, which is a meaningful behavioral caution. It does not mention irreversibility or permission needs, but the annotation plus consequence statement carry most of the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tightly written sentences: the first states the action and scope; the second states the direct consequence and a safety requirement. There is no filler or repetition of schema content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter deletion tool with full schema coverage and annotations, the description is complete. It names the resource, the effect, and the user-intent requirement; nothing an agent needs to decide whether to invoke it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the destination_id property is already well documented: it is the Nilyo webhook destination ID returned by create/list tools and must never be the Unipile endpoint ID directly. The description adds no new parameter-level detail, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the exact action ('Delete') on a specific resource ('Nilyo-owned Unipile webhook endpoint') and names the ownership boundary, which distinguishes this from deleting some other webhook resource. It clearly differentiates from sibling tools like webhook_create_destination, webhook_update_destination, and webhook_list_destinations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells the agent the consequence ('stops future realtime delivery to that destination') and adds an important gate: 'require explicit user intent.' It does not explicitly contrast with alternatives (e.g., updating/disabling instead of deleting), but the direct deletion call and consequence make the usage context clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_get_delivery_logsRealtime: Get delivery logsARead-onlyIdempotentInspect
Inspect recent Unipile webhook delivery conversations for this destination. Use when an agent/n8n receiver did not wake or a test event was not observed. This is preferred to guessing whether delivery occurred.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | Yes | ||
| destination_id | Yes | Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose read-only, idempotent, non-destructive behavior. The description adds the troubleshooting context (when delivery is suspected to have failed) but not additional behavioral details like response shape or field meanings. It does not contradict any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, no fluff. The central action and resource are in the first sentence, and the 'when to use' is in the second and third. Perfectly front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema, the tool is simple enough that the description plus schema cover what an agent needs: the resource, the trigger, and the safe read-only behavior. The only gap is that 'Realtime' from the title isn't echoed in the description, but 'recent' suffices for this low-complexity tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers destination_id with a thorough explanation and a warning not to use the Unipile endpoint ID, while limit has type/default/bounds but no prose. The tool description doesn't elaborate on limit's meaning beyond what the schema gives, so it adds minimal value beyond the existing 50% schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Inspect') and resource ('recent Unipile webhook delivery conversations for this destination'), which clearly differentiates it from sibling tools like webhook_test_destination or webhook_get_destination. It also frames the tool's role in troubleshooting delivery failures.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly names two trigger conditions ('agent/n8n receiver did not wake' and 'test event was not observed') and contrasts with 'guessing whether delivery occurred.' However, it does not name any alternative tool or exclusion criteria, so it stops short of the 5-level.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_get_destinationRealtime: Get destinationARead-onlyIdempotentInspect
Get one Nilyo-owned webhook destination and its configured events/provider/account selection.
| Name | Required | Description | Default |
|---|---|---|---|
| destination_id | Yes | Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is established. The description adds the scoping that this is a single-destination read and lists what is included, but it does not describe response format or error/absence behavior. That is useful but not rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no filler. The core action, resource, and returned information are front-loaded, making it easy for an agent to scan and act on immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read operation with full schema coverage and strong annotations, the description covers what is needed: what is fetched and what fields are included. No return schema is provided, but the phrase about configured events/provider/account selection gives sufficient context, and there is no additional complexity to document.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the destination_id parameter already has a detailed description in the input schema, including its source and the warning not to use the Unipile endpoint ID directly. The tool description does not need to add parameter semantics and does not go beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Get'), a specific resource ('one Nilyo-owned webhook destination'), and the returned content ('configured events/provider/account selection'). It is clearly distinguished from list/create/update/delete siblings by the 'one destination' framing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use or when-not-to-use guidance is given; it never points to webhook_list_destinations for retrieving all destinations or to other webhook tools for setup/testing. The only hint is the word 'Get one,' which leaves the choice of tool to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_get_setup_guideRealtime: Get setup guideARead-onlyIdempotentInspect
Get runtime-specific instructions for receiving Unipile realtime events in n8n, OpenClaw, Hermes, Make or a generic agent. Use BEFORE creating the webhook when the user has not yet produced a public receiver URL.
| Name | Required | Description | Default |
|---|---|---|---|
| runtime | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds context that it returns instructions and provides sequencing guidance, but it does not disclose any additional behavioral traits like output format or the absence of side effects beyond what annotations imply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first states the tool's purpose and scope, the second gives usage timing. The most decision-relevant information is front-loaded and every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple guide-retrieval tool with one enum parameter, the description covers purpose, scope, and usage timing. There is no output schema, but 'runtime-specific instructions' adequately conveys what the caller will receive. The only minor gap is not stating the format of the returned instructions, which is unlikely to hinder correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It does so by naming each runtime ('n8n, OpenClaw, Hermes, Make or a generic agent') that maps directly to the 'runtime' enum values, making it clear that the parameter selects which runtime's instructions to return.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get') and resource ('runtime-specific instructions for receiving Unipile realtime events') and enumerates the exact runtimes supported. This makes it immediately distinguishable from sibling webhook tools like webhook_create_destination, webhook_get_destination, and webhook_list_available_events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit temporal guidance: 'Use BEFORE creating the webhook when the user has not yet produced a public receiver URL.' This tells the agent both when to invoke it and the precondition that selects it over alternatives, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_list_available_eventsRealtime: List available eventsARead-onlyIdempotentInspect
List realtime Unipile V2 event types Nilyo can subscribe an agent to, plus the common event envelope. Use this before creating a destination if the user's requested trigger is ambiguous.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the 'realtime' qualifier and mentions the return of the common event envelope, which is minor behavioral context, but it does not go deeper (e.g., response shape or filtering).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero filler. The first sentence front-loads the core purpose and output, and the second delivers targeted usage guidance. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list tool, the description is complete enough: it states what is returned (event types + envelope) and when to call it. No output schema exists, but the description partially compensates. It lacks a note about static output or format, but that is a minor gap given the low complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so per the rubric the baseline is 4. The description needs no parameter guidance; the empty schema with 100% coverage fully documents the input.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a resource ('realtime Unipile V2 event types'), and a scope ('Nilyo can subscribe an agent to'), plus a secondary output ('the common event envelope'). This clearly distinguishes it from siblings like webhook_list_destinations and webhook_get_setup_guide.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The second sentence gives explicit when-to-use guidance: 'Use this before creating a destination if the user's requested trigger is ambiguous.' This is actionable, but it does not mention alternatives or when not to use it, leaving some room for inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_list_destinationsRealtime: List destinationsARead-onlyIdempotentInspect
List webhook destinations created by this Nilyo user. These are control-plane records; realtime traffic flows directly Unipile -> destination, not through Nilyo.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the operation's safety is covered. The description adds meaningful context beyond annotations by explaining that these are control-plane records and that realtime traffic flows directly Unipile -> destination, not through Nilyo. This clarifies the nature of the data returned and the architectural role of the destinations, which is valuable for the agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no wasted words. The action and scope are front-loaded ('List webhook destinations created by this Nilyo user'), and the second sentence adds essential context about control-plane vs. data-plane. Every sentence earns its place, and it is highly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with no parameters, no output schema, and comprehensive annotations (readOnly, idempotent, non-destructive), the description is mostly complete. It specifies the scope (created by this user) and clarifies the architectural role of the records. However, it does not mention what fields are returned or whether pagination is involved, though without an output schema, the agent might need such hints. Still, for a zero-parameter list, the description is adequate and goes beyond minimal requirements.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so schema coverage is trivially 100%. The description does not need to explain any parameters, and the baseline for 0 params is 4. The description adds no parameter-specific semantics because none exist, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb (list) and resource (webhook destinations created by this Nilyo user), and the scope is explicit. It distinguishes itself from siblings like webhook_get_destination (which retrieves a single record) by implying a listing operation, and the mention of 'created by this Nilyo user' adds precision.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides context about control-plane records but does not explicitly state when to use this tool versus alternatives like webhook_get_destination or webhook_list_available_events. The usage is implied (when you need all destinations for the user), but no direct comparison or exclusion is given. Given the simplicity of the tool (no parameters), this is a moderate gap, not a severe one.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_test_destinationRealtime: Test destinationARead-onlyIdempotentInspect
Return the exact test procedure for a destination. In a Unipile Development Application, use Mock accounts/Test & Debug to generate a real fake event, then inspect webhook_get_delivery_logs and the target runtime. Nilyo does not fabricate provider event payloads because the Unipile mock event is the source of truth.
| Name | Required | Description | Default |
|---|---|---|---|
| destination_id | Yes | Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, covering the safety profile. The description adds behavioral context: it explains the source of truth (Unipile mock event) and clarifies that Nilyo does not fabricate provider event payloads. This goes beyond annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The purpose is front-loaded, and the usage guidance is compact yet complete. Every sentence contributes value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple (one param, no output schema), and the description covers its purpose, usage steps, and key constraints. It references the environment and alternative tools, so nothing critical is missing for correct invocation. A 5 would require explicit return-format details, but the description already sets expectations for a procedure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the parameter description clearly explains destination_id and even warns against using the Unipile endpoint ID directly. The tool description adds no additional parameter semantics, but the baseline 3 applies when schema fully covers the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource ('Return the exact test procedure') and clearly differentiates from sibling webhook tools like webhook_get_setup_guide and webhook_get_destination. It also clarifies what it does not do (does not fabricate payloads), leaving no ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs when to use this tool (to retrieve the test procedure) and gives step-by-step context: use Mock accounts/Test & Debug to generate a real fake event, then inspect webhook_get_delivery_logs and the target runtime. It also names the alternative (webhook_get_delivery_logs) and explains the limitation of Nilyo, making the selection obvious.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
webhook_update_destinationRealtime: Update destinationAInspect
Update a webhook destination URL, events or provider/account selection. Common n8n chain: create with Test URL -> receive mock event -> update same destination to Production URL. Nilyo recomputes authorized account_ids server-side.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| events | No | Exact Unipile V2 event types. Call webhook_list_available_events first when unsure. Do not invent event names. | |
| enabled | No | ||
| runtime | No | ||
| providers | No | Optional provider filter. google includes Gmail and outlook includes Microsoft accounts. With auto_include_new_accounts=true, Nilyo keeps this Unipile endpoint's account_ids synchronized when the user connects matching accounts later. | |
| account_ids | No | Optional explicit Unipile account IDs returned by list_connected_accounts. Nilyo rejects the whole request if any ID is not owned by the authenticated user. | |
| request_url | No | Public HTTPS POST receiver URL supplied by the target runtime, without user:password@ credentials or #fragment. Never guess a URL. | |
| destination_id | Yes | Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly. | |
| auto_include_new_accounts | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the safety profile (mutation, non-destructive, non-idempotent, closed-world), so the bar is lower. The description adds a genuinely non-obvious behavior: 'Nilyo recomputes authorized account_ids server-side,' telling the agent the account selection may be adjusted server-side rather than used verbatim.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, purpose front-loaded, then workflow context, then a behavioral note. Each sentence carries information; no filler or repetition of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, 9 params with only 56% description coverage, and a mutation tool whose partial-vs-full update semantics (what happens to unspecified fields) are never stated. The purpose and workflow are covered, but an agent still lacks enough to call this confidently in edge cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description names three updatable categories (URL, events, provider/account selection) mapping to request_url, events, and providers/account_ids, which helps scope the call. But schema coverage is only 56% and name, enabled, runtime, and auto_include_new_accounts get no mention, so the description does not fully compensate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Update), resource (webhook destination) and the fields affected (URL, events, provider/account selection), so an agent knows this is the mutation counterpart to webhook_create_destination. It stops short of naming a sibling as an alternative, but the update/create verb split plus the referenced n8n chain provides implicit differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Common n8n chain: create with Test URL -> receive mock event -> update same destination to Production URL' gives concrete context for when to reach for this tool. No explicit when-not conditions or named alternatives are offered, but the workflow framing is clear usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_connectWhatsApp: ConnectAInspect
Connect or reconnect the user's WhatsApp account directly in the conversation without leaving the agent. Default mode returns a QR code image to scan from WhatsApp > Linked devices; with phone_number it returns a pairing code to type on the phone instead (useful when the QR image cannot be displayed). Then poll account_connection_status until connected. Requires an active trial/subscription and a free WhatsApp slot on the plan; otherwise the result explains the upgrade. Use account_id to re-authenticate an existing disconnected WhatsApp account.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Nilyo connection ID (unipile_account_id from list_connected_accounts) of an EXISTING account to re-authenticate. Omit to connect a new account. | |
| phone_number | No | Optional. International phone number of the WhatsApp account, digits only (e.g. 33612345678). When provided, a pairing code is returned instead of a QR code. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations are all false, so description carries full burden. It discloses that it returns a QR code or pairing code, that it is asynchronous (polling required), and that it explains upgrades if ineligible. Re-authentication behavior is also disclosed. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five sentences, each earning its place: purpose, mode explanation, polling instruction, prerequisites, and re-auth usage. Front-loaded with the core action, no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-param tool with no output schema, the description covers return behavior (QR/pairing code), next steps (polling), and eligibility conditions. No critical information is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 100% schema coverage, the description adds meaningful context: explains the default QR mode, the phone_number toggling to pairing code, and account_id's role in re-authentication. This goes beyond the schema's already detailed property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool connects/reconnects a WhatsApp account, specifying the resource (WhatsApp) and the action (connect). It distinguishes itself from siblings like account_connection_status by explicitly mentioning polling after initiation, and from telegram_connect by being WhatsApp-specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance: when to use phone_number (when QR cannot be displayed), when to use account_id (re-authenticate existing account), and directs to poll account_connection_status afterward. Also states prerequisites (active trial/subscription and free slot) and what happens if unmet.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_get_profileWhatsApp: Get profileARead-onlyIdempotentInspect
Retrieve a WhatsApp user profile by provider user ID or supported phone-number identifier. Use to resolve/verify the recipient before a new chat.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Exact provider user ID returned by the relevant profile/contact resolver; never a display name or profile URL. For LinkedIn, use the stable system ID. LinkedIn system user ID: Stable LinkedIn/Unipile user id, commonly ACo... for Classic profiles. Obtain with: linkedin_get_profile_from_url(profile_url) -> result.id; linkedin_get_profile(user_id_or_public_identifier) -> result.id; linkedin_search_people(...) -> selected result.id Never pass: full linkedin.com/in/... URL, person name, company ID. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint, openWorldHint, idempotentHint, destructiveHint. The description adds 'resolve/verify the recipient' context, which is useful but does not go beyond what annotations imply. It doesn't mention rate limits, caching, or exact data returned, but with annotations covering the safety profile, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The main description is one sentence, efficient. The account_id parameter has a lengthy but useful explanation. The overall structure is clear, but the parameter descriptions add extra detail that, while helpful, could distract from the main description.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 2 parameters and no output schema, the description is complete enough for an agent to call it correctly. It explains the identifier requirements, the resolution purpose, and the acaccount_id handling. It might benefit from noting that phone numbers must be in E.164 format, but the current detail is adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already describes both parameters including the user_id and account_id. The description clarifies that user_id must come from a resolver and never be a display name or URL, and guides on account_id selection when multiple accounts exist. This adds valuable meaning beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Retrieve a WhatsApp user profile' and specifies the input identifiers (provider user ID or phone number), distinguishing it from other WhatsApp tools like whatsapp_list_contacts or whatsapp_is_number_registered. It could be slightly more specific about what fields are returned, but the purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says 'Use to resolve/verify the recipient before a new chat', providing clear context for when to use this tool. It does not explicitly mention when not to use it or name alternatives, but the purpose is clear enough among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_is_number_registeredWhatsApp: Is number registeredARead-onlyIdempotentInspect
Check whether a phone number corresponds to a WhatsApp user/account before starting outreach or resolving a WhatsApp recipient. Pass the number in international form.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| phone_number | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds the operational context that this is a pre-check, but it does not disclose additional behavioral traits such as return semantics, error behavior, or rate limits. This is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, and the core purpose is front-loaded. Every part of the description earns its place, including the concrete formatting instruction for the phone number.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is a simple, read-only check with one required parameter and no output schema. 'Check whether' implies a boolean-style result, but the description does not explicitly confirm return behavior or how failures are signaled. Still, the essential calling context and parameter requirement are present, so it is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: phone_number has no schema description, and the description compensates by specifying it must be in international form. account_id already has a detailed schema description, so the tool description does not need to repeat it. This adds meaningful guidance beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('Check whether') and a clear resource ('a phone number corresponds to a WhatsApp user/account'), and it differentiates the tool by anchoring it to the pre-outreach and recipient-resolution use case. This makes the purpose easy to distinguish from related siblings like whatsapp_get_profile or messaging_resolve_recipient.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: use it before starting outreach or resolving a WhatsApp recipient. It does not explicitly name alternatives or state when not to use it, so it falls short of a 5, but the intended trigger conditions are obvious.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_list_contactsWhatsApp: List contactsARead-onlyIdempotentInspect
List WhatsApp contacts so a human name/phone can be resolved to an exact provider user identity before starting a new chat. Reuse the returned provider user ID; do not pass display name as whatsapp_user_id.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| cursor | No | Opaque pagination cursor returned by previous call; never invent. | |
| offset | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds valuable context about the tool's purpose and the behavioral rule about reusing the provider user ID, which goes beyond the annotations. It does not contradict any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero fluff, front-loading the purpose and immediately delivering the key usage instruction. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a list tool with no output schema, the description explains purpose and a key rule but omits output format and pagination behavior (limit/offset/cursor). It also does not mention that results are paginated or what fields are returned, which an agent would need for correct invocation. Annotations cover safety but not these operational details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 50% (limit and offset lack descriptions), and the description adds no parameter-specific meaning. It does not explain limit, offset, cursor, or account_id beyond what the schema provides, failing to compensate for the undocumented parameters. The 'provider user ID' is not a parameter here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists WhatsApp contacts and explicitly ties it to resolving a human name/phone to an exact provider user identity before starting a chat. It distinguishes itself from siblings like whatsapp_list_conversations by focusing on contact resolution, and even gives a concrete usage directive (reuse provider user ID).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides a clear when-to-use context (before starting a new chat) and a critical 'do not' instruction (do not pass display name as whatsapp_user_id). However, it does not explicitly name alternatives or when not to use this tool, though the use case is well implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_list_conversationsWhatsApp: List conversationsARead-onlyIdempotentInspect
List WhatsApp chats from the user's own connected WhatsApp account, most recently active first. Use to find a chat_id before reading or sending when the user identifies a conversation by person/name rather than ID. For 'what did I receive since X' use messaging_list_recent_messages.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered. The description adds the 'most recently active first' ordering and the scope of 'user's own connected WhatsApp account,' which are useful behavioral details. However, it does not disclose response structure, pagination behavior, or whether archived/deleted chats are included, so it adds moderate but not rich behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the first states the action and ordering, the second explains when to use it, and the third routes to an alternative. The key scoping phrase ('most recently active first') is front-loaded. Zero wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has only two optional parameters and no output schema, so the description does not need to explain return values. It covers the main usage scenario, the alternative for a different intent, and the account_id edge case is handled in the schema. A small gap is that it does not distinguish from messaging_list_chats or mention reading/sending counterparts, but the provider-specific name largely resolves that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is exactly 50%: account_id has a thorough description covering multi-account behavior and how to choose the ID, while limit has only type/numeric constraints. The tool description itself does not add parameter detail, but the account_id schema carries significant meaning. Since half the parameters are effectively described (account_id) and limit is self-explanatory with min/max bounds, this is adequate but not exceptional.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List WhatsApp chats from the user's own connected WhatsApp account, most recently active first.' It further clarifies the primary use case ('find a chat_id before reading or sending when the user identifies a conversation by person/name rather than ID') and explicitly contrasts with messaging_list_recent_messages. This clearly distinguishes it from sibling tools despite the many similar list_conversations tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives both a positive trigger ('Use to find a chat_id before reading or sending when the user identifies a conversation by person/name rather than ID') and a negative trigger with an explicit alternative ('For 'what did I receive since X' use messaging_list_recent_messages'). This is explicit when/when-not guidance with a named sibling, which is exactly what the rubric rewards.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_read_conversationWhatsApp: Read conversationARead-onlyIdempotentInspect
Read a WhatsApp chat and recent message history. Use for context, summaries, follow-up detection and cross-channel workflows before sending a reply.
| Name | Required | Description | Default |
|---|---|---|---|
| chat_id | Yes | Exact chat/conversation ID returned by conversation/inbox listing. Never pass a person name or provider user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive, and closed-world behavior. The description adds only 'recent message history' and use-case context; it does not disclose return format, pagination, or any additional behavioral details, so it adds moderate value beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences front-load the core action first, then list use cases without filler. Every word earns its place, and the structure makes it easy for an agent to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with exhaustive schema descriptions and safety annotations, the description covers what the tool does and when to use it. No critical information needed to select or invoke the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema thoroughly documents chat_id and account_id. The description itself adds no parameter-level semantics beyond what the schema already provides, matching the baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (Read) and the resource (a WhatsApp chat and recent message history). It is specific enough to distinguish from send/message tools and from read tools for other providers, though it does not explicitly name sibling alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives concrete use cases: context, summaries, follow-up detection, and cross-channel workflows before sending a reply. This provides clear context for when to use the tool, but it does not mention exclusions or alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_send_messageWhatsApp: Send messageADestructiveInspect
Send a WhatsApp message in an existing chat from the user's own account. If chat_id is unknown, call whatsapp_list_conversations first. Use only after the final message is explicitly requested/approved.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| chat_id | Yes | Exact chat/conversation ID returned by conversation/inbox listing. Never pass a person name or provider user ID. Chat ID: Exact provider chat/conversation ID. LinkedIn chat IDs may also be visible in /messaging/thread/{chat_id}/ URLs. Obtain with: provider list conversations/inbox chats -> chat.id Never pass: person name, user_id, message_id. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal a non-readonly, destructive, non-idempotent external action. The description adds valuable behavioral context beyond that: the action is scoped to the user's own account, requires an existing chat, and is gated on explicit user approval, which mitigates the risk of unsolicited sends.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three short sentences with no filler. The core action is front-loaded, followed by the prerequisite for chat_id and the approval guardrail, making it easy for an agent to parse in order.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a side-effecting send action, the description supplies the critical missing context: how to resolve an unknown chat_id and when sending is permitted. It leaves implicit the fallback to whatsapp_start_conversation for a new chat and does not describe the return value, but the tool is otherwise simple enough to call correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents chat_id and account_id in detail, and the description adds no new parameter-level meaning beyond saying chat_id must refer to an existing chat. With schema coverage at 67% and text being self-explanatory, the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Send a WhatsApp message in an existing chat from the user's own account.' It clearly distinguishes this tool from related siblings like whatsapp_start_conversation by limiting it to existing chats, and the provider-specific name prevents confusion with generic messaging_send_message.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit operational guidance: call whatsapp_list_conversations first if chat_id is unknown, and only send after the final message is explicitly requested or approved. It does not explicitly mention when to use whatsapp_start_conversation for new chats, so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whatsapp_start_conversationWhatsApp: Start conversationADestructiveInspect
Start a new 1-to-1 WhatsApp chat and send the first message. Resolve/verify recipient first with whatsapp_list_contacts or WhatsApp profile/number lookup. whatsapp_user_id must be provider identity, never a contact display name.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | First message text explicitly requested/approved by user. | |
| account_id | No | Optional Nilyo connection ID (unipile_account_id from list_connected_accounts). Omit when the user has one account for this provider. When several exist, Nilyo never guesses: list them (display name, identifier, provider user ID), choose the one the user named or ask, and pass its ID here. | |
| whatsapp_user_id | Yes | Exact WhatsApp provider user ID returned by contact/profile/number resolution; not a human name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, so the description does not need to re-state that sending a message is a side effect. It adds useful behavioral context by requiring recipient verification and that whatsapp_user_id be a provider identity, but does not elaborate on consequences like irreversibility or sending limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences deliver the action, the prerequisite, and an identity constraint with no filler. The key scoping detail ('new 1-to-1 chat') is front-loaded, and each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the schema covers all parameters, annotations convey destructive behavior, and the description adds the essential recipient-resolution workflow and provider-identity constraint, the definition is complete for an agent to select and invoke the tool correctly. No output schema is present, so return-value details are not required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema describes each parameter, but the description adds critical meaning by clarifying that whatsapp_user_id must be a provider identity, never a display name, and that recipient resolution must come first. This goes beyond the bare schema definition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action ('Start a new 1-to-1 WhatsApp chat and send the first message') and clearly identifies the resource. It differentiates from related messaging tools by emphasizing 'new' chat and first message, signaling this is not for continuing an existing conversation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context on when to use the tool by instructing the agent to resolve/verify the recipient first with whatsapp_list_contacts or a profile/number lookup. It does not explicitly name an alternative like whatsapp_send_message for existing chats, but the 'new' framing implies the distinction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
- Changed
webhook_create_destination1 field changed- changed
Input schema / properties / request_url / descriptionPrevious value: -"Public HTTPS POST receiver URL supplied by the target runtime. Never guess a URL."New value: +"Public HTTPS POST receiver URL supplied by the target runtime, without user:password@ credentials or #fragment. Never guess a URL."
- Changed
webhook_update_destination1 field changed- changed
Input schema / properties / request_url / descriptionPrevious value: -"Public HTTPS POST receiver URL supplied by the target runtime. Never guess a URL."New value: +"Public HTTPS POST receiver URL supplied by the target runtime, without user:password@ credentials or #fragment. Never guess a URL."
12 tool updates
- Changed
chat_update7 fields changed- changed
Input schema / additionalPropertiesPrevious value: -{}New value: +false - added
Input schema / properties / archive_statusAdded value: +{ + "type": "boolean" +} - added
Input schema / properties / labelAdded value: +{ + "type": "string" +} - added
Input schema / properties / muted_untilAdded value: +{ + "type": [ + "boolean", + "string" + ] +} - added
Input schema / properties / nameAdded value: +{ + "type": "string" +} - added
Input schema / properties / pin_statusAdded value: +{ + "type": "boolean" +} - added
Input schema / properties / read_statusAdded value: +{ + "type": "boolean" +}
- Changed
instagram_update_my_profile3 fields changed- changed
Input schema / additionalPropertiesPrevious value: -{}New value: +false - added
Input schema / properties / bioAdded value: +{ + "type": "string" +} - added
Input schema / properties / pictureAdded value: +{ + "additionalProperties": false, + "properties": { + "content": { + "type": "string" + }, + "content_type": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "metadata": { + "additionalProperties": false, + "properties": { + "duration": { + "type": "number" + } + }, + "type": "object" + } + }, + "required": [ + "content", + "content_type", + "filename" + ], + "type": "object" +}
- Changed
linkedin_list_job_postings6 fields changed- removed
Input schema / properties / cursorRemoved value: -{ - "description": "Pagination cursor returned by the previous list call; never invent it.", - "type": "string" -} - removed
Input schema / properties / limit / descriptionRemoved value: -"Maximum postings to return." - added
Input schema / properties / offsetAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Input schema / properties / stateAdded value: +{ + "default": [ + "DRAFT", + "OPEN", + "CLOSED", + "REVIEW", + "SUSPENDED" + ], + "items": { + "enum": [ + "DRAFT", + "OPEN", + "CLOSED", + "REVIEW", + "SUSPENDED" + ], + "type": "string" + }, + "minItems": 1, + "type": "array" +} - removed
Input schema / properties / statusRemoved value: -{ - "description": "Provider-supported posting status filter.", - "type": "string" -} - added
Input schema / requiredAdded value: +[ + "state" +]
- Changed
linkedin_recruiter_search_people2 fields changed- added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +}
- Changed
linkedin_resolve_company2 fields changed- added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +}
- Changed
linkedin_resolve_person2 fields changed- added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +}
- Changed
linkedin_sales_navigator_search_people2 fields changed- added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +}
- Changed
linkedin_search_companies2 fields changed- added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +}
- Changed
linkedin_search_jobs5 fields changed- added
Input schema / properties / primary_location / descriptionAdded value: +"Location parameter ID from linkedin_get_search_parameters(type=LOCATION); not a location name." - removed
Input schema / properties / primary_location / itemsRemoved value: -{ - "type": "string" -} - changed
Input schema / properties / primary_location / typePrevious value: -"array"New value: +"string" - added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +}
- Changed
linkedin_search_people12 fields changed- added
Input schema / properties / advanced_keywordsAdded value: +{ + "additionalProperties": false, + "properties": { + "company": { + "type": "string" + }, + "first_name": { + "type": "string" + }, + "last_name": { + "type": "string" + }, + "school": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "type": "object" +} - added
Input schema / properties / connections_ofAdded value: +{ + "type": "string" +} - added
Input schema / properties / followers_ofAdded value: +{ + "type": "string" +} - added
Input schema / properties / network_distance / items / anyOfAdded value: +[ + { + "const": 1, + "type": "number" + }, + { + "const": 2, + "type": "number" + }, + { + "const": 3, + "type": "number" + } +] - removed
Input schema / properties / network_distance / items / typeRemoved value: -"string" - added
Input schema / properties / open_to_volunteeringAdded value: +{ + "type": "boolean" +} - added
Input schema / properties / past_companyAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / profile_languageAdded value: +{ + "items": { + "maxLength": 2, + "minLength": 2, + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +} - added
Input schema / properties / schoolAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / serviceAdded value: +{ + "items": { + "type": "string" + }, + "type": "array" +}
- Changed
linkedin_search_posts5 fields changed- added
Input schema / properties / content_typeAdded value: +{ + "enum": [ + "VIDEOS", + "IMAGES", + "JOB_POSTS", + "LIVE_VIDEOS", + "DOCUMENTS", + "COLLABORATIVE_ARTICLES" + ], + "type": "string" +} - added
Input schema / properties / date_posted / enumAdded value: +[ + "PAST_DAY", + "PAST_WEEK", + "PAST_MONTH" +] - added
Input schema / properties / save_custom_filterAdded value: +{ + "not": {} +} - added
Input schema / properties / save_searchAdded value: +{ + "not": {} +} - added
Input schema / properties / sort_by / enumAdded value: +[ + "RELEVANCE", + "DATE" +]
- Changed
linkedin_update_my_profile7 fields changed- changed
Input schema / additionalPropertiesPrevious value: -{}New value: +false - added
Input schema / properties / background_pictureAdded value: +{ + "additionalProperties": false, + "properties": { + "content": { + "type": "string" + }, + "content_type": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "metadata": { + "additionalProperties": false, + "properties": { + "duration": { + "type": "number" + } + }, + "type": "object" + } + }, + "required": [ + "content", + "content_type", + "filename" + ], + "type": "object" +} - added
Input schema / properties / bioAdded value: +{ + "type": "string" +} - removed
Input schema / properties / first_nameRemoved value: -{ - "type": "string" -} - removed
Input schema / properties / last_nameRemoved value: -{ - "type": "string" -} - added
Input schema / properties / pictureAdded value: +{ + "additionalProperties": false, + "properties": { + "content": { + "type": "string" + }, + "content_type": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "metadata": { + "additionalProperties": false, + "properties": { + "duration": { + "type": "number" + } + }, + "type": "object" + } + }, + "required": [ + "content", + "content_type", + "filename" + ], + "type": "object" +} - added
Input schema / properties / specificsAdded value: +{ + "additionalProperties": false, + "properties": { + "linkedin": { + "additionalProperties": {}, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "type": "object" +}
1 tool update
- Added
messaging_list_recent_messages
1 tool update
- Added
message_get_attachment
173 tool updates
- First observed
account_change_plan - First observed
account_connect - First observed
account_connection_status - First observed
account_get_subscription - First observed
account_list_attention - First observed
account_start_subscription - First observed
agent_capability_guide - First observed
agent_id_guide - First observed
calendar_cancel_event - First observed
calendar_create_calendar - First observed
calendar_create_event - First observed
calendar_delete_calendar - First observed
calendar_delete_event - First observed
calendar_get_calendar - First observed
calendar_get_event - First observed
calendar_list_calendars - First observed
calendar_list_events - First observed
calendar_restore_event - First observed
calendar_rsvp_event - First observed
calendar_update_calendar - First observed
calendar_update_event - First observed
chat_add_participant - First observed
chat_delete - First observed
chat_list_participants - First observed
chat_remove_participant - First observed
chat_update - First observed
email_create_draft - First observed
email_create_folder - First observed
email_delete_draft - First observed
email_delete_folder - First observed
email_get_attachment - First observed
email_get_draft - First observed
email_get_folder - First observed
email_get_thread - First observed
email_list_contacts - First observed
email_list_drafts - First observed
email_list_folder_messages - First observed
email_list_folders - First observed
email_list_messages - First observed
email_mark_read - First observed
email_mark_unread - First observed
email_move_or_label - First observed
email_read_message - First observed
email_resolve_folder - First observed
email_resolve_message - First observed
email_send - First observed
email_send_draft - First observed
email_trash - First observed
email_update_draft - First observed
email_update_folder - First observed
feedback_report_bug - First observed
feedback_request_feature - First observed
imap_connect - First observed
instagram_get_my_profile - First observed
instagram_get_profile - First observed
instagram_list_conversations - First observed
instagram_list_followers - First observed
instagram_list_following - First observed
instagram_read_conversation - First observed
instagram_send_message - First observed
instagram_update_my_profile - First observed
linkedin_accept_invitation - First observed
linkedin_cancel_or_refuse_invitation - First observed
linkedin_classic_get_applicant_resume - First observed
linkedin_classic_get_job_applicant - First observed
linkedin_classic_list_job_applicants - First observed
linkedin_comment_on_post - First observed
linkedin_create_post - First observed
linkedin_endorse_skill - First observed
linkedin_follow_user - First observed
linkedin_get_company - First observed
linkedin_get_inmail_credits - First observed
linkedin_get_job_posting - First observed
linkedin_get_job_posting_budget - First observed
linkedin_get_my_profile - First observed
linkedin_get_post - First observed
linkedin_get_profile - First observed
linkedin_get_profile_from_url - First observed
linkedin_get_search_parameters - First observed
linkedin_list_comment_replies - First observed
linkedin_list_contracts - First observed
linkedin_list_conversations - First observed
linkedin_list_followers - First observed
linkedin_list_following - First observed
linkedin_list_inbox_chats - First observed
linkedin_list_inboxes - First observed
linkedin_list_invitations - First observed
linkedin_list_job_postings - First observed
linkedin_list_managed_company_pages - First observed
linkedin_list_my_connections - First observed
linkedin_list_post_comments - First observed
linkedin_list_post_reactions - First observed
linkedin_list_user_posts - First observed
linkedin_list_user_relations - First observed
linkedin_react_to_message - First observed
linkedin_react_to_post - First observed
linkedin_read_conversation - First observed
linkedin_recruiter_get_applicant - First observed
linkedin_recruiter_get_applicant_resume - First observed
linkedin_recruiter_list_applicants - First observed
linkedin_recruiter_search_people - First observed
linkedin_remove_connection - First observed
linkedin_reply_to_comment - First observed
linkedin_resolve_company - First observed
linkedin_resolve_my_post - First observed
linkedin_resolve_person - First observed
linkedin_sales_navigator_search_people - First observed
linkedin_search_companies - First observed
linkedin_search_from_url - First observed
linkedin_search_jobs - First observed
linkedin_search_people - First observed
linkedin_search_posts - First observed
linkedin_select_contract - First observed
linkedin_send_invitation - First observed
linkedin_send_message - First observed
linkedin_start_conversation - First observed
linkedin_start_conversation_from_inbox - First observed
linkedin_submit_company_member_otp - First observed
linkedin_unfollow_user - First observed
linkedin_update_my_profile - First observed
linkedin_verify_company_member_email - First observed
linkedin_visit_profile - First observed
list_connected_accounts - First observed
message_add_reaction - First observed
message_delete - First observed
message_edit - First observed
message_forward - First observed
message_get - First observed
message_list_reactions - First observed
message_mark_read - First observed
message_remove_reaction - First observed
message_resolve_chat - First observed
message_send_native_media - First observed
message_send_voice_note - First observed
messaging_find_chat_by_user - First observed
messaging_list_chats - First observed
messaging_list_messages - First observed
messaging_resolve_recipient - First observed
messaging_send_message - First observed
messaging_send_to_contact - First observed
messaging_set_chat_state - First observed
messaging_set_composing - First observed
messaging_set_presence - First observed
messaging_start_chat - First observed
social_delete_comment - First observed
social_delete_post - First observed
social_list_comment_reactions - First observed
social_react_to_comment - First observed
social_remove_comment_reaction - First observed
social_remove_post_reaction - First observed
social_resolve_comment - First observed
social_update_comment - First observed
social_update_post - First observed
team_add_seats - First observed
team_invite_member - First observed
telegram_connect - First observed
webhook_create_destination - First observed
webhook_delete_destination - First observed
webhook_get_delivery_logs - First observed
webhook_get_destination - First observed
webhook_get_setup_guide - First observed
webhook_list_available_events - First observed
webhook_list_destinations - First observed
webhook_test_destination - First observed
webhook_update_destination - First observed
whatsapp_connect - First observed
whatsapp_get_profile - First observed
whatsapp_is_number_registered - First observed
whatsapp_list_contacts - First observed
whatsapp_list_conversations - First observed
whatsapp_read_conversation - First observed
whatsapp_send_message - First observed
whatsapp_start_conversation
Publisher details
- Operator
- Nilyo · Publisher source
- Operator website
- https://nilyo.com · Publisher source
- Vendor relationship
- First-party · Publisher source
- Documentation
- https://nilyo.com/setup-for-agents — connect the MCP (https://nilyo.com/mcp, OAuth 2.1 with dynamic client registration), then connect provider accounts from the conversation or the dashboard. · Publisher source
- Trust center
- https://nilyo.com/security (security overview; privacy policy at https://nilyo.com/privacy). No dedicated compliance portal yet. · Publisher source
- Restrictions
- Requires a Nilyo account (created during the OAuth flow, 7-day free trial, no card; paid plans afterwards at https://nilyo.com/pricing). Users connect their own provider accounts (LinkedIn, WhatsApp, Instagram, Telegram, Gmail, Outlook, IMAP, calendars). No admin approval, no custom OAuth app to create, no regional limit beyond ChatGPT/Claude availability.
Related MCP Connectors
Email, WhatsApp and Telegram for AI agents: send, campaigns, automations, contacts, agent inboxes.
Instagram, WhatsApp, LinkedIn DMs and media: full threads, dormant leads, human-approved follow-ups
Gmail, Outlook, Drive, OneDrive and calendars for AI agents. Many accounts, one endpoint, audit log.
AI-agent outreach: cold email, warmup, LinkedIn, Instagram, WhatsApp, verification, 200M leads
Related MCP Servers
AlicenseNot gradedqualityBmaintenanceEnables coding agents to discover, write, and test integrations for LinkedIn (Classic, Sales Navigator, Recruiter), WhatsApp, Instagram, Telegram, Gmail/Outlook/IMAP email, and Google/Outlook calendar by reading the live API contract and executing real calls on connected accounts.MIT- AlicenseAqualityDmaintenanceEnables AI assistants to manage social media accounts and CRM operations, including posting, analytics, inbox management, and customer management.22Apache 2.0
- AlicenseAqualityAmaintenanceYour real mailbox and calendar for your AI agent — Microsoft 365 via Graph or any IMAP — as 24 tools: read, search, attachments as text, sender history, drafting from identity and knowledge files, free-slot computation. Send, reply, delete and calendar writes need out-of-band human approval: the agent cannot approve its own actions.29211 PyPI10AGPL 3.0
- -licenseNot gradedqualityNot gradedmaintenanceGives AI assistants access to one or more IMAP/SMTP mailboxes and a professional Instagram account through Meta's official API, exposing 20 tools that search, read, send, draft, move and delete e-mail and that read profile metrics, comments and Direct while replying to comments, hiding spam, sending DMs and publishing images, carousels or Reels. Server-side guards enforce rules like the 24-hour Direct window and header-only tokens, credentials never reach the model, and every write is recorded to an audit trail.-
Glama MCP Gateway
Add one secure layer between your agents and this server.
social_delete_commentPosts: Delete commentADestructive Inspect
Delete one exact comment. Resolve post_id then comment_id; never use comment text as ID. Destructive. Post ID: Exact provider/Unipile post id; LinkedIn commonly uses a preformatted/base64-style post ID. Obtain with: linkedin_search_posts -> result.id; linkedin_list_user_posts -> result.id; instagram_list_user_posts -> result.id Never pass: post text, author user ID, URL unless a resolver tool explicitly accepts it. Comment ID: Exact comment id scoped to the identified post. Obtain with: linkedin_list_post_comments(post_id) -> comment.id; instagram_list_post_comments(post_id) -> comment.id Never pass: comment text, post_id.
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, so the explicit 'Destructive' warning is redundant but consistent. The description adds behavioral value by requiring exact ID resolution and forbidding text-based identifiers, which prevents accidental deletion of the wrong comment.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but organized into Post ID and Comment ID sections with clear do/don't lists. There is minor repetition of 'never use comment text as ID' at the top and again under Comment ID, but every sentence otherwise earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, ID-sensitive tool it covers target resolution, forbidden inputs, and provider-specific ID formats, and account disambiguation is handled in the schema. It does not mention return/confirmation behavior, but this is a deletion action and no output schema exists to require it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the input schema already contains the same ID-resolution guidance for post_id and comment_id. The description adds no meaning beyond the schema, so the high-coverage baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening phrase 'Delete one exact comment' names a specific verb and resource, with 'one exact' distinguishing it from bulk or fuzzy operations. The title 'Posts: Delete comment' plus this description clearly separates it from siblings like social_delete_post and social_update_comment.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs the agent to resolve post_id first, then comment_id, and states what must never be passed (comment text, author user ID, URL, post_id in comment_id). It names concrete resolver tools for obtaining valid IDs, giving the agent a clear path to correct invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.