Nilyo
Server Details
Your own LinkedIn, WhatsApp, Instagram, Telegram, Email and Calendar accounts, usable from any agent
- Status
- Healthy
- Uptime
- 99.7% over 42 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- nilyo-com/nilyo-mcp
- GitHub Stars
- 0
- Server Listing
- Nilyo
TDQS
Scored across 184 tools
The set contains multiple overlapping namespaces for the same actions: generic messaging_* / message_* / chat_* coexist with provider-specific tools like whatsapp_send_message, linkedin_send_message, and instagram_send_message. Similarly social_* comment/post tools overlap with linkedin_* and instagram_* equivalents, and account_connect overlaps with whatsapp_connect, telegram_connect, and imap_connect. Descriptions attempt to draw boundaries, but agents can easily misselect among many near-duplicate operations.
Most tools follow a predictable snake_case domain_verb_noun pattern, with clear provider prefixes such as linkedin_, calendar_, email_, webhook_, and whatsapp_. However, retrieval verbs vary (get vs read vs resolve vs list), and the coexistence of message_, messaging_, and chat_ namespaces plus the un-prefixed list_connected_accounts creates minor inconsistency.
With 184 tools, the surface is extremely large and exceeds any reasonable scoped integration. Many tools duplicate capability across generic, provider-specific, and resolver layers, so the count is far beyond what is needed for the stated domain and actively harms coherence.
Coverage is very broad: email, calendar, LinkedIn, Instagram, WhatsApp, Telegram, webhooks, billing, team, and feedback all have substantial lifecycle support, including resolvers and guides. Minor gaps remain, such as LinkedIn job posting creation/update/delete and Instagram post creation, but most core workflows are covered.
Available Tools
184 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 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, idempotentHint=false, destructiveHint=false, and openWorldHint=true, so the mutation/non-idempotent profile is covered. The description adds the useful 'Resolve chat_id independently from user_id' constraint, but says nothing about what happens when the user is already a participant, notification behavior, or permission 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 purpose is front-loaded in the first clause, which is good, but the remainder is a dense run-on that repeats schema content verbatim (chat_id definition, 'Never pass' lists) and mixes chat-ID and user-ID guidance without clear separation. It is informative but not tight.
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 mutation tool, the description thoroughly covers identifier resolution but omits outcome behavior: success/failure semantics, idempotency effects, or what the caller gets back. Adequate for calling the tool, but incomplete for predicting its effects.
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 parameters are already documented in the schema — including much of the same 'Obtain with'/'Never pass' text that appears in the description (a notable duplication in chat_id). The description adds marginal value via the cross-ID resolution chain, 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+resource+scope: 'Add an exact provider user to an exact group chat.' An agent can immediately distinguish this from chat_remove_participant, chat_list_participants, and messaging_start_chat without opening a 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 extensive guidance on how to obtain chat_id and user_id ('Obtain with: provider list conversations/inbox chats -> chat.id') and what never to pass, but it never states when this tool should be chosen over alternatives such as messaging_start_chat or messaging_send_message, nor any preconditions. Usage is implied rather than framed as a decision.
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 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 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?
Annotations already cover readOnly/idempotent/non-destructive, so safety needs no restating. The description adds a genuinely behavioral fact not in the annotations: on IMAP/Exchange-over-IMAP the email id encodes folder+UID and CHANGES when the message is moved or a draft updated, so ids must be reused from the last operation. It does not describe the returned payload (bytes vs. URL vs. base64), which is the remaining behavioral 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?
The purpose is front-loaded, but the body is heavy and repetitive: 'Email provider ID: Exact email ID returned by Nilyo...' and the IMAP id-instability sentence appear verbatim in both the description and the schema, and the never-pass lists are restated multiple times. A tighter statement of the chain and the one non-obvious caveat would carry the same information in half the space.
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-id retrieval tool with full schema coverage and read-only annotations, the input side is well covered. The gap is the output: with no output schema, the description never says what retrieval yields (raw bytes, a signed URL, base64, a saved file path) or how large attachments are handled, which an agent needs to act on the 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 100% and the description largely reproduces the schema text, so the baseline is 3. It earns an extra point for presenting the cross-parameter workflow ('resolve/list -> email_id -> read -> attachment.id -> retrieve') as a single ordered chain, which clarifies the dependency between the two required ids in a way the per-field schema text 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 opening sentence gives a specific verb and resource ('Retrieve one exact attachment') plus the provider scope (Gmail, Outlook/Microsoft, IMAP), which is enough to separate it from generic read/list tools. However, it never names the sibling it pairs with (email_read_message) or states the contrast explicitly, so the differentiation is inferred from the required chain 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 'Required chain: resolve/list email -> email_id -> read email -> attachment.id -> retrieve' tells the agent exactly what must happen before invoking, and the repeated 'Never pass' clauses (filename, URL, RFC Message-ID, subject, stale IMAP ids) are explicit exclusions. This is about as prescriptive as a usage section gets.
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 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?
Annotations already cover safety (readOnly/idempotent/non-destructive), and the description adds real operational context beyond them: IMAP pages capped at 50 live messages, keep limit ~20 to avoid timeouts, an empty page is not 'zero emails' without a filter, and IMAP IDs change on move/update. No auth or error-mode detail, but the added traits are genuinely useful.
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 well, but the long 'Email provider ID' block is verbose and partly duplicates guidance that matters more to read/move tools, and the folder ID text repeats the folder_id schema description verbatim. Information-dense but not tight.
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, yet the description explains that listing yields email.id and that totals must come from email_list_folders, plus IMAP page caps and cursor-based paging. For a 9-parameter tool with IMAP quirks this is nearly complete, with only the to/from/any_email semantics left uncovered.
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?
At 33% schema coverage the description must compensate. It documents after/before as ISO 8601 UTC datetimes with a 'today' hint, the limit constraint, and folder_id's exact-ID requirement. However to, from, and any_email have no description anywhere in either the schema or the text, leaving meaningful 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 with scope: 'List messages inside one exact folder.' The 'one exact folder' scoping distinguishes it from a broader message listing, but it never names the sibling email_list_messages, so the differentiation is inferred rather than explicit.
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 IMAP workflow (list folders -> select folder.id -> list messages -> email.id -> read/action) and a clear when-not: for totals use folder.total_count/unread_count from email_list_folders instead of listing. It stops short of explicitly contrasting with the email_list_messages sibling for cross-folder listing.
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 readBInspect
Mark one exact email read. Resolve human email reference -> email_id first. Email provider ID: Exact email ID returned by Nilyo 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 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 declare the safety profile (mutation via readOnlyHint=false, not destructive, not idempotent), and the description adds nothing beyond that about the effect of marking read. The ID-lifecycle warning is duplicated verbatim from the input schema, so it earns no transparency credit 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?
The first sentence is tight and front-loaded, but everything after it is the parameter description pasted wholesale into the body, duplicating the schema field-by-field. Roughly 80% of the text is redundant with structured data.
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 annotations cover the safety posture, so the description only needs to cover the operation plus ID hygiene, which it does. It omits any note on provider-specific behavior of read state (e.g., server sync effects), leaving it merely 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 description coverage is 100%, so the schema already carries the full ID semantics and account_id guidance. The description simply restates the email_id text without adding format, validation, or fallback meaning. 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 opening sentence gives a specific verb+resource+scope ('Mark one exact email read'), which distinguishes it from bulk operations. It does not explicitly name its closest sibling email_mark_unread, but the 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?
It states a prerequisite workflow ('Resolve human email reference -> email_id first') and where to obtain the ID, which implies usage. It never says when to use this versus email_mark_unread or what happens if the email is already read.
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 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 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 cover the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=true), so the bar is lower, and the description adds genuinely useful non-obvious behavior: on IMAP/Exchange the id encodes folder+UID and changes on move or draft update, so a stale id silently targets the wrong message. It doesn't describe the resulting state change beyond 'unread', but the ID-volatility warning is real added 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?
Purpose is correctly front-loaded in the first sentence, but the remainder is a long block that largely restates the schema's email_id text, including a run-on 'Obtain with / Never pass' list that is hard to parse. It is thorough but not tight.
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-required-param mutation with no output schema, the ID resolution path is covered exhaustively and annotations carry the safety semantics. The only real gap is the absence of any routing versus email_mark_read / email_trash.
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's ID guidance is essentially a verbatim duplicate of the email_id schema description, adding no syntax or format detail the schema lacks, and account_id is not discussed at all in the description body.
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 with scope ('Mark one exact email unread'), which is unambiguous and immediately separable from its sibling email_mark_read. An agent knows exactly what state transition is requested.
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 strong prerequisite ('Resolve email_id first') and routes to the tools that produce the id, but never says when to choose this over email_mark_read or email_trash, nor any when-not condition. Usage is implied by the verb rather than stated.
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 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 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 declare a non-read-only, non-idempotent, open-world mutation, and the description adds genuinely new behavioral context: on IMAP the id encodes folder+UID and CHANGES after a move, so result.id must be reused. That is material, non-obvious behavior beyond the annotations. It does not contradict the annotations (mutation allowed, not destructive).
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 well with the core operation and the id-change caveat, but the back half is a near-verbatim paste of the schema's email_id and folders_ids descriptions, producing heavy redundancy. Padding rather than earning each 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?
No output schema exists, and the description responsibly explains the return value ('the result is the email after the change') plus the ID-reuse implication. For a state-changing tool with annotations covering safety, this is largely complete, though the opaque 'specifics' parameter is never addressed.
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?
Coverage is 50%; email_id and folders_ids semantics are explained, but the same text already appears in the schema parameter descriptions, so the description adds little beyond what the schema provides. The 'specifics' object parameter is undocumented in both places, so the description fails to 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 and resource with scope: 'Move/label one exact email.' An agent can distinguish it from email_trash or email_mark_read by the resource and operation. However, it never explicitly routes against those siblings, so it stops short of a 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?
Gives strong 'how' guidance for parameter resolution (resolve email_id independently, resolve folder names to folder.id, never pass 'Inbox' strings). But it offers no explicit when-to-use-this-vs-alternatives guidance — e.g., versus email_trash, email_update_folder, or email_mark_read — leaving tool selection to inference.
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 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 readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=false, so the safety profile is fully covered by structured data. The description adds that it spans multiple providers and returns body/headers, which is useful but modest. No permissions, rate-limit, or failure-mode context is added.
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 the operation stated first and the workflow hint second. No 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?
For a read-only tool with rich annotations and fully documented parameters, the description covers what it does and roughly what it returns (body/headers). There is no output schema, but a read of a single message needs little more; return-format details would be a minor addition.
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 email_id field description is unusually thorough (IMAP UID instability, what not to pass). The description itself adds no parameter guidance, 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 specific verb (Read) and resource (a specific email including body/headers), and names the providers (Gmail, Outlook, IMAP). It is clearly a single-message read, distinguishable from email_list_messages, though it does not explicitly contrast with email_get_thread or email_resolve_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?
Gives sequencing context: 'Use after email_list_messages and before a contextual reply or cross-channel decision.' That tells the agent when in the workflow to reach for it. It lacks explicit exclusions versus thread- or resolve-oriented siblings, 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.
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 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?
Annotations already declare this as a safe, idempotent, closed-world read (readOnlyHint/idempotentHint/destructiveHint=false), so the description doesn't need to restate the safety profile. It adds genuinely useful behavior the annotations can't carry: IMAP ids encode folder+UID and change on move or draft update, so the last returned id must always be reused, plus explicit 'never pass' guidance (subject, stale ids, RFC Message-ID). It still says nothing about result ordering or pagination 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 sentence and the IMAP fallback are front-loaded and well ordered. However, the bulk of the text is generic provider-ID/reply-reference/thread-ID boilerplate that is repeated across email tools and is only tangentially about a resolution tool, which dilutes the signal for an agent reading this specific definition.
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 0 required parameters, the description does convey what the tool returns (email candidates with provider id and thread_id) and how to obtain each id, which is reasonably complete for a read-only resolver. The remaining gap is parameter-level meaning for the seven undocumented filter/pagination inputs.
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% (account_id alone) across 8 parameters, so the description carries the burden and does not meet it. It never names or explains to, from, any_email, after, before, limit or cursor, and the words 'sender, recipient, subject or date' are only loosely suggestive of to/from/any_email/date filters. An agent must guess at the filter semantics and at how limit/cursor interact.
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 names a specific verb+resource (search/list email candidates) and a concrete outcome (mapping a human reference like sender, recipient, subject or date to an exact email_id) ahead of downstream read/reply/trash/move operations. It is clearly distinct in intent from a plain listing tool. It stops short of explicitly contrasting itself with the very similar email_list_messages sibling, which it only cites as a source of ids.
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 when to use the tool (to resolve a human reference before read/reply/trash/move/attachment operations) and gives an explicit alternative path for one case: on generic IMAP, when account-wide listing is unavailable, use email_list_folders then email_list_folder_messages. There is no general when-not guidance for the non-IMAP case, so no exclusions for Gmail/Outlook users.
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: TrashADestructiveInspect
Trash one exact email. Resolve email_id first; destructive mailbox action. Email provider ID: Exact email ID returned by Nilyo 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 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 idempotentHint=false, so the safety profile is covered. The description adds genuinely useful non-annotation behavior: on IMAP the ID encodes folder + UID and changes when the message moves, so the id from the last operation must be reused. That volatility caveat is real behavioral context 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 lead sentence is well front-loaded, but the description then duplicates the long ID-resolution paragraph that already appears in the schema, so several sentences do not earn their place by adding new information. Net effect is redundancy rather than sharp concision.
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 100% schema coverage, destructive annotations, and no output schema required, the definition supplies everything needed to invoke correctly: the target ID source, the required resolve-first step, and the ID-stability caveat. Only the trash-vs-permanent-delete distinction is left unstated.
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 email_id guidance in the description is essentially a verbatim repeat of the schema text, adding no new meaning. The account_id semantics (multi-account disambiguation) are likewise already fully documented in 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?
States a specific verb and resource ("Trash one exact email") with clear single-message scope, which separates it from bulk or move/label operations like email_move_or_label. It does not explicitly name the sibling it differs from, and leaves some ambiguity about whether "trash" means move-to-trash-folder (recoverable) versus permanent removal, so it stops short of a 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?
Gives one prerequisite ("Resolve email_id first") and flags the destructive nature, which implies when to use it. However, it never names an alternative (e.g., email_move_or_label to relocate instead of trash) or states when-not-to-use, so 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.
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_comment_on_postInstagram: Comment on postADestructiveInspect
Publish an approved top-level text comment on one exact Instagram post. Resolve/read the post first; reuse post.id, then read comments for context. This does not reply to a specific comment. No attachments or comment_as are supported here. Publish only the exact user-requested/approved text and target. Never automatically retry a failed, partial or timed-out write: inspect instagram_list_post_comments before deciding another send.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | Final comment text explicitly requested/approved by the user for this exact post and connected account. | |
| post_id | Yes | Exact Instagram post.id (shortcode) from instagram_list_user_posts or instagram_get_post. Never use caption, author ID, numeric media PK, LinkedIn post ID or full URL; resolve a URL with instagram_get_post first. | |
| account_id | No | Owned Instagram account_id from list_connected_accounts(provider='instagram'); omit only when one Instagram account is connected. Never use a profile, post or another user's account ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false and openWorldHint=true, but the description goes further by disclosing behavior the annotations cannot: unsupported payload features (no attachments, no comment_as) and a hard no-auto-retry rule for failed/partial/timed-out writes with a recovery step. For a non-idempotent public write, that is exactly the operational context an agent needs.
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 action and every sentence carries an instruction, but there is mild redundancy: 'approved top-level text comment on one exact Instagram post' and 'publish only the exact user-requested/approved text and target' say substantially the same thing. Still dense and skimmable, with 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?
With no output schema, the description covers prerequisites, payload limits and failure handling, which is most of what is needed for a write tool. It does not say what a successful publish returns (e.g. the new comment identifier) or what errors surface, a minor gap 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%, so the baseline is 3, and the schema already specifies post_id format/derivation and account_id provenance. The description adds incremental value by implying the allowed payload shape ('top-level text comment', 'no attachments or comment_as'), warning agents away from parameters that do not exist. It does not restate parameter syntax, which is already covered.
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 precise verb+resource+scope: 'Publish an approved top-level text comment on one exact Instagram post.' The qualifiers 'top-level' and 'This does not reply to a specific comment' carve out a distinct action from reply/comment-update operations in the sibling set (e.g. social_update_comment, linkedin_reply_to_comment). An agent can identify the tool's exact effect 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?
Gives an explicit prerequisite sequence (resolve/read the post first, reuse post.id, read comments for context) and an explicit failure-branch instruction: inspect instagram_list_post_comments before deciding another send. It also bounds the input ('publish only the exact user-requested/approved text and target'), so when-to-use and when-not-to-retry are both stated rather than inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_follow_userInstagram: Follow userAInspect
Follow one exact Instagram account from the selected owned account. Resolve/disambiguate with instagram_get_profile or instagram_get_profile_from_url, then use numeric profile.id, never specifics.messaging_identifier. Requires explicit user intent/approval. Preserve the native receipt: UserFollowed means followed; RelationRequest means a follow request was sent to a private account, not accepted. Never automatically retry a failed or ambiguous write; read the profile/following state first.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Numeric Instagram profile.id from instagram_get_profile or instagram_get_my_profile. Resolve/disambiguate the exact username first. Never use a display name, URL, @handle, LinkedIn ID, account_id or specifics.messaging_identifier. | |
| account_id | No | Owned Instagram account_id from list_connected_accounts(provider='instagram'); omit only when one Instagram account is connected. Never use a profile, post or another user's account ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare it a non-readonly, non-idempotent, open-world write with destructiveHint=false. The description adds behavior beyond that: the approval prerequisite, the native receipt semantics (UserFollowed = followed vs RelationRequest = pending request to a private account, not accepted), and a no-auto-retry policy on failed/ambiguous writes.
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 tight sentences, zero filler, front-loaded with the action and its scope. Each remaining sentence carries a distinct operational rule (prerequisite, receipt interpretation, retry policy), so nothing is 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 non-idempotent social write with no output schema, the description supplies everything an agent needs: how to identify the target, the approval gate, how to interpret the two possible success receipts, and the failure-handling policy. No material gap remains.
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 user_id and account_id are already fully documented in the schema. The description restates the resolve-then-use-profile.id workflow and the messaging_identifier prohibition, which mirrors rather than extends the schema text. 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 ('Follow one exact Instagram account') plus the scope constraint ('from the selected owned account'), which cleanly separates it from linkedin_follow_user and the read-only instagram_get_profile siblings. An agent can identify the action 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?
Explicitly instructs the agent to resolve/disambiguate via instagram_get_profile or instagram_get_profile_from_url first, mandates numeric profile.id over specifics.messaging_identifier, and requires explicit user intent/approval before calling. It also states the when-not case: never automatically retry a failed or ambiguous write.
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_postInstagram: Get postARead-onlyIdempotentInspect
Read and resolve an Instagram post from its shortcode or Instagram post/reel URL before liking or commenting. Reuse returned post.id; confirm the post and author. URLs are parsed locally, never fetched.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Owned Instagram account_id from list_connected_accounts(provider='instagram'); omit only when one Instagram account is connected. Never use a profile, post or another user's account ID. | |
| post_id_or_url | Yes | Instagram shortcode or HTTPS Instagram /p/, /reel/ or /tv/ post URL. Only the shortcode is sent to V2; no URL is fetched. Reuse returned post.id for writes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint and destructiveHint=false, so safety is covered. The description adds genuinely new context: URLs are 'parsed locally, never fetched', which tells the agent no network fetch occurs for the URL, and it directs reuse of the returned post.id for subsequent writes.
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, front-loaded with the core action, then workflow, then the behavioral note. No filler and every clause carries 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?
No output schema exists, and the description hints at the return value ('reuse returned post.id', 'confirm the post and author'), enough for a read-only resolution tool. Return shape is not detailed, but annotations and the schema cover the essentials.
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 (account_id, post_id_or_url) are already fully documented in the schema, including the account_id scoping rule. The description largely restates what the schema provides, 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 specific verb and resource ('read and resolve an Instagram post') and names the input forms (shortcode or /p/, /reel/, /tv/ URL). An agent can distinguish it from instagram_list_post_comments, instagram_like_post and instagram_comment_on_post 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?
Gives clear situational context: use it 'before liking or commenting' to obtain and confirm the post. There are no explicit exclusions or named alternatives, but the pre-write workflow is unambiguous.
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
Resolve an Instagram username or @handle to a profile; for URLs use instagram_get_profile_from_url. Reuse numeric profile.id for instagram_list_user_posts and instagram_follow_user; specifics.messaging_identifier is only for messaging.
| Name | Required | Description | Default |
|---|---|---|---|
| user_id | Yes | Instagram username, @handle, numeric profile ID or HTTPS profile URL; resolves to profile.id for posts/follow actions. Not a human display name, post URL, account_id or messaging_identifier. | |
| 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, openWorld, and non-destructive behavior, so the description adds useful context about reusing the numeric profile.id and the scope of messaging_identifier. It does not add deeper behavioral details like permission requirements, private-profile handling, or rate limits, but its output-usage guidance is valuable 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?
Front-loads the core action and then adds the critical routing and output-reuse guidance in a compact, single-sentence structure with no filler. Every clause serves a distinct 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?
For a two-parameter, read-only resolver with full schema coverage and no output schema, the description provides the key routing alternative and output-field reuse guidance. 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?
Schema description coverage is 100%, so the schema already documents user_id and account_id fully. The description adds a routing nuance for URLs but does not add meaning beyond the schema parameters themselves, 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?
States a specific verb (Resolve) and resource (Instagram username or @handle to a profile), and explicitly distinguishes itself from instagram_get_profile_from_url for URL input. An agent can tell exactly what this tool does and when not to use it.
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?
Names the alternative for URLs and gives explicit reuse guidance for profile.id with instagram_list_user_posts and instagram_follow_user, plus an exclusion for messaging_identifier. This covers when to use, when to use a sibling instead, and how to use the output downstream.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_get_profile_from_urlInstagram: Get profile from URLARead-onlyIdempotentInspect
Resolve an Instagram profile URL or @handle to the exact profile before posts/follow actions. Only Instagram profile URLs are parsed; no arbitrary URL is fetched. Reuse numeric profile.id, never specifics.messaging_identifier, and disambiguate the intended identity.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Owned Instagram account_id from list_connected_accounts(provider='instagram'); omit only when one Instagram account is connected. Never use a profile, post or another user's account ID. | |
| profile_url | Yes | Instagram username, @handle, numeric profile ID or HTTPS profile URL; resolves to profile.id for posts/follow actions. Not a human display name, post URL, account_id or messaging_identifier. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnly, idempotent, openWorld, non-destructive), so the bar is lower; the description adds real behavioral context: it only parses Instagram profile URLs and fetches nothing arbitrary, and it warns to carry forward numeric profile.id rather than specifics.messaging_identifier. It does not describe the returned object shape, but the safety-relevant disclosures are useful.
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, front-loaded with the core action, then scope limit, then the identity-handling rule. No filler; each clause carries operational weight.
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-parameter read tool with no output schema, the description covers the resolution target and the downstream identifier to reuse, which is the critical piece an agent needs. A brief note on what the resolved profile contains 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%, so the schema already documents profile_url's accepted forms (username, @handle, numeric ID, HTTPS URL) and the account_id ownership rule. The description reinforces the profile.id vs messaging_identifier distinction but adds little beyond the schema, so 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 specific verb and resource: 'Resolve an Instagram profile URL or @handle to the exact profile', which is distinct from a plain profile-by-id lookup. It also scopes the input ('Only Instagram profile URLs are parsed; no arbitrary URL is fetched'). It does not explicitly contrast itself with the sibling instagram_get_profile, so differentiation is partial.
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 precondition for use: 'before posts/follow actions', plus an explicit exclusion ('no arbitrary URL is fetched'). However, it never names an alternative tool (e.g. instagram_get_profile for ID/username-only lookups), so the routing decision is left partly to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_like_postInstagram: Like postAInspect
Like one exact Instagram post from the selected owned Instagram account. Read/resolve the post with instagram_get_post or instagram_list_user_posts first and reuse post.id. Sends the fixed V2 reaction instagram_like; no arbitrary reaction. Act only on the user's explicit request/approval. Never automatically retry a failed or ambiguous write; inspect the post's user_reacted state first.
| Name | Required | Description | Default |
|---|---|---|---|
| post_id | Yes | Exact Instagram post.id (shortcode) from instagram_list_user_posts or instagram_get_post. Never use caption, author ID, numeric media PK, LinkedIn post ID or full URL; resolve a URL with instagram_get_post first. | |
| account_id | No | Owned Instagram account_id from list_connected_accounts(provider='instagram'); omit only when one Instagram account is connected. Never use a profile, post or another user's account ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the write profile (readOnly=false, non-idempotent, non-destructive, open-world). The description adds the fixed V2 reaction (no arbitrary reaction), the approval requirement, and — critically — that retrying an ambiguous write is forbidden and prior user_reacted state must be checked, which is exactly the non-idempotency guidance the annotation can't express.
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 tightly scoped sentences, front-loaded with the action and scope before prerequisites, reaction constraint, approval gate, and retry policy. No filler; every sentence carries a distinct operational instruction.
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 tool with no output schema, it covers prerequisites, reaction type, approval and retry policy well. It stops short of saying what a successful response returns (e.g., resulting reaction state) and whether specific scopes/permissions are 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%, so both post_id and account_id are already fully documented with format and anti-patterns. The description's 'reuse post.id' and 'selected owned Instagram account' restate schema content rather than extend it; 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 specific verb (Like) and resource (one exact Instagram post) scoped to the selected owned Instagram account. Names the resolution siblings (instagram_get_post, instagram_list_user_posts), so the agent can immediately tell this apart from read tools in the family.
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 prerequisite workflow (resolve the post first and reuse post.id), a gating condition (act only on the user's explicit request/approval), and a prohibition with an alternative (never auto-retry; inspect user_reacted state first). When-to-use and when-not-to-use are both covered.
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_list_post_commentsInstagram: List post commentsARead-onlyIdempotentInspect
Read comments on an exact Instagram post before composing a comment or checking whether an earlier uncertain comment was applied. Resolve post.id with instagram_list_user_posts/instagram_get_post first. Cursor pagination only; preserve account/post and sort order with next_cursor, no offset.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Requested page ceiling, not a guaranteed count; keep it small and follow next_cursor sequentially. | |
| cursor | No | Opaque next_cursor returned by the prior page. Preserve the same account and target; never invent a cursor or use offset. | |
| post_id | Yes | Exact Instagram post.id (shortcode) from instagram_list_user_posts or instagram_get_post. Never use caption, author ID, numeric media PK, LinkedIn post ID or full URL; resolve a URL with instagram_get_post first. | |
| sort_by | No | ||
| account_id | No | Owned Instagram account_id from list_connected_accounts(provider='instagram'); omit only when one Instagram account is connected. Never use a profile, post or another user's account ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false, so the safety profile is covered. The description adds genuinely new behavior: cursor-only pagination with no offset support and the requirement to preserve account/post and sort order across pages. It stops short of disclosing return shape, ordering guarantees per sort_by, 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?
Three sentences, zero filler, and the primary action plus its most likely motivation are front-loaded before the prerequisite and pagination caveats. Every clause carries an actionable constraint.
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 paginated list with no output schema and annotations covering safety, the definition supplies the prerequisite resolution path and pagination contract, which is what an agent needs to call it correctly. It omits any indication of what a returned comment contains or the default page size, minor gaps for a 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 80% and the schema already documents limit, cursor, post_id and account_id with strong guidance (including what NOT to pass as post_id). The description mostly restates the cursor/no-offset discipline already in the schema and adds nothing for the undescribed sort_by enum. 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 ('Read comments on an exact Instagram post') and implicitly contrasts with the write-side sibling instagram_comment_on_post by framing it as the read step before composing. The 'exact post' qualifier and the platform prefix distinguish it from linkedin_list_post_comments, so an agent can route correctly 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?
Gives concrete use contexts ('before composing a comment or checking whether an earlier uncertain comment was applied') and a hard prerequisite ('Resolve post.id with instagram_list_user_posts/instagram_get_post first'). It names the resolution alternatives but states no explicit when-not-to-use case, which keeps it at 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instagram_list_user_postsInstagram: List user postsARead-onlyIdempotentInspect
List posts authored by another resolved Instagram account or 'me'. Resolve a username with instagram_get_profile or a profile URL with instagram_get_profile_from_url, then reuse numeric profile.id. Results include post.id (shortcode) for likes/comments. Cursor pagination only: preserve account_id/user_id with next_cursor, no offset. One page is not an exhaustive list; private accounts depend on the connected account's access.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Requested page ceiling, not a guaranteed count; keep it small and follow next_cursor sequentially. | |
| cursor | No | Opaque next_cursor returned by the prior page. Preserve the same account and target; never invent a cursor or use offset. | |
| user_id | Yes | me | |
| account_id | No | Owned Instagram account_id from list_connected_accounts(provider='instagram'); omit only when one Instagram account is connected. Never use a profile, post or another user's account ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld/non-destructive, so the safety bar is met structurally. The description still adds real value: cursor-only pagination with no offset, preserving account_id/user_id across pages, 'one page is not an exhaustive list', and access-dependent visibility for private accounts.
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 action, then prerequisites, then return/pagination caveats in dense declarative sentences. Every sentence earns its place with 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?
Complete for a filterable, paginated list tool despite having no output schema; the description partly compensates by noting post.id (shortcode) in results. Minor remaining gap is the full return shape, but annotations and schema carry the rest.
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%, so most parameters are self-documenting. The description reinforces workflow meaning for user_id/profile.id reuse and the cursor/account_id pairing, adding marginal but useful context 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 (List) and resource (posts authored by a resolved Instagram account or 'me'), and implicitly distinguishes itself from the single-post sibling instagram_get_post and profile siblings. An agent can tell what it returns and for whom 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?
Explicitly prescribes the prerequisite workflow: resolve a username via instagram_get_profile or a URL via instagram_get_profile_from_url, then reuse the numeric profile.id. It also states the pagination constraint (cursor only, no offset) and the private-account caveat, leaving little to inference.
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 | LinkedIn Classic mentions belong in text: @ followed by the resolved person's Classic ACo... ID or the company's numeric ID (for example @1441). Resolve people with linkedin_get_profile_from_url/linkedin_resolve_person and companies with linkedin_resolve_company/linkedin_search_companies; disambiguate every target before publishing. Never use a display name, profile URL, company slug, URN, Sales Navigator or Recruiter ID as a mention. Example after resolving both targets: 'Thanks @ACo_RESOLVED_MEMBER for working with @1441.' The API replaces each token with the target's name and mention metadata; no separate mentions field is needed. Approve the final text and mentioned identities before the write; never retry an ambiguous write automatically. | |
| 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 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 destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the write/non-idempotent profile is covered. The description adds a consent guardrail ('only when the user has asked to publish the final reply'), which is useful, but it omits post-publication behaviors (that a comment can later be edited/deleted via social_update_comment/social_delete_comment) and any rate or visibility 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 short sentences, front-loaded with the action and followed by the guardrail. Every clause earns its place and nothing is redundant with 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 destructive write with no output schema and full parameter documentation, the description covers the action, the required identifier, and the consent precondition, while annotations carry the safety profile. It is essentially complete, with only minor gaps around alternatives and post-publication editability.
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 fully documents post_id, text, and account_id, including the mention-token mechanics and how to obtain a post ID. The description only repeats 'Requires post_id' and adds no meaning beyond the structured field.
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 (publish a comment/reply on a LinkedIn post) and adds the scope 'on behalf of the user' and a required identifier. It clearly says what happens, but it conflates 'comment' and 'reply' and does not distinguish itself from the sibling linkedin_reply_to_comment, which is a plausible alternative for the same 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?
Gives real when-to-use context: 'Use after reading the post/comments and only when the user has asked to publish the final reply,' establishing a read-then-write ordering and a consent gate. It stops short of naming the alternatives (linkedin_reply_to_comment, linkedin_create_post) or stating 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.
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 | LinkedIn Classic mentions belong in text: @ followed by the resolved person's Classic ACo... ID or the company's numeric ID (for example @1441). Resolve people with linkedin_get_profile_from_url/linkedin_resolve_person and companies with linkedin_resolve_company/linkedin_search_companies; disambiguate every target before publishing. Never use a display name, profile URL, company slug, URN, Sales Navigator or Recruiter ID as a mention. Example after resolving both targets: 'Thanks @ACo_RESOLVED_MEMBER for working with @1441.' The API replaces each token with the target's name and mention metadata; no separate mentions field is needed. Approve the final text and mentioned identities before the write; never retry an ambiguous write automatically. | |
| 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 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?
Annotations already declare destructiveHint=true, idempotentHint=false and openWorldHint=true, so the safety profile is partly covered. The description still adds real value by flagging the public side effect, the approval requirement, and the identity-ambiguity risk ('never retry an ambiguous write automatically'), which reinforces non-idempotency in operational terms.
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: the action and target scope come first, the safety precondition second. No filler, no repetition of schema 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 write tool with no output schema, the description plus the annotations and the richly documented schema cover what an agent needs: what it publishes, under whose identity, and the approval gate. Return-value behavior is not required here.
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 itself carries very detailed parameter docs (mention token resolution, post_as identity rules, account_id selection). The description only adds the framing that post_as targets a managed company page, which is already stated in the schema, so it adds little beyond structured data.
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 ('Publish a LinkedIn post') and scopes it precisely to the user's own account with an optional managed-company-page target via post_as. That scope cleanly separates it from update/comment/react siblings, though no sibling is named explicitly to route the agent away from alternatives like social_update_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?
Gives a clear gating condition: use only after the user has clearly approved the final content and target identity. It does not, however, contrast this tool with alternatives (e.g. social_update_post for edits, or scheduling tools), so the agent gets a precondition but no explicit 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_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 userBInspect
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 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 non-read-only, non-idempotent, non-destructive, and open-world behavior, so the bar is lower. The description adds useful auth/precondition context ('connected personal account', resolve exact ID first) but does not disclose duplicate-follow behavior, rate limits, or notification 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 short sentences, front-loaded with the action and account scope, followed by the key prerequisite. No filler or 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 mutation tool with no output schema but with complete schema descriptions and annotations covering safety, the description supplies the key account context and ID-resolution prerequisite. It omits failure or duplicate-follow behavior, but this is not fatal given the structured 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 100%, so the schema already documents both parameters in detail. The description's 'Resolve the exact provider user_id first' reinforces the schema's existing warning against display names/URLs but adds no new syntax, format, or constraint.
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 ('Follow') and resource ('a LinkedIn user') with the scope 'from the connected personal account'. Clear, but it does not name or distinguish from sibling tools such as linkedin_unfollow_user 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?
Provides a prerequisite ('Resolve the exact provider user_id first') but no when-to-use, when-not-to-use, or alternative-tool guidance. It does not explain when to follow versus sending an invitation or using other LinkedIn relation tools.
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_company_follow_creditsLinkedIn: Get company follow creditsARead-onlyIdempotentInspect
Read the remaining LinkedIn credits for inviting members to follow a company page administered by the connected account: remaining_credit, credit_grant per reset and resets_on (ISO 8601 UTC). Use before linkedin_send_company_follow_invitation or after a credit-limit error. Requires the numeric company ID of an administered page (linkedin_list_managed_company_pages).
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Owned LinkedIn unipile_account_id from list_connected_accounts. Omit only when one LinkedIn account is connected; never use a member/company ID. | |
| company_id | Yes | Numeric LinkedIn company ID from linkedin_list_managed_company_pages or linkedin_resolve_company/linkedin_search_companies, then verify the page is administered. Never pass a name, URL, slug or URN. |
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 genuinely useful behavior: the exact returned fields, the reset semantics (credit_grant per reset, resets_on in ISO 8601 UTC) and the administered-page requirement. It stops short of noting rate limits or account-selection behavior, so a 4 rather than 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?
Two dense sentences with zero filler: the capability and returned fields come first, then the usage trigger and prerequisite. Every clause carries actionable 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?
There is no output schema, so the description's enumeration of return fields (remaining_credit, credit_grant, resets_on) is necessary and present, along with prerequisites, the error-recovery use case, and the sibling it precedes. 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?
Schema description coverage is 100%, so both parameters (account_id, company_id) are already fully documented with format rules and cross-references. The description restates the company_id requirement and its source but 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?
States a specific verb (read) and resource (remaining LinkedIn credits for company-page follow invitations) and enumerates the returned fields, distinguishing it from the sibling credit tool linkedin_get_inmail_credits. An agent can identify it 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?
Explicit when-to-use guidance: call before linkedin_send_company_follow_invitation or after a credit-limit error, and it names the prerequisite source for the company ID (linkedin_list_managed_company_pages). Both the trigger and the alternative are stated.
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 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 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, destructiveHint=false, and openWorldHint, so the safety profile is fully covered by structured data. The description only adds that it returns 'full post context,' which is minimal 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?
Two short sentences, front-loaded with the action and the key precondition. No filler, though 'by Nilyo post_id' is slightly awkward 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 two-param read tool with full schema coverage and full annotations, the description plus structured fields cover everything needed to call it correctly. A hint on return shape would help since there is no output schema, but it is 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?
Schema coverage is 100% and the post_id param description is extremely detailed (sources, never-pass guidance, format notes). The description adds nothing beyond the schema, so 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 states a clear verb+resource: 'Get a LinkedIn post by ... post_id.' This distinguishes it from list/search siblings well enough, though the odd phrasing 'by Nilyo post_id' muddles it slightly and it doesn't explicitly differentiate from linkedin_resolve_my_post or linkedin_list_user_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?
It says when to use it ('when you already know a post_id') and implies the precondition that you must have a post_id in hand, which implicitly steers agents toward search/list tools when they don't. It does not name the alternative explicitly nor state exclusions.
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 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?
Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower. The description still adds real behavior: it normalizes the URL (extract only the /in/{public_identifier}/ slug, ignore query parameters/fragments/trailing slash) and discloses that the result carries result.id, plus an internal delegation to 'Get User Profile'. It omits auth/account prerequisites and any rate-limit or failure behavior, which keeps it from 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?
The first sentence is well front-loaded, but the body then repeats itself with two glossary blocks ('LinkedIn system user ID: ...' and 'LinkedIn public identifier: ...') that read like injected reference material and cycle through the same extraction rules and 'Never pass' warnings three times. Substantial content does not earn its place in a tool 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 no output schema, the description compensates by naming the key return field (result.id) and its downstream consumers, and it clarifies URL normalization. Annotations cover the safety profile. It is close to complete for a 3-parameter resolver, missing only account-selection guidance and error 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?
Schema description coverage is 100%, so the baseline is 3. The description reinforces profile_url semantics ('extract ONLY john-doe-123 from the /in/{public_identifier}/ pathname') and the example URL, but the schema already states the URL format and that query parameters are ignored. with_sections and account_id are untouched in the description, so no meaning is added 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 and resource: 'Resolve a full LinkedIn person profile URL into the real LinkedIn profile and stable system user ID.' It also names the downstream dependency (result.id) and references the sibling it delegates to ('call Get User Profile'), which separates it from linkedin_get_profile and linkedin_resolve_person. Slightly diluted by glossary-style text that restates the same idea, 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?
Explicitly tells the agent when the output is needed: 'Use result.id for connection requests, new conversations and other actions requiring user_id.' It also lists alternative sources of a user_id (linkedin_get_profile, linkedin_search_people), giving comparative context. It stops short of stating the inverse condition ('use when you only have a URL'), so routing is inferred rather than fully spelled out.
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 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 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 declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is fully covered by structured data. The description adds chaining context but says nothing about pagination behavior or result limits, which matters for a list tool that exposes an offset parameter.
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 one-line purpose, then tightly packed chain notation with no filler sentences. The repetitive restatement of parameter guidance that also lives in the schema is mildly wasteful but does not obscure the core instruction.
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?
Input resolution is covered thoroughly for a 4-parameter tool, but with no output schema and an unexplained offset parameter, the agent gets no sense of how replies are returned or paged. For a listing tool this is a meaningful gap, though annotations and schema carry most of the remaining burden.
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%, which sets a baseline of 3. The post_id and comment_id text in the description is essentially a verbatim duplicate of the schema property descriptions, and account_id and offset receive no treatment in the description, so no meaning is added 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 and resource with scope: "List replies under one exact LinkedIn comment." The word "replies" plus the parent-comment scoping distinguishes it from linkedin_list_post_comments, which returns top-level comments, so an agent can tell the two apart. It stops short of explicitly naming that sibling as the 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?
Provides explicit prerequisites and an acquisition chain (resolve post -> post.id -> list comments -> comment.id -> replies) and clear exclusions ("Never pass: post text, author user ID, URL"). What it lacks is any statement of when this tool should be preferred over its siblings, but the chaining makes the intended slot in the workflow unambiguous.
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 followersBRead-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 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=true, idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds no behavioral context beyond that—no pagination behavior, rate limits, or result-ceiling details despite an offset parameter 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?
Two short sentences, front-loaded with the scope and then the key calling convention. Tight, though the second sentence partly duplicates the schema's user_id 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?
No output schema exists and the description says nothing about return shape or pagination, which matters for a list tool with an offset parameter. Annotations cover the safety profile, so the gap is moderate but real.
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%: user_id and account_id are richly documented in the schema, while offset is undocumented in both places. The description's 'me' tip largely restates the schema default/description, so it adds only marginal 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?
Specific verb 'List' with resource 'followers' and explicit scope (account owner or a known LinkedIn user). The directionality (followers vs following) is implicitly clear against the sibling linkedin_list_following, though that sibling is never named.
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 sentence about user_id='me' is parameter guidance rather than when-to-use. It implies the listing use case but gives no when-not conditions and never routes to alternatives like linkedin_list_following.
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 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 the safety profile (readOnly, idempotent, non-destructive, openWorld). The description goes beyond them by disclosing that provider availability may restrict following data for non-self users — a real behavioral constraint the annotations cannot express. It does not cover pagination 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?
Two sentences, zero waste, with purpose stated first and the parameter preference second. Every clause carries 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 read-only list tool with no output schema, the description covers purpose, the self-vs-other distinction, and a known data-availability limitation. It stops short of describing pagination behavior despite an offset parameter, which is the one 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 coverage is 67% and the user_id description is already extremely rich (how to obtain the ID, what never to pass). The description adds only a soft preference for 'me', which is a marginal complement to the schema's default and does not address the undocumented 'offset' parameter. 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: users followed by the connected account owner. The phrasing distinguishes it from linkedin_list_followers and linkedin_list_my_connections by-direction, though it never names those siblings explicitly, so differentiation requires the agent to reason it out.
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?
Offers a clear default directive ('Prefer user_id=me') and a caveat about provider availability for other users, which implies when this tool is useful. However it never routes the agent to alternatives (e.g. list_followers, list_user_relations) or states when not 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_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 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, openWorldHint and destructiveHint=false, so the safety profile is covered without the description. The description adds only a workflow hint, leaving return shape, pagination via offset, and result volume undisclosed.
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 resource and prerequisite front-loaded and no filler. Efficient, though it could organize the workflow note more explicitly.
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 no output schema, the description supplies purpose, prerequisite and intended use. The only meaningful gap is the undocumented offset/pagination behavior, which is minor here.
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 carry rich descriptions, while offset is undocumented in both places. The description echoes the post_id sourcing rule that the schema already states, so it adds little beyond the structured fields.
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 comments on a LinkedIn post'), which is clearly distinct from write siblings like linkedin_comment_on_post and linkedin_reply_to_comment. It does not, however, explicitly distinguish itself from linkedin_list_comment_replies, so an agent must infer that this returns top-level comments rather than 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?
Gives a clear prerequisite ('Requires post_id from search/list/get post') and a workflow cue ('Use before deciding which comments need a reply'). It stops short of naming alternatives or exclusion conditions, but the context is unambiguous.
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 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, destructiveHint=false, and openWorldHint=true, so the agent knows this is a safe, idempotent read operation. The description adds the reaction/people focus and engagement-analysis use case, but does not disclose pagination behavior via offset, whether authentication is required, or what the return shape looks like. 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?
Two short sentences with zero waste. The purpose is front-loaded in the first sentence, and the second sentence adds use-case context without padding. 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 list tool with rich annotations and no output schema, the description is minimally adequate: it says what is listed and why. However, it does not explain the return format, pagination via offset, or potential rate limits, which are relevant when no output schema exists. The definition is functional but leaves 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 67%: post_id has a detailed description and account_id has a description, while offset is undocumented. The description adds no parameter-level meaning beyond what the schema already provides, but the schema carries the important ID semantics. Baseline 3 reflects that the schema does most of the work, though the unaddressed offset parameter and lack of description-level clarification keep this from being higher.
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 people/reactions on a LinkedIn post.' An agent can immediately tell this is a read operation returning reaction data for a post. However, it does not differentiate itself from close siblings such as linkedin_list_post_comments or social_list_comment_reactions, so the agent must infer the distinction from 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 offers a use case ('engagement analysis or to identify who reacted'), which gives clear context for when to call it. But it names no alternatives and provides no exclusions or conditions for choosing this over linkedin_list_post_comments or social_list_comment_reactions. Usage 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.
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 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=true, destructiveHint=false, and idempotentHint=true, so the safety profile is fully covered. The description adds the workflow purpose (supplying post_id) but says nothing about pagination behavior despite an offset parameter, or the shape of the listing returned.
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, zero filler, with the action and the downstream-use guidance front-loaded. Nothing is wasted or buried.
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 should ideally convey the return shape and pagination. It mentions post_id, which is the key output, but leaves offset/pagination and the listing format unspecified, so an agent still lacks full 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%; user_id and account_id carry detailed schema descriptions, but offset has none. The description restates the source options ('connected LinkedIn user or a known provider user ID') but adds no syntax or format beyond what the schema already provides. Baseline 3 fits.
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 with scope: 'List posts authored by the connected LinkedIn user or a known provider user ID.' This distinguishes it from linkedin_get_post (single post), linkedin_search_posts (search), and linkedin_resolve_my_post, so an agent can route correctly without opening schemas.
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 the workflow: 'Use to locate a recent post and obtain its post_id before reading comments/reactions or replying.' This gives clear when-to-use context and downstream alternatives. It stops short of stating when-not to use it, so not 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_list_user_relationsLinkedIn: List user relationsBRead-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 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 only the 'visible' scoping qualifier; it says nothing about pagination behavior, result caps, or what happens for a private profile, which are the meaningful unknowns for a read 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 short sentences with zero filler, and the identity/scope constraint is front-loaded ahead of the usage guidance. Nothing is 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?
With no output schema, the description should at least sketch the return shape (list of related profiles? what fields?), and it does not. Given four parameters and a paginated list operation, the definition is minimally adequate but leaves the agent guessing about results and paging.
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%: user_id and account_id are well documented in the schema itself, while cursor and search are undocumented anywhere. The phrase 'by provider user ID' reinforces user_id but adds no syntax or format detail beyond the schema, and it does not compensate for the undocumented pagination and search 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 gives a clear verb and resource ('List a LinkedIn user's visible relations by provider user ID'), but 'relations' is undefined and ambiguous against siblings like linkedin_list_my_connections, linkedin_list_followers, and linkedin_list_following. An agent cannot tell whether 'relations' means followers, following, connections, or some union of them 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?
It provides a positive trigger ('Use when network graph context is requested for a known profile') but no exclusions or named alternatives, despite several overlapping sibling list tools. Usage is implied rather than delimited.
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 postBDestructiveInspect
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 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 already declare readOnly=false, destructive=true, idempotent=false and openWorld=true, so the safety profile is covered. The description adds only 'on behalf of the user' plus the intent gating; it never explains the non-idempotent behavior (re-reacting replaces the prior reaction) or what 'destructive' means for a reaction. Helpful but thin beyond 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?
Two short sentences, front-loaded with the action and followed by the constraint. 'Use a supported LinkedIn reaction value' is slightly redundant since the schema already enumerates the values, but the phrasing is tight overall.
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 is the only place to say what a successful call yields, and it says nothing about the resulting state or how to undo a reaction. Against rich annotations and 100% schema coverage the omission is tolerable, but a mutation that changes visible state on a public post warrants more 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%, with post_id sourcing, the reaction enum, and account_id selection all documented in the schema. The description adds no syntax, format, or fallback meaning beyond it, 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 specific verb+resource ('Add a LinkedIn reaction to a post') and scope ('on behalf of the user'), and the LinkedIn qualifier distinguishes it from siblings like instagram_like_post and message_add_reaction. It stops short of naming a sibling alternative, so it doesn't fully earn a 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?
Gives one real when-to-use condition ('only when the user's intent to react is clear'), which is genuinely useful gating guidance. However, it names no alternatives and offers no when-not guidance, e.g. no pointer to social_remove_post_reaction or linkedin_list_post_reactions, so usage remains 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.
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 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, idempotentHint=false and readOnlyHint=false, so the safety profile is covered. The description still adds useful context beyond annotations: that the user's network is mutated and that explicit user intent is required before calling.
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, front-loaded with the action, then precondition, then risk. No padding or redundant restatement of the tool name.
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 two-parameter tool with full schema coverage and annotations carrying the safety profile, the description covers purpose, prerequisite and caveat. It lacks detail on edge cases (target not currently connected, effect on pending invitations) and no output schema exists, but nothing essential to 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 user_id description is exceptionally detailed (resolvers, forbidden inputs, format). The description only echoes the 'resolve the exact provider user_id' point, so it adds little beyond what the schema already provides — 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?
States a specific verb+resource: 'Remove an existing LinkedIn relation/connection.' It is separable from nearby siblings like linkedin_unfollow_user and linkedin_cancel_or_refuse_invitation by the word 'connection', though it never names those siblings explicitly to remove 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?
Gives a clear precondition ('Resolve the exact provider user_id first') and a caution about when this is appropriate ('changes the user's network and requires explicit intent'). It stops short of explicitly contrasting with cancel/refuse invitation or unfollow alternatives.
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 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. LinkedIn Classic mentions belong in text: @ followed by the resolved person's Classic ACo... ID or the company's numeric ID (for example @1441). Resolve people with linkedin_get_profile_from_url/linkedin_resolve_person and companies with linkedin_resolve_company/linkedin_search_companies; disambiguate every target before publishing. Never use a display name, profile URL, company slug, URN, Sales Navigator or Recruiter ID as a mention. Example after resolving both targets: 'Thanks @ACo_RESOLVED_MEMBER for working with @1441.' The API replaces each token with the target's name and mention metadata; no separate mentions field is needed. Approve the final text and mentioned identities before the write; never retry an ambiguous write automatically. | |
| post_id | Yes | Exact post ID from post search/list. Post ID: Exact provider 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 declare destructiveHint=true and idempotentHint=false, but the description adds substantial behavioral context: it explains that mentions are resolved via @ tokens and replaced by the API, that targets must be disambiguated before publishing, that final text and identities must be approved, and that ambiguous writes should never be retried automatically.
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 organized into Post ID and Comment ID sections, but it duplicates much of the schema's property descriptions, making it somewhat longer than necessary.
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 lack of an output schema, the description covers the full workflow (ID resolution, optional reply reading, mention resolution, approval before write) and is complete enough for an agent to invoke the tool correctly. Annotations handle the safety profile, and the schema covers parameters.
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 including the mention syntax for text and ID sources. The description largely repeats this information rather than adding new parameter-level 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?
States a specific verb (reply) and resource (one exact LinkedIn comment) and explicitly contrasts with creating a new top-level comment, so the agent can distinguish it from siblings like linkedin_comment_on_post 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 a required resolution chain (resolve post -> post.id -> list comments -> comment.id -> optionally read replies -> reply) and clearly says not to create a new top-level comment. It also names the tools to obtain post and comment IDs, giving explicit when-to-use and how-to-proceed guidance.
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 postBRead-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 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?
Annotations already declare readOnly/idempotent/non-destructive/closed-world, so the safety profile is covered. The description adds real context beyond that: it returns only the account owner's posts and discloses the base64-style ID format. It omits pagination behavior and result size, and the stray Instagram reference is potentially misleading.
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 is front-loaded in the first sentence, but the body is a dense run of colon-delimited fragments, and the 'Post ID' block plus the irrelevant instagram_list_user_posts reference consume space without earning it for a LinkedIn resolver.
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 only a partial description of the return ('Returns the account owner's posts; ... reuse result.id'), the description should explain the result shape and how offset/pagination work. It covers the resolve workflow adequately but leaves the return contract and paging semantics underspecified.
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% (account_id documented, offset not). The description's 'Post ID' section actually describes the returned result.id, not a parameter, and never explains the offset parameter or pagination. It therefore fails to compensate for the uncovered parameter, adding no meaning beyond what the schema already provides for account_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?
States a specific verb+resource ('Resolve ... into exact post IDs') and clarifies scope ('Returns the account owner's posts'), which separates it from linkedin_get_post. However, citing instagram_list_user_posts as an ID source in a LinkedIn-only tool muddies the resource boundary and slightly undercuts 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?
Gives clear context ('before comments/reactions/edit/delete') and names concrete alternatives for obtaining an ID (linkedin_search_posts, linkedin_list_user_posts) plus an explicit 'Never pass' exclusion. It does not explicitly contrast with linkedin_get_post or the other resolver siblings, so it stops short of full when/when-not routing.
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 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 declare readOnly/idempotent/openWorld/non-destructive, so the safety profile is covered. The description adds real behavioral context beyond that: it may return multiple candidates, it should be disambiguated before writes, and it documents the stable ID shape ('ACo...'). Missing only return-shape/pagination 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?
Front-loads purpose and usage before the ID mechanics, and every section (purpose, when-to-use, ID format, obtain-methods, never-pass rules) earns its place. The 'Obtain with' block is dense but functional rather than 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 read-only resolution tool with strong annotations and no output schema, the description covers the essential agent needs: trigger conditions, disambiguation behavior, ID format, how to obtain IDs, and explicit invalid inputs. Gaps are limited to the un-annotated numeric/optional parameters.
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, and it partially does by explaining what keywords can contain (name, role, employer, location). However, limit, save_search, save_custom_filter, and the filters object receive no added meaning, so half the surface remains 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 (resolve) and resource (a human description to LinkedIn people and their stable system IDs), with concrete input examples (name, role, employer, location keywords). It is clearly distinguishable from linkedin_search_people and other lookup siblings because its job is pre-action ID resolution.
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 names the triggering conditions ('message Sarah at Acme', 'connect with the CTO of X') versus the alternative of already having an ID. It also gives the disambiguation rule ('if multiple plausible results remain, show/disambiguate before any write'), which is a clear when-to-use policy.
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_company_follow_invitationLinkedIn: Send company follow invitationADestructiveInspect
Invite one or more Classic LinkedIn members to follow a company page administered by the connected account, in one provider request. Resolve/disambiguate the numeric company and each Classic ACo member first; linkedin_get_company_follow_credits shows remaining invitation credits. Send only when the user explicitly requested/approved this exact page, recipients and account; otherwise ask for confirmation under the common MCP action rules. This is distinct from a connection invitation or following a company yourself. LinkedIn enforces page permissions, recipient eligibility and invitation credits. The receipt returns created invitation IDs and success/failed counts; it confirms creation only, not acceptance or a new follower, and does not say which members failed. No listing, acceptance or withdrawal is supported. Never retry automatically, including failed recipients, provider errors, rate limits and timeouts. After a partial or ambiguous failure the user must inspect LinkedIn before deciding any further send; no MCP invitation-state lookup exists for this action.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No | Owned LinkedIn unipile_account_id from list_connected_accounts. Omit only when one LinkedIn account is connected; never use a member/company ID. | |
| company_id | Yes | Numeric LinkedIn company ID from linkedin_list_managed_company_pages or linkedin_resolve_company/linkedin_search_companies, then verify the page is administered. Never pass a name, URL, slug or URN. | |
| member_ids | Yes | Non-empty list of distinct Classic LinkedIn member IDs (ACo...) from linkedin_get_profile_from_url, linkedin_resolve_person with Classic search, or linkedin_list_my_connections. Disambiguate first; never pass a URL, slug, URN, Sales Navigator or Recruiter ID. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true/idempotent=false, but the description adds substantial context beyond them: page permission and recipient-eligibility enforcement, invitation credits, receipt semantics (creation only, not acceptance; no per-member failure detail), unsupported operations, and a strict no-auto-retry rule covering rate limits and timeouts. This is exactly the extra behavioral disclosure the annotations cannot carry.
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 action and its scope lead, followed by prerequisites, failure semantics, and retry rules. Almost every sentence earns its place, though the closing sentences on state lookup overlap slightly with the earlier 'no listing/acceptance/withdrawal' statement.
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 mutation with no output schema, the description covers everything an agent needs: prerequisite resolution, credit gating, receipt interpretation, lack of per-recipient failure detail, and explicit no-retry and post-failure inspection 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 description coverage is 100%, so all three parameters are already documented with patterns and sourcing tools, which sets the baseline at 3. The description reinforces the resolve/disambiguate workflow and 'one or more' cardinality, but adds little syntax or format detail 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 (invite to follow) and resource (a company page administered by the connected account), and explicitly delineates scope: Classic members, numeric company, one provider request. It names what it is NOT ('distinct from a connection invitation or following a company yourself'), which cleanly separates it from siblings like linkedin_send_invitation and linkedin_follow_user.
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 explicit preconditions and gating: 'Send only when the user explicitly requested/approved this exact page, recipients and account; otherwise ask for confirmation.' It also points to linkedin_get_company_follow_credits for credit checks and instructs resolving/disambiguating IDs first, and names the sibling operations it is not.
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 declare destructiveHint=true, idempotentHint=false and openWorldHint=true, so the safety profile is covered structurally. The description adds product-conditional requirements and the prerequisite ordering, but says nothing about failure behavior, limits, or what sending actually commits (e.g. real outbound message to recipients).
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, front-loaded with the action and scope, then prerequisites, then surface-specific rules. Little waste, though the multi-clause prerequisite sentence packs several distinct rules together.
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 and a nested-parameter schema at 43% coverage, the description covers the product variants, recipient resolution, inbox sourcing, and product-specific required fields. Remaining gaps (return value, attachment semantics, idempotency) are minor given the annotations 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 coverage is only 43% and `specifics` is an undocumented free-form object, so the description does meaningful work by noting the subject goes in specifics for Sales Navigator and that users_ids accepts one ID (direct) or many (group). This partially compensates for the gap but leaves several parameters (name, specifics structure, send_mode/voice_note) unexplained.
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 ("Start a LinkedIn ... conversation") and scopes it to "from an explicit inbox", which distinguishes it from the sibling linkedin_start_conversation. It also enumerates the three supported product surfaces (Classic, Sales Navigator, Recruiter), so an agent can identify it 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?
Gives concrete prerequisites: resolve recipient user IDs first and obtain inbox_id via linkedin_list_inboxes, plus product-specific requirements (Sales Navigator subject in specifics; Recruiter may need subject and signature). It stops short of explicitly contrasting when to choose this tool over linkedin_start_conversation or linkedin_send_message, so no exclusions are named.
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 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=false, idempotentHint=false, destructiveHint=false, openWorldHint=true. The description doesn't contradict these but also adds nothing beyond them: it doesn't say whether unfollowing is reversible, whether it requires permission, or what happens if the user is not currently followed. With annotations carrying the safety profile, this is adequate but thin.
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. No waste, though the second sentence merely restates what the schema already documents.
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-param mutation with full schema coverage and existing annotations, this is close to sufficient. The missing piece is the relationship between unfollow and remove_connection, and reversibility, which an agent would benefit from before invoking.
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 user_id param description already explains obtaining it via resolvers and lists what never to pass. The description's only addition is a one-line reminder to resolve first, which is redundant with the schema. 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?
States a specific verb (Unfollow) and resource (LinkedIn user) from the connected account. A sibling tool linkedin_follow_user exists, and the name plus description make the direction of the relationship operation 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 sequencing prerequisite ('Resolve the exact provider user_id first'), which is useful guidance. However, it never explicitly contrasts with alternatives like linkedin_remove_connection (removing a connection vs unfollowing) — a distinction an agent could easily get wrong given both exist as siblings.
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 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 cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the description earns credit for adding ordering ('newest first'), the pagination mechanism ('before/after on the message timestamp'), and chat-scoped ID semantics. It does not describe rate limits or the shape of returned records, but for a read-only list tool this is solid added 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 tight sentences, purpose front-loaded, no filler. The follow-up warning about chat_id is placed last where it reads as an operational note.
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 must carry return-value context, and it does supply ordering and pagination semantics. It falls short of stating what fields each message includes (sender, text, attachments) and how cursor/offset differ, but for an 8-parameter list tool it is largely 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 low (38%), so the description carries extra burden. It usefully clarifies that before/after filter on the message timestamp, but leaves limit, cursor, and offset unexplained, and does not resolve the distinction between the cursor and offset pagination parameters, which is a meaningful ambiguity for an agent.
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 with scope and ordering: 'List messages in a known chat, newest first.' The phrase 'in a known chat' implicitly separates it from messaging_list_recent_messages and messaging_list_chats, but it never names those alternatives explicitly, so the differentiation is inferred 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?
'In a known chat' implies the required prerequisite (a chat_id you already have), and the closing sentence routes the agent to keep chat_id for follow-up get/edit/delete actions. However, there is no explicit when-to-use vs when-not guidance, nor any pointer to siblings like messaging_list_recent_messages or message_get for the single-message case.
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 declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the agent knows this is a non-idempotent write. The description's 'by sending its first message' corroborates that but adds little beyond the annotations — no auth requirements, rate limits, or what happens on failure are disclosed.
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, front-loaded with the core action and followed by the two routing constraints an agent most needs. No filler, though the LinkedIn sentence could arguably be tighter.
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 tool with nested attachment objects and no output schema, the description covers the main chat-initiation flow well but leaves optional parameters (attachments, specifics, account_id handling) unaddressed. Adequate but with visible 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 29%, yet the description's parameter detail (string vs array for users_ids) merely restates what the users_ids schema description already says. Attachments, specifics, name, and text remain undocumented in both places, so the description does not 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 first sentence names a specific verb (start), the resource (chat), the providers (WhatsApp, Instagram, Telegram), and the scope (one-to-one/group via first message). It also distinguishes itself from the LinkedIn-specific start tools, so an agent can tell it apart from the many messaging 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?
It gives clear preconditions ('Resolve users_ids first') and routing rules ('A string starts 1-to-1; an array requests a group', 'LinkedIn requires the inbox-specific start tool'). It doesn't explicitly contrast with messaging_send_message or messaging_send_to_contact, but the context needed to pick this tool is well supplied.
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 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 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 destructiveHint=true, readOnlyHint=false, idempotentHint=false and openWorldHint=true, so the safety profile is covered. The description adds real value beyond that: the requirement of explicit deletion intent before acting, and the provider quirk that LinkedIn post IDs are preformatted/base64-style. It does not address reversibility or failure/recovery behavior, which keeps it from 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 action and the destructive-intent gate, then the ID rules; every clause is operational rather than filler. Slight redundancy from repeating the schema's post_id text nearly word-for-word costs it a point.
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, no-output-schema, two-parameter tool, the description covers intent gating, ID resolution flow, exclusions, and ID format quirks. Nothing an agent needs to invoke this safely and 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 description coverage is 100%, so baseline is 3. The description's post_id guidance (exact provider ID, format quirk, how to obtain it, what not to pass) is essentially duplicated verbatim in the schema's own post_id description, and account_id is not mentioned at all, so it adds little beyond the structured field.
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 with a scope qualifier ("Delete an exact supported social post"), so an agent can readily separate it from social_delete_comment or social_update_post. It stops short of explicitly naming the alternative tools, 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?
Gives prerequisites (resolve/verify post_id first), the intent gate (explicit deletion intent required), concrete resolver paths (linkedin_search_posts / linkedin_list_user_posts / instagram_list_user_posts -> result.id), and explicit exclusions (never pass post text, author user ID, or URL). This is when-to-use, how-to-get-the-argument, and when-not-to content all in one place.
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 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 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, so the safety profile is covered by structured data. The description adds the ID-resolution dependency chain, but discloses nothing about return shape, pagination behavior, or rate limits beyond what the schema's offset field 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?
Purpose is front-loaded and the workflow is organized, but a large share of the text duplicates the schema's parameter descriptions verbatim, making it longer than it needs to be for the value added.
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-param read-only lister with no output schema, the description covers the critical prerequisite chain (resolve post_id -> list comments -> select comment_id) that an agent must follow. Return format is not explained, but nothing essential 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%, so the baseline is 3. The prose largely restates the schema's own parameter descriptions (post_id and comment_id text is near-identical), adding no format or syntax detail beyond 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?
States a specific verb (List) and resource (reactions on an exact comment), which distinguishes it from the write siblings social_react_to_comment and social_remove_comment_reaction, and from linkedin_list_post_reactions (post-level vs comment-level). An agent can tell what this 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?
Gives explicit sequencing: 'First resolve post_id, then list comments and select comment.id,' and names the resolver tools (linkedin_search_posts, linkedin_list_post_comments, etc.) that produce each ID. Clear context, though it never states a when-not-to-use case.
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 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 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 the safety profile (readOnlyHint=false, destructiveHint=true, idempotentHint=false, openWorldHint=true), so the description need not repeat it. What it adds is purely ID-resolution guidance rather than behavioral context it says nothing about what a successful reaction does, whether it can be changed, or how it is undone. With annotations carrying the behavioral burden, a 3 is apt.
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 action and the resolve-first rule, then the ID guidance, which is the right order. The bulk is the repeated Obtain with / Never pass block that also lives in the schema, so it is somewhat redundant rather than wasteful prose.
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 with no output schema and full annotation coverage, the description gives everything needed to invoke correctly: both required IDs, how to source them, and the multi-account account_id path is covered in the schema. It omits which reaction values are provider-supported and how a reaction is reversed, which would be helpful but is not blocking.
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's post_id/comment_id text is essentially duplicated verbatim inside the schema, so it adds little the agent cannot already read. The routing hints (which list tools yield the IDs) are useful but appear in both places, keeping this 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?
"React to one exact comment" gives a specific verb and resource, and the emphasis on "exact comment" versus post-level reactions implicitly separates it from linkedin_react_to_post and social_list_comment_reactions. It never names a sibling outright, so the differentiation is inferable 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?
Provides a clear operational sequence (Resolve post -> comment before acting) and explicit anti-patterns (do not confuse post_id and comment_id; never pass post text, author ID, or URL). It stops short of naming the alternative tools (e.g. social_remove_comment_reaction, linkedin_list_post_comments) as the routing decision, so it is strong context without explicit when-not guidance.
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 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 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?
Annotations already declare destructiveHint=true, idempotentHint=false and openWorldHint=true, so the safety profile is carried. The description adds the precondition that IDs must be resolved before invocation, but discloses nothing about failure modes (e.g., reaction not present) or reversibility beyond what the destructive hint 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?
Front-loaded with the core action, then clearly labeled 'Post ID' and 'Comment ID' sections. However, the ID-resolution text is duplicated verbatim in the schema descriptions, which is wasted space against a tight budget.
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, open-world, mutation tool with no output schema and full schema coverage, the description supplies the essential ID-resolution preconditions. It omits error/edge-case behavior, but annotations and schema cover most of what an agent needs 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 description coverage is 100%, so the baseline is 3. The description restates the post_id and comment_id guidance almost verbatim from the schema rather than adding new meaning, so it neither compensates nor detracts.
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+scope: 'Remove the user's reaction from one exact comment.' It is readily distinguishable from siblings like social_remove_post_reaction (post, not comment) and social_react_to_comment (the inverse), so an agent can pick it 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?
The description gives clear context and a prerequisite workflow ('Resolve post_id/comment_id first') plus explicit prohibitions ('Never pass: post text, author user ID, URL'). It stops short of naming a sibling alternative or exclusion condition (e.g., when to prefer social_remove_post_reaction), so it is strong 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.
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 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 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, readOnlyHint=false and idempotentHint=false, so the agent knows this mutates state. The description adds nothing about reversibility, whether other users' reactions are affected, or permission requirements, and 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?
Front-loaded with the action, which is good, but the post_id guidance block (resolver list plus 'Never pass' list) is repeated almost word-for-word from the schema, so several sentences are spent restating structured data rather than adding 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 3-param, no-output-schema mutation tool with full annotation coverage, the description supplies the one thing structured fields do not: how to obtain a valid post_id and what must never be substituted. Return behavior is left implicit, but that is a minor gap given annotations cover the safety profile.
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 post_id, reaction and account_id in detail. The description's post_id text is essentially a verbatim duplicate of the schema field, adding no new syntax or format meaning; 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 specific verb+resource ('Remove the user's reaction from one exact post') and scopes it to a single post. It implies the boundary against post-comment and message reaction siblings but never names an alternative, so an agent must infer the routing itself.
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 explicit procedural guidance ('Resolve post_id first') and a clear prohibition ('never use post URL/text unless another resolver explicitly converts it'), with concrete resolver paths. It stops short of stating when-not to use this tool versus sibling reaction tools, so no explicit exclusion list.
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 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 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, so the safety profile is covered. The description adds the workflow precondition (post must already be resolved) but says nothing about pagination despite an offset parameter, nor about the shape/limits of the comment list returned.
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, which is good, but the body is dense and repeats the 'post ID / obtain with / never pass' block that already appears verbatim in the schema description. Several lines (the Comment ID sourcing chain) serve the resolution goal rather than this tool's 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 cross-provider resolver with three parameters and no output schema, the description covers the input workflow adequately but omits pagination behavior and what the returned comment entries contain (which fields an agent can match a human reference against). Those gaps matter precisely because there is no output schema to fall back on.
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%, and the description's post_id guidance largely duplicates the schema's own post_id text rather than adding new meaning. It says nothing about offset (the undescribed parameter) or about how account_id affects provider scoping, and it elaborates a 'Comment ID' block for something that is not an input parameter 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 and goal: list comments on an already-resolved post so a human reference like 'the comment from Sarah' can be mapped to an exact comment_id. That distinguishes it from the raw provider listers (linkedin_list_post_comments, instagram_list_post_comments) that it names. The verb 'List' sits a little awkwardly under the name resolve_comment, but an agent can still tell what it 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 gives an explicit ordering ('First resolve post_id') and a clear downstream purpose (before replying/reacting/editing/deleting), plus concrete obtain-chains for the IDs it needs. It does not state when to skip this tool (e.g. when an exact comment_id is already known) or how it should be preferred over the provider-specific listers it cites.
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 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 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 destructiveHint=true, idempotentHint=false, and openWorldHint=true, so the safety profile is covered. The description adds the ID-namespace warning and resolution chain, which is useful, but says nothing about side effects beyond replacement (e.g. whether the prior comment text is unrecoverable) or return 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 core purpose is front-loaded well, but the body is a dense run-on that largely duplicates the schema property descriptions ('post_id and comment_id are different ID namespaces', obtain-with chains, never-pass lists appear in both places). Redundant rather than wasteful, but not tight.
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 moderate-complexity mutation, the hardest part — resolving two distinct ID namespaces — is thoroughly explained, including source tools for each. The gap is return behavior: there is no output schema and the description never indicates what the edit returns or how failures surface.
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 four parameters, including the identical ID-namespace and obtain-with text. The description re-states that same content almost verbatim, so it adds little semantic value beyond the schema. Baseline 3 applies when the 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 states a specific verb+resource: 'Edit an existing comment.' Combined with the resolution chain, an agent knows exactly what this does and can distinguish it from delete/react/reply siblings by verb. However, it never explicitly names the competing siblings (social_delete_comment, linkedin_reply_to_comment, social_react_to_comment) to sharpen the boundary.
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?
Strong procedural guidance: 'Required chain when starting from human text: resolve post -> post.id -> list comments -> comment.id -> edit,' plus explicit negative instructions ('Never pass: post text, author user ID, URL...'). It stops short of stating when to use edit vs reply_to_comment or resolve_comment, so no explicit alternative routing.
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 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 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 establish write/non-idempotent/open-world, and the description adds genuinely new behavioral context: the mandatory two-step resolve-then-edit pattern and the warning that LinkedIn IDs are preformatted/base64-style, which is non-obvious. It does not disclose authorization requirements (e.g., must own the post) or that can_comment changes audience visibility, so it falls short of a 5. 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 resolution-first instruction is front-loaded, which is correct, but the entire post_id block ("Post ID: Exact provider post id; LinkedIn commonly uses...") is repeated word-for-word from the input schema, and the resolver list is jammed into one run-on line. Redundancy costs it points.
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 non-idempotent write with no output schema and 4 parameters, the ID-resolution story is well covered but several things an agent needs are missing or only in the schema: the multi-account disambiguation flow (account_id), the meaning of can_comment, and whether the editing user must be the post author. Adequate, 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 coverage is 75%, so the baseline is 3. The post_id guidance in the description is largely a verbatim duplicate of the post_id schema description rather than added meaning, and it says nothing about `text` semantics or what the `can_comment` enum values actually change about the post. Marginal added value over 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 ("Edit an existing supported social post"), which cleanly separates it from social_update_comment, social_delete_post, and linkedin_create_post. The word "supported" leaves the provider scope slightly fuzzy, though the resolver list (LinkedIn, Instagram) implies it. Strong but not a perfect sibling disambiguation.
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 an explicit workflow: resolve the post first, then reuse post.id, and it names the resolver tools (linkedin_search_posts, linkedin_list_user_posts, instagram_list_user_posts). The "Never pass: post text, author user ID, URL" rule is a clear negative constraint. It stops short of naming when NOT to use this tool (e.g., comment edits vs. post edits), so it is a 4 rather than a 5.
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 creates the endpoint server-side but ALWAYS restricts it 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 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 endpoint's account_ids synchronized when the user connects matching accounts later. | |
| account_ids | No | Optional explicit 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?
Annotations already establish write/non-destructive/non-idempotent, and the description layers on genuinely new behavior: the endpoint is created server-side, always restricted to accounts owned by the authenticated user, auto-inclusion semantics for future accounts, and the crucial security fact that the signing secret is encrypted server-side and never returned (never ask for it). That is exactly the beyond-annotations context the dimension rewards.
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 is front-loaded and each sentence carries distinct content (security scope, auto-include semantics, n8n workflow, secret handling). The middle sentences are dense and could be tightened, but no sentence 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 7-parameter mutation tool with no output schema, the description covers the essential risks — ownership restriction, account synchronization, and the never-returned secret — that an agent needs before invoking. Minor gaps remain around return/confirmation behavior, but annotations and schema carry the rest.
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?
At 57% schema coverage, two parameters (name, runtime, and the undocumented auto_include_new_accounts) lack schema descriptions, and the description compensates by explaining the auto_include_new_accounts / providers / account_ids interaction — explicit account_ids without a providers filter stay restricted even with auto_include_new_accounts=true. It adds real meaning beyond the schema, though it does not cover every 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 opens with a specific verb+resource ("Create a realtime event destination"), which an agent can immediately place against webhook_update_destination, webhook_delete_destination and webhook_get_destination. It is clear and unambiguous, though it never names a sibling to explicitly steer selection.
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 supplies concrete usage context — use the n8n Test URL first, validate with a Development/Mock event, then move to the Production URL — which implicitly points at the test/update flow. It stops short of an explicit when-to-use-this-vs-alternatives rule, so it is strong context rather than full routing guidance.
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 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 remote webhook endpoint ID directly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=false, so the safety profile is covered. The description adds useful context beyond that: the endpoint must be Nilyo-owned (not the remote endpoint), the concrete consequence is halting future realtime delivery, and user intent must be explicit. It omits whether the deletion is reversible or what happens to queued deliveries, keeping it from 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?
Two tightly written sentences with zero waste. The action is front-loaded, followed by the operational consequence and the intent requirement in priority 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 single-parameter destructive tool with rich annotations and no output schema, the description covers what is being deleted, the ownership scope, the delivery-stopping effect, and the intent prerequisite. It is nearly complete; only the permanence/reversibility of the deletion is left unstated.
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 destination_id parameter is fully documented in the schema, including the warning to use the Nilyo destination ID rather than the remote endpoint ID. The description adds no parameter-level detail, 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 specific verb and resource ('Delete an Nilyo-owned webhook endpoint') and immediately scopes the effect ('stops future realtime delivery'). It is unmistakable against siblings like webhook_update_destination or webhook_get_destination.
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 usage directive: 'require explicit user intent,' which is strong guidance for a destructive operation. It does not, however, name alternatives (e.g., use webhook_update_destination to disable instead of delete), so it stops short of explicit when-not guidance.
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 webhook delivery attempts 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 remote webhook 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 covered. The description adds the diagnostic framing but says nothing about retention window, pagination, or what the log entries contain, which is the behavior an agent most needs for a diagnostics 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?
Three short sentences, front-loaded with the action and then the trigger condition. The final sentence ('preferred to guessing whether delivery occurred') is mildly redundant rationale but still short and non-repetitive.
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?
Complete for a two-parameter, read-only diagnostic tool whose safety profile is fully covered by annotations and whose parameter semantics are largely in the schema. No output schema exists, so the description need not explain return values.
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%: destination_id carries a rich schema description including the warning to use the Nilyo ID rather than the remote endpoint ID, while limit has constraints but no prose. The description adds nothing about either parameter, so it does not compensate for the undocumented limit, but the schema itself remains informative.
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 ('Inspect') and resource ('recent webhook delivery attempts for this destination'), which is clearly distinct from sibling tools like webhook_get_destination or webhook_test_destination. It does not explicitly name a sibling to contrast with, 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?
Gives concrete triggering conditions: use when an agent/n8n receiver did not wake or a test event was not observed. This is clear diagnostic context. It stops short of naming explicit alternatives (e.g. webhook_test_destination) or stating 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.
webhook_get_destinationRealtime: Get destinationBRead-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 remote webhook endpoint ID directly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, closed-world. The description adds that the destination is Nilyo-owned and includes its configured events/provider/account, which is useful return-shape context the annotations don't give. No auth/pagination details, so a 3.
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 compact sentence with the resource and its returned contents front-loaded; no waste.
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 simple 1-param read with full schema and annotations; the description is adequate but lacks output shape and how it relates to sibling getters, so it's minimum viable.
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 description already warns against using the remote endpoint ID. The description adds nothing beyond the schema; 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 specific verb (get) and resource (one webhook destination) and names what it returns (events/provider/account selection). The 'Nilyo-owned' qualifier distinguishes it from remote endpoint lookups, though it doesn't name the sibling list/get alternatives 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 gives no guidance on when to call this versus webhook_list_destinations or webhook_get_delivery_logs. The 'Nilyo-owned' distinction is a hint but no when/when-not is stated.
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 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 establish the safe-read profile (readOnlyHint, idempotentHint, destructiveHint=false, openWorldHint=false). The description adds genuinely new context beyond them: this returns guidance rather than event data, the guidance is runtime-specific, and it is meant to run before webhook creation. It omits any note on return shape or rate limits, so not 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?
Two sentences, zero waste: the first establishes what is returned and for whom, the second establishes when to call it. Front-loaded purpose before the usage constraint.
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 burden of explaining the return and does so at a high level ('runtime-specific instructions for receiving realtime events'). It is adequate for a one-enum-parameter, read-only guide tool, though it never sketches what the instructions actually contain (steps, code snippets, URLs).
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%, but the single parameter is an enum whose five values are self-describing, and the description restates them in prose ('n8n, OpenClaw, Hermes, Make or a generic agent'), confirming the agent must pick its runtime. It does not explain what 'generic' yields or how the instructions differ per runtime, so it adds only marginal meaning beyond the enum.
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 (get) and resource (setup guide) and enumerates the exact runtimes covered: n8n, OpenClaw, Hermes, Make, generic agent. This clearly distinguishes it from sibling write/read tools like webhook_create_destination and webhook_get_destination, which operate on destinations rather than returning instructions.
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 sequencing rule: 'Use BEFORE creating the webhook when the user has not yet produced a public receiver URL.' That is a clear precondition and implies the when-not case. It does not name an alternative tool for the case where a receiver URL already exists, so it falls 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.
webhook_list_available_eventsRealtime: List available eventsARead-onlyIdempotentInspect
List realtime 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 readOnly, idempotent, non-destructive and closed-world, so safety is covered. The description adds genuinely useful context beyond them: the response includes the common event envelope, which matters given there is no output schema. It does not mention pagination, but for a static enumeration tool that is minor.
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, with the core function stated first and the usage condition second. 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?
With zero parameters and rich annotations, the main remaining burden was signalling what comes back; the description covers that by naming the event types and the common envelope. It stops short of explaining the envelope's shape, but that is discoverable from the call itself.
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 there is no schema semantics to expand; per the baseline a 4 applies. The description correctly implies a no-argument listing call.
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: listing realtime event types that can be subscribed to an agent, plus the event envelope. It is clearly separable from webhook_list_destinations and webhook_get_destination because it enumerates event types rather than destinations, though it does not name those siblings directly.
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 when-to-use rule: call it before webhook_create_destination when the user's requested trigger is ambiguous. It names no exclusions or alternative enumeration sources, so it falls short of a full when/when-not statement.
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 events are delivered directly to the destination, not relayed through Nilyo.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), so the bar is lower. The description still adds genuinely new context: these are control-plane/config records and realtime events are delivered directly rather than relayed, which clarifies what the returned records do not represent.
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 the primary purpose front-loaded and the architectural clarification second. No filler or 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?
No output schema exists, so the description could optionally hint at what a destination record contains, but for a simple parameterless list operation the stated scope and the 'control-plane records' framing are enough 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?
The tool takes zero parameters, so there is nothing for the description to disambiguate; the baseline for a parameterless tool is 4. No parameter behavior is misrepresented.
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') and resource ('webhook destinations') with an ownership scope ('created by this Nilyo user'). It is clearly separable from webhook_get_destination, though it never names a sibling explicitly to reinforce the distinction.
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 no when-to-use or when-not-to-use guidance and does not point to alternatives such as webhook_get_destination for details or webhook_create_destination for setup. Usage must be inferred entirely from the name.
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. Generate a mock/test event with a Mock account (Test & Debug), then inspect webhook_get_delivery_logs and the target runtime. Nilyo does not fabricate provider event payloads because the 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 remote webhook endpoint ID directly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (read-only, idempotent, non-destructive), so the bar is lower, yet the description adds real behavioral context: it returns a procedure rather than performing the test, and it explicitly states it will not fabricate provider event payloads. That 'what it does not do' disclosure is genuinely useful and beyond 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?
Three sentences, front-loaded with the core purpose, then the procedure, then a rationale. The final sentence about not fabricating payloads is slightly tangential but earns its place by setting expectations about the tool's guarantee.
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-param read-only tool with full schema coverage and no output schema, the description is nearly complete: it explains what is returned, how to use the result, and its non-fabrication guarantee. Minor gap: it doesn't state the format of the returned 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?
One parameter with 100% schema description coverage that already warns never to pass the remote webhook endpoint ID. The description offers no additional parameter meaning, so the schema 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?
States a specific verb+resource: 'Return the exact test procedure for a destination.' Crucially, it disambiguates the misleading name by clarifying the tool returns a procedure rather than executing a test, and it names webhook_get_delivery_logs as a follow-up step. It doesn't fully contrast against the other webhook_* siblings (e.g. get_setup_guide), keeping it just below a 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?
Gives clear context for when to use it: after creating a destination, generate a mock/test event with a Mock account (Test & Debug), then inspect webhook_get_delivery_logs and the target runtime. The workflow is spelled out, though there are no explicit exclusions or a named alternative to avoid.
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 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 endpoint's account_ids synchronized when the user connects matching accounts later. | |
| account_ids | No | Optional explicit 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 remote webhook endpoint ID directly. | |
| auto_include_new_accounts | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare a non-read-only, non-idempotent, non-destructive mutation; the description adds a genuinely useful server-side behavior note (Nilyo recomputes authorized account_ids). It does not say whether omitting a field leaves it unchanged or clears it, which matters given idempotentHint=false, so it stops short of full 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 tightly packed sentences with the core action and field list front-loaded, followed by the workflow example and the server-side behavior note. 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 9-parameter mutation with no output schema and mixed schema coverage, the description is adequate but incomplete: it omits what an update returns, how unspecified fields are treated, and the meaning of enabled/runtime/auto_include_new_accounts. The presence of rich field descriptions in the schema offsets this only partially.
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 56% across 9 parameters, so the description must carry more weight, and it names only URL, events and provider/account selection, leaving enabled, runtime, auto_include_new_accounts and partial-update semantics unexplained. The value it does add on events/account_ids is already largely present in the schema field 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 (Update) plus the resource (webhook destination) and enumerates the mutable fields (URL, events, provider/account selection). The n8n chain wording implicitly separates it from webhook_create_destination and webhook_get_destination, though no sibling is named outright, which keeps it short of a 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?
Gives a concrete when-to-use scenario: create with a Test URL, receive a mock event, then update the same destination to a Production URL. That is clear usage context, but there is no explicit when-not-to-use (e.g. use webhook_create_destination for a new endpoint, webhook_test_destination to fire a test) and no prerequisite guidance.
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 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, openWorldHint and destructiveHint, so the safety profile is fully covered. The description adds only mild context (verifying a recipient) and says nothing about return shape or error behavior. With annotations carrying the load, 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 tight sentences that front-load the purpose and then the use case. No filler, and the identifier scope is stated up 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 simple read with no output schema and full schema coverage, the description supplies enough to call correctly: what it fetches and the identifiers accepted. It could round out by naming the alternative resolver, but nothing essential 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 both parameters are documented in the schema, and the required user_id is described in great detail there. The description restates that the ID may be a provider user ID or phone-number identifier but adds no format or resolution detail beyond the schema. 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 specific verb (Retrieve) and resource (WhatsApp user profile) plus the accepted identifiers (provider user ID or phone-number identifier). An agent knows exactly what it returns. It does not explicitly contrast with sibling resolvers like messaging_resolve_recipient or whatsapp_list_contacts, so it falls short of a 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?
"Use to resolve/verify the recipient before a new chat" gives a clear when-to-use context. However it names no alternative tools and no when-not-to-use conditions, which keeps it below 5.
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.
11 tool updates
- Added
instagram_comment_on_post - Added
instagram_follow_user - Added
instagram_get_post - Changed
instagram_get_profile2 fields changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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 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."New value: +"Instagram username, @handle, numeric profile ID or HTTPS profile URL; resolves to profile.id for posts/follow actions. Not a human display name, post URL, account_id or messaging_identifier." - added
Input schema / properties / user_id / maxLengthAdded value: +2048
- Added
instagram_get_profile_from_url - Added
instagram_like_post - Added
instagram_list_post_comments - Added
instagram_list_user_posts - Changed
linkedin_comment_on_post1 field changed- added
Input schema / properties / text / descriptionAdded value: +"LinkedIn Classic mentions belong in text: @ followed by the resolved person's Classic ACo... ID or the company's numeric ID (for example @1441). Resolve people with linkedin_get_profile_from_url/linkedin_resolve_person and companies with linkedin_resolve_company/linkedin_search_companies; disambiguate every target before publishing. Never use a display name, profile URL, company slug, URN, Sales Navigator or Recruiter ID as a mention. Example after resolving both targets: 'Thanks @ACo_RESOLVED_MEMBER for working with @1441.' The API replaces each token with the target's name and mention metadata; no separate mentions field is needed. Approve the final text and mentioned identities before the write; never retry an ambiguous write automatically."
- Changed
linkedin_create_post1 field changed- added
Input schema / properties / text / descriptionAdded value: +"LinkedIn Classic mentions belong in text: @ followed by the resolved person's Classic ACo... ID or the company's numeric ID (for example @1441). Resolve people with linkedin_get_profile_from_url/linkedin_resolve_person and companies with linkedin_resolve_company/linkedin_search_companies; disambiguate every target before publishing. Never use a display name, profile URL, company slug, URN, Sales Navigator or Recruiter ID as a mention. Example after resolving both targets: 'Thanks @ACo_RESOLVED_MEMBER for working with @1441.' The API replaces each token with the target's name and mention metadata; no separate mentions field is needed. Approve the final text and mentioned identities before the write; never retry an ambiguous write automatically."
- Changed
linkedin_reply_to_comment1 field changed- changed
Input schema / properties / text / descriptionPrevious value: -"Final reply text explicitly requested/approved by the user."New value: +"Final reply text explicitly requested/approved by the user. LinkedIn Classic mentions belong in text: @ followed by the resolved person's Classic ACo... ID or the company's numeric ID (for example @1441). Resolve people with linkedin_get_profile_from_url/linkedin_resolve_person and companies with linkedin_resolve_company/linkedin_search_companies; disambiguate every target before publishing. Never use a display name, profile URL, company slug, URN, Sales Navigator or Recruiter ID as a mention. Example after resolving both targets: 'Thanks @ACo_RESOLVED_MEMBER for working with @1441.' The API replaces each token with the target's name and mention metadata; no separate mentions field is needed. Approve the final text and mentioned identities before the write; never retry an ambiguous write automatically."
41 tool updates
- Changed
email_get_attachment1 field changed- changed
Input schema / properties / email_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
email_mark_read1 field changed- changed
Input schema / properties / email_id / descriptionPrevious value: -"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."New value: +"Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo 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."
- Changed
email_mark_unread1 field changed- changed
Input schema / properties / email_id / descriptionPrevious value: -"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."New value: +"Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo 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."
- Changed
email_move_or_label1 field changed- changed
Input schema / properties / email_id / descriptionPrevious value: -"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."New value: +"Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo 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."
- Changed
email_read_message1 field changed- changed
Input schema / properties / email_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
email_trash1 field changed- changed
Input schema / properties / email_id / descriptionPrevious value: -"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."New value: +"Exact provider email ID from email list/read/resolve. Email provider ID: Exact email ID returned by Nilyo 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."
- Changed
instagram_get_profile1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
linkedin_comment_on_post1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider 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."
- Changed
linkedin_create_post1 field changed- changed
Input schema / properties / quoted_post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID to quote, returned by post search/list/get. Never pass post text or a URL. Post ID: Exact provider 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."
- Changed
linkedin_follow_user1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
linkedin_get_post1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider 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."
- Changed
linkedin_list_comment_replies1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact post ID from post search/list. Post ID: Exact provider 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."
- Changed
linkedin_list_followers1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
linkedin_list_following1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
linkedin_list_post_comments1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider 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."
- Changed
linkedin_list_post_reactions1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider 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."
- Changed
linkedin_list_user_posts1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
linkedin_list_user_relations1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
linkedin_react_to_post1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID returned by post search/list/get. Never pass post text, author ID or URL. Post ID: Exact provider 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."
- Changed
linkedin_remove_connection1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
linkedin_reply_to_comment1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact post ID from post search/list. Post ID: Exact provider 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."
- Changed
linkedin_start_conversation_from_inbox1 field changed- changed
Input schema / properties / users_ids / anyOfPrevious value: -[ - { - "description": "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.", - "minLength": 1, - "type": "string" - }, - { - "items": { - "description": "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.", - "minLength": 1, - "type": "string" - }, - "minItems": 1, - "type": "array" - } -]New value: +[ + { + "description": "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 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.", + "minLength": 1, + "type": "string" + }, + { + "items": { + "description": "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 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.", + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } +]
- Changed
linkedin_unfollow_user1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
messaging_list_messages1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
- Changed
messaging_start_chat1 field changed- changed
Input schema / properties / users_ids / anyOfPrevious value: -[ - { - "description": "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.", - "minLength": 1, - "type": "string" - }, - { - "items": { - "description": "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.", - "minLength": 1, - "type": "string" - }, - "minItems": 1, - "type": "array" - } -]New value: +[ + { + "description": "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 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.", + "minLength": 1, + "type": "string" + }, + { + "items": { + "description": "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 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.", + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } +]
- Changed
social_delete_comment1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
social_delete_post1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
social_list_comment_reactions1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
social_react_to_comment1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
social_remove_comment_reaction1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
social_remove_post_reaction1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
social_resolve_comment1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID returned by post search/list/get. Never pass post text, author ID or a post URL. Post ID: Exact provider 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."
- Changed
social_update_comment1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
social_update_post1 field changed- changed
Input schema / properties / post_id / descriptionPrevious value: -"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."New value: +"Exact provider post ID. Resolve/list the post first; never pass post text, author ID or a human description. Post ID: Exact provider 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."
- Changed
webhook_create_destination3 fields changed- changed
Input schema / properties / account_ids / descriptionPrevious value: -"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."New value: +"Optional explicit account IDs returned by list_connected_accounts. Nilyo rejects the whole request if any ID is not owned by the authenticated user." - changed
Input schema / properties / events / descriptionPrevious value: -"Exact Unipile V2 event types. Call webhook_list_available_events first when unsure. Do not invent event names."New value: +"Exact event types. Call webhook_list_available_events first when unsure. Do not invent event names." - changed
Input schema / properties / providers / descriptionPrevious value: -"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."New value: +"Optional provider filter. google includes Gmail and outlook includes Microsoft accounts. With auto_include_new_accounts=true, Nilyo keeps this endpoint's account_ids synchronized when the user connects matching accounts later."
- Changed
webhook_delete_destination1 field changed- changed
Input schema / properties / destination_id / descriptionPrevious value: -"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly."New value: +"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the remote webhook endpoint ID directly."
- Changed
webhook_get_delivery_logs1 field changed- changed
Input schema / properties / destination_id / descriptionPrevious value: -"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly."New value: +"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the remote webhook endpoint ID directly."
- Changed
webhook_get_destination1 field changed- changed
Input schema / properties / destination_id / descriptionPrevious value: -"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly."New value: +"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the remote webhook endpoint ID directly."
- Changed
webhook_test_destination1 field changed- changed
Input schema / properties / destination_id / descriptionPrevious value: -"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly."New value: +"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the remote webhook endpoint ID directly."
- Changed
webhook_update_destination4 fields changed- changed
Input schema / properties / account_ids / descriptionPrevious value: -"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."New value: +"Optional explicit account IDs returned by list_connected_accounts. Nilyo rejects the whole request if any ID is not owned by the authenticated user." - changed
Input schema / properties / destination_id / descriptionPrevious value: -"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the Unipile endpoint ID directly."New value: +"Nilyo webhook destination ID returned by webhook_create_destination/webhook_list_destinations. Never use the remote webhook endpoint ID directly." - changed
Input schema / properties / events / descriptionPrevious value: -"Exact Unipile V2 event types. Call webhook_list_available_events first when unsure. Do not invent event names."New value: +"Exact event types. Call webhook_list_available_events first when unsure. Do not invent event names." - changed
Input schema / properties / providers / descriptionPrevious value: -"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."New value: +"Optional provider filter. google includes Gmail and outlook includes Microsoft accounts. With auto_include_new_accounts=true, Nilyo keeps this endpoint's account_ids synchronized when the user connects matching accounts later."
- Changed
whatsapp_get_profile1 field changed- changed
Input schema / properties / user_id / descriptionPrevious value: -"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."New value: +"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 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."
2 tool updates
- Added
linkedin_get_company_follow_credits - Added
linkedin_send_company_follow_invitation
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
LinkedIn, WhatsApp, Telegram and Instagram inboxes, profiles and outreach for your AI assistant.
Email, WhatsApp and Telegram for AI agents: send, campaigns, automations, contacts, agent inboxes.
Gmail, Outlook, iCloud, Fastmail and any IMAP mailbox for your agent. Scoped OAuth, approved sends.
Gmail, Outlook, Drive, OneDrive and calendars for AI agents. Many accounts, one endpoint, audit log.
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.2MIT- 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.30742 PyPI17AGPL 3.0
- AlicenseNot gradedqualityCmaintenanceGives 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.MIT
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 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, readOnlyHint=false, and idempotentHint=false, so 'Destructive' repeats structured data rather than adding to it. The description does add the scope constraint (only one exact comment, scoped to an already-resolved post) and the resolution prerequisite, but says nothing about whether replies cascade, whether the action is reversible, or what failure on a non-idempotent repeat looks like.
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 instruction is correctly front-loaded ('Delete one exact comment'), but the body copies the post_id and comment_id schema descriptions verbatim, padding the definition with content the agent already receives 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 destructive mutation with full annotation coverage and no output schema, the description supplies the key operational detail an agent needs (ID resolution order and valid sources). It omits return-value expectations and cascade/permission behavior, which are minor given the annotations already flag destructiveness.
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 text for post_id and comment_id is a verbatim duplication of the schema descriptions rather than new meaning. The only marginal addition is the account_id guidance, which is already carried in the schema. Baseline 3 applies when the 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?
States a specific verb and resource ('Delete one exact comment') and scopes it precisely with 'one exact comment.' An agent can distinguish it from siblings like social_update_comment, social_resolve_comment, and linkedin_reply_to_comment 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?
Gives explicit prerequisites and sequencing ('Resolve post_id then comment_id'), concrete obtain-with chains (linkedin_list_post_comments -> comment.id, etc.), and negative constraints ('never use comment text as ID'). It does not name the sibling social_resolve_comment as the resolver for an unknown comment, which is the one missing routing hint.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.