Skip to main content
Glama

Server Details

Search customer feedback, topics, people and companies in Modem, and run the Modem Agent.

Ownership verified
Status
Healthy
Uptime
88.4% over 43 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL

TDQS

A3.6/5.0

Scored across 21 tools

Disambiguation4/5

Most tools target clearly distinct resources and actions (companies, people, topics, automations, agent runs). A few pairs need the descriptions to separate them: update_topic vs bulk_update_topics (single vs bulk), send_feedback vs create_feedback_channel (feedback to Modem vs an app feedback channel), and modem_docs vs modem_skills vs search_modem (orienting/read tools). The descriptions do resolve these overlaps, so boundaries are largely clear.

Naming Consistency4/5

The dominant pattern is snake_case verb_noun (create_companies, update_people, merge_topics, search_modem, send_feedback, list_automations). The modem_agent_* tools use a noun/prefix-first convention (modem_agent_get_run, modem_agent_invoke), which is a minor deviation but internally consistent as a subsystem. No chaotic mixing of camelCase or arbitrary verbs.

Tool Count4/5

21 tools is on the heavier side but spans genuinely distinct areas: CRM entities (people/companies/topics), automations, durable agent runs, and orientation/telemetry tools (docs, skills, search, feedback). Each tool has a plausible distinct purpose. It leans heavy rather than being an arbitrary sprawl, so slightly above the ideal band.

Completeness3/5

Lifecycle coverage is uneven: automations have create/list/update, agent runs have invoke/get/cancel/send_message, but there is no delete for anything, and companies/people/topics have no dedicated get/list tools — reads depend entirely on the generic search_modem. Merges and bulk updates exist, so it is workable, but the missing delete and explicit read operations are notable gaps.

Available Tools

21 tools
add_people_to_companyAdd People to CompanyB
Idempotent
Inspect

Associate one or more people with a company. Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
companyIdYes
personIdsYes

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=false, idempotentHint=true, and destructiveHint=false, so the description doesn't need to restate safety. However, the description adds no behavioral context beyond the hint to read the skill, which is not about tool behavior. For a mutation tool, it could disclose idempotency implications or error cases, but it doesn't, so it falls short of the higher bar.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence that states the core purpose, followed by a direct instruction to read a skill. It's concise and front-loaded with the primary action, with no unnecessary fluff, but it could be clearer about the skill's role.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (2 params, no output schema, no nested objects), so the description covers the basic action and points to a skill for further details, which is adequate. However, it doesn't clarify what happens after the call (e.g., whether it returns anything) or any side effects, and given the instruction to read a skill, it somewhat relies on external context, making it minimally complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage, meaning it only provides types and patterns but no semantic meaning. The description explicitly mentions 'one or more people' and 'a company', which clarifies that personIds is an array (at least one) and companyId is a single ID, adding value beyond the schema. It doesn't explain the ID format, but the patterns are self-explanatory.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Associate' and the resource 'one or more people with a company', which aligns with the tool name and title. It is distinct from siblings like merge_companies or update_people, though it doesn't explicitly name them, making it clear but not fully differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions 'Before your first call, read the skill: modem_skills(...)', which implies a prerequisite for using the tool, giving some usage guidance. However, it doesn't provide explicit when-to-use or when-not-to-use conditions, nor does it contrast with alternative tools like merge_people or update_companies, so it's only minimally helpful.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

bulk_update_topicsBulk Update TopicsA
DestructiveIdempotent
Inspect

Update multiple topics at once (e.g. archive or re-prioritize a set of topics). Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
archivedNoSet to true to archive topics, false to unarchive them.
priorityNoUpdate all topics to this priority. Valid values: very_low, low, default, high, very_high.
topicIdsYes
archivedReasonNoOptional reason for archiving. Only used when archived=true.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as destructive and not read-only, while the description adds context by naming archive and re-prioritize as example operations. It does not describe the nature of the destructive effects or whether changes are reversible, but 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with the core behavior front-loaded and an actionable prerequisite included in the second sentence. Every part earns its place; there is no redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The essential batch semantics and required pre-read skill are covered, and annotations already supply safety and idempotency context. It does not discuss return values or partial-failure behavior, but the schema and annotations cover most operational needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides descriptions for archived, priority, and archivedReason (75% coverage), and the description's examples map onto those same parameters. The description adds no new parameter-level semantics beyond what the schema already exposes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a precise verb and resource: 'Update multiple topics at once.' It also gives concrete example uses ('archive or re-prioritize a set of topics') and the plural scope clearly distinguishes it from the sibling update_topic tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides a clear usage context by indicating batch operation over multiple topics and instructs the agent to read the 'write-tools' skill before the first call. It does not explicitly name alternatives or state when not to use it, 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.

create_automationCreate AutomationAInspect

Create an automation. Useful for reminders, follow-ups, periodic tasks, or event-driven workflows per user. Returns the full automation object including computed nextRunAt.

Schedule field accepts 5 formats:

  • {type: "at", at: "<ISO 8601>"} - one-time execution (must be future)

  • {type: "every", unit: "minutes"|"hours", n: } - recurring interval (min 30 min)

  • {type: "cron", expr: ""} - cron schedule (min 30 min between runs)

  • {type: "rrule", rrule: ""} - iCalendar rule (min 30 min between occurrences)

  • {type: "event", events: ["", ...]} - event-driven (triggers immediately on ANY of the listed events, up to 20; each occurrence fires one run carrying just that event's payload). {type: "event", event: ""} (single string field) is a legacy alias for a one-event array and is still accepted, but "events" is canonical for new automations. GitHub PR triggers may also include {targetBranches: ["main", ...]} to run only when the PR's target branch matches one of those case-sensitive names or * patterns (e.g. "release/*").

    • matches zero or more characters, including slashes. Omit it to match every target branch. Optionally add {delaySeconds: <int 1..604800>} to an event schedule to defer the run until N seconds after the trigger event fires (e.g. 1800 = 30 minutes later; max 604800 = 7 days). Omit for immediate execution. A delayed run is cancelled if the automation is disabled during the wait. Optionally add {condition: "<natural language, up to 2000 chars>"} to run only for events that satisfy it (e.g. "the customer is on the Enterprise plan"); Modem checks it against each event's payload before running. A condition also satisfies an event that requires a channel or product scope. conditionMode and conditionSchemaVersion are set by Modem and ignored on input.

Available events: github.pr.created, github.pr.merged, github.pr.dismissed, github.issue.closed, gitlab.mr.created, gitlab.mr.merged, gitlab.mr.closed, topic.created, topic.priority.high, stripe.customer.created, stripe.subscription.created, stripe.subscription.canceled, stripe.subscription.trial_ending, stripe.invoice.payment_failed, sentry.feedback.created, feedback.created, topic.group.added, topic.group.updated, conversation.activity

Prompt guidelines: must be self-contained with ALL context the executing agent needs. Write in plain language. Structure as a clear plan with steps. Include external service IDs (Slack channel/user IDs). Never include database internals.

MODEL LEVEL GUIDELINES: Pick the model level that best matches the automation's complexity. Do NOT default to "high".

  • "low" (Fast): Lookup/linking tasks, simple data retrieval, pattern matching, forwarding/routing. Examples: linking PRs to topics, tagging items with keywords, posting simple notifications, checking statuses.

  • "med" (Balanced): Summaries of structured data, daily digests, status rollups, template-based reports. Examples: daily standup summaries, weekly metric rollups, changelog digests, review request roundups.

  • "high" (Smart): Complex analysis, nuanced writing, multi-step reasoning, customer-facing content, creative tasks. Examples: user health analysis, strategic recommendations, personalized outreach, complex triage decisions. When in doubt, use "med" (Balanced).

timezone is required and must be an IANA time zone such as America/New_York. You become its owner. The automation's dashboard page is https://app.modem.dev/<org-slug>/automations/<id>. Before your first call, read the skill: modem_skills({ name: "automations" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesHuman-friendly name for the workflow run, e.g. "weekly_summary_for_alex"
promptYesNatural language instructions for what the automation should do.
enabledNoWhether the automation should be enabled to run on its schedule.
scheduleYesDefines when an automation should run.
timezoneYes
modelLevelNoModel level: "low" (Fast), "med" (Balanced), or "high" (Smart).
capabilityModeNoCapability mode: "all" (all visible capabilities, including ones added later) or "custom" (only listed capabilities). If omitted on create, defaults to "custom" with a snapshot of every currently-available capability so the automation does not silently inherit future integrations.
outputChannelsNoAllowed output channels and optional destination restrictions.
allowedCapabilitiesNoCapability keys to enable when capabilityMode is "custom". On create, providing this field implies custom mode when capabilityMode is omitted. An empty array means core-only.
sourceDefaultTaskSlugNoTemplate-library default task slug this automation is being created from, if any.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare write, non-idempotent, non-destructive. The description adds genuinely new traits: the caller "becomes its owner," delayed runs are cancelled if the automation is disabled mid-wait, and it returns the object with computed nextRunAt. It stops short of discussing auth scopes or error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well front-loaded and sectioned (schedule formats, prompt guidelines, model-level guidelines), but it is long and re-states several schema fields (delaySeconds, condition, targetBranches) almost verbatim, which is duplicative rather than additive.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter creation tool with no output schema, it covers the essentials: schedule grammar, required timezone, ownership, return shape, and a skill pointer for deeper context. Nothing critical to correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already high (90%), but the description adds substantial meaning beyond it: the 30-minute minimum for recurring schedules, model-level selection guidance, prompt-writing rules, the required IANA timezone, and event condition/delay semantics. This far exceeds the baseline-3 expectation for high-coverage schemas.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Create an automation") with concrete use cases (reminders, follow-ups, periodic tasks, event-driven workflows) and the return value. It is unmistakably distinct from siblings like update_automation and list_automations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names the scenarios that justify use (reminders, follow-ups, periodic/event-driven workflows) and gives a prerequisite (read the automations skill before first call). It does not explicitly contrast when to create vs update an existing automation, leaving minor inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_companiesCreate CompaniesCInspect

Create one or more companies in the organization. Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
companiesYes

TDQS

C2.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, idempotentHint=false, and destructiveHint=false, and the description does not contradict them. The description adds the bulk-creation trait and a required skill precondition, but does not discuss duplicate behavior, permissions, or side effects. This is modest context 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences with the core action front-loaded and the skill prerequisite placed second. There is no filler or redundant restatement of the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

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 one parameter with zero schema descriptions, so the description needed to carry more weight. It omits parameter semantics, error or duplicate handling, and any distinction from update/merge siblings. The skill link is helpful but does not fill these gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description adds no meaning for the 'name' or 'domain' fields, including format, uniqueness, or validation. The phrase 'one or more companies' merely restates what the schema already encodes via minItems/maxItems. No parameter semantics are conveyed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Create one or more companies in the organization.' The phrase 'one or more' clarifies bulk capability. It does not explicitly contrast with update_companies or merge_companies, but the create verb inherently distinguishes them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives like update_companies or merge_companies. The instruction to read the write-tools skill is a prerequisite, not a tool-selection guideline. The agent is left to infer when creation is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_feedback_channelCreate Feedback ChannelAInspect

Create a feedback channel for one app and return its feedback token. Send name (the app’s name) and allowedOrigins (every browser origin the app is served from, such as https://app.example.com and http://localhost:3000; omit for an app that does not run in a browser). The channel is created in the organization’s default project. The returned token is shown only in this response, so write it where the app reads it before you do anything else. The token is safe to ship in a browser bundle or a binary: it is valid only for sending feedback to this channel and cannot read anything. Requires an organization admin. Before your first call, read the skill: modem_skills({ name: "install-feedback" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
allowedOriginsNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover mutation/idempotency safety, but the description adds crucial non-obvious behavior: the token is shown only in this response (must be persisted immediately), it is write-only for sending feedback, safe to embed in bundles/binaries, and creation targets the org's default project. These are exactly the traits an agent cannot infer from annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Roughly five sentences, front-loaded with the action and return value, then parameters, then the critical write-it-down warning and auth/skill prerequisites. No filler sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter creation tool with no output schema, the description covers the return value (token), its one-time visibility, its security properties, the project scope, and the auth requirement — everything needed to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates: `name` is defined as the app's name, and `allowedOrigins` is defined as every browser origin with concrete format examples and an explicit omission rule for non-browser apps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource+scope ('Create a feedback channel for one app and return its feedback token'), making it clearly distinguishable from the sibling send_feedback which presumably posts feedback rather than creating a channel.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives strong context: requires an organization admin, instructs reading the `install-feedback` skill before the first call, and explains when to omit allowedOrigins (non-browser apps). It does not explicitly contrast with alternatives like send_feedback, but the prerequisite and gating guidance is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_automationsList AutomationsA
Read-onlyIdempotent
Inspect

List every automation in the organization with its schedule, enabled flag, model level, output channels, creator, and a summary of its recent runs. Call it before create_automation to avoid creating a duplicate, and to find the automationId that update_automation needs. Send userId to list only the automations that user created. Before your first call, read the skill: modem_skills({ name: "automations" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
userIdNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds valuable context beyond them: org-wide scope, filter semantics for userId, and the prerequisite skill step before first invocation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads what the tool returns, then routes to related tools, then explains the filter, then the skill prerequisite. Three tight sentences with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-param read tool with no output schema, it covers return fields, filtering, sibling-tool relationships, and a prerequisite. Adequate and complete for invocation; only the default sort/limit behavior is unstated, which is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry parameter meaning. It explains what userId does ('list only the automations that user created'), which meaningfully compensates, though the param is optional and no format details are given.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List every automation') and enumerates the returned fields (schedule, enabled flag, model level, output channels, creator, recent runs), which distinguishes it from sibling write tools like create_automation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to call it: before create_automation to avoid duplicates, and to obtain the automationId needed by update_automation. It also names the userId filter behavior and a required skill read before first call.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

merge_companiesMerge CompaniesA
Destructive
Inspect

Merge one or more source companies into a target company. Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
targetCompanyIdYes
sourceCompanyIdsYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry destructiveHint=true and readOnlyHint=false, and the description does not contradict them. It adds no details about whether source companies are deleted, reversibility, or permissions; the only addition is the prerequisite to read the write-tools skill, which is useful but not a disclosure of merge behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with the core operation front-loaded and a single actionable prerequisite following. No filler or redundant phrasing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive multi-source merge with no output schema, the description alone lacks the consequences of merging, but it explicitly directs the agent to read the write-tools skill before first use. That reference makes the definition actionable and fairly complete in context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must carry the semantic load, and it does convey which parameter is the target and which are sources, plus 'one or more' cardinality. However, it adds little beyond the property names and minItems in the schema, and does not elaborate on ID formats or parameter-specific constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the action ('Merge'), the object ('companies'), and the relationship ('source companies into a target company'). This is specific enough to distinguish it from sibling tools like merge_people and merge_topics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear operation and a prerequisite (read the write-tools skill), but it does not explicitly say when to use this over merge_people/update_companies or what conditions exclude it. The skill reference is a procedural instruction, not a usage-alternative explanation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

merge_peopleMerge PeopleB
Destructive
Inspect

Merge one or more source people into a target person. Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
targetPersonIdYes
sourcePersonIdsYes

TDQS

B3.4/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare destructiveHint=true and readOnlyHint=false. The description does not add behavioral specifics beyond the annotation, such as whether source people are deleted, whether the merge is reversible, or what side effects occur on related data. It simply restates the merging action without enriching the agent's understanding of what gets destroyed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is delivered in one clear sentence, followed by a concise prerequisite instruction. There is no redundancy or filler; every sentence earns its place. The core behavior is front-loaded before the skill instruction.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation tool with no output schema and minimal parameter descriptions, the description should clarify side effects, return behavior, and any constraints. It only provides the merge concept and a skill reference. An agent would still need to inspect the skill or infer critical details about what happens to source records.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry semantic weight. It does clarify the roles of 'source' and 'target' and notes 'one or more' source people, which aligns with sourcePersonIds' minItems: 1. However, it does not explain ID formats, uniqueness expectations, or what happens if a source person equals the target person. Basic semantics are present but not comprehensive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Merge'), a clear resource ('people'), and the relationship between source and target persons: 'Merge one or more source people into a target person.' This clearly differentiates it from sibling tools like merge_companies and merge_topics by resource type.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes a prerequisite for first use ('read the skill: modem_skills(...)') but does not explicitly state when to use this tool versus alternatives such as merge_companies, merge_topics, or update_people. Usage is only implied by the tool name and resource type. There are no exclusions or alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

merge_topicsMerge TopicsA
Destructive
Inspect

Merge one or more source topics into a target topic. Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
targetTopicIdYesID of the topic to merge into. Must not be in the sourceTopicIds array.
sourceTopicIdsYesIDs of topics to merge into the target. Must not include the target topic ID.

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the agent knows this is a mutating, non-idempotent operation. The description adds no further behavioral context (e.g., whether source topics are deleted, side effects, or return value), but 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence stating the operation, followed by a necessary prerequisite (reading the skill). There is no redundant wording, and the key action is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema, the description is minimal. It references a skill that presumably provides deeper guidance, which adds some context, but it does not clarify the outcome for source topics, potential errors, or response format. The annotation covers the destructive nature, but more detail would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides complete descriptions for both parameters (targetTopicId and sourceTopicIds), including the constraint that they must not overlap. The description adds no additional semantic detail beyond the schema, so a baseline score of 3 is appropriate given 100% schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: merge one or more source topics into a target topic. It identifies the specific resource (topics) and the verb (merge), which distinguishes it from sibling merge tools for companies and people, and from update_topic.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

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 like update_topic or bulk_update_topics. It only states a prerequisite to read a skill before the first call, but does not explain the selection context or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modem_agent_cancel_runCancel Agent RunA
DestructiveIdempotent
Inspect

Cooperatively cancel one exact durable Modem agent run. Completed external actions are not reversed.

ParametersJSON Schema
NameRequiredDescriptionDefault
run_idYesRun ID returned by modem_agent_invoke or modem_agent_send_message.
conversation_idYesConversation ID returned by modem_agent_invoke.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond annotations with 'cooperatively' and especially 'completed external actions are not reversed,' which is critical for an agent deciding whether to cancel. 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded action, no redundancy. The key caveat is included.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Definitions clear with both params documented, plus the critical non-reversal caveat. Missing only explicit routing to siblings and return expectations, which are not essential for a destructive cancel action.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers both parameters with clear descriptions (IDs returned by modem_agent_invoke). Description adds no new parameter-level meaning beyond 'exact' run targeting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('cancel') and identifies the exact target ('one exact durable Modem agent run'). It is clearly distinguished from sibling tools like modem_agent_get_run or modem_agent_invoke.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives, no prerequisites or conditions for cancellation, and no mention of what to check before invoking. The caveat about external actions is behavioral, not usage routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modem_agent_get_runGet Agent RunA
Read-onlyIdempotent
Inspect

Get the current status and terminal result of a durable Modem agent run.

ParametersJSON Schema
NameRequiredDescriptionDefault
run_idYesRun ID returned by modem_agent_invoke or modem_agent_send_message.
conversation_idYesConversation ID returned by modem_agent_invoke.

TDQS

A3.8/5.0
Behavior3/5

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 clear. The description adds 'durable' and 'terminal result', which slightly extends context, but it does not specify response behavior, failure modes, or what 'terminal' means in practice. It provides some value beyond annotations but does not go deep.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that states the verb, resource, and key qualifiers without any filler. Every word contributes meaning, making it highly efficient for agent parsing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 two well-documented parameters and comprehensive annotations, the description is nearly complete. It does not explain what 'terminal result' entails or the response format, but with no output schema, these details are less critical. The core usage is fully covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with both run_id and conversation_id fully described in the input schema. The description adds no additional parameter context, so it meets the baseline for schema-heavy definitions but offers no extra semantic enrichment.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Get') and resource ('current status and terminal result of a durable Modem agent run'), clearly distinguishing it from sibling tools like modem_agent_invoke, modem_agent_send_message, and modem_agent_cancel_run. The purpose is unambiguous and the scope is well-defined.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage (to retrieve status after a run has been invoked) but does not explicitly state when to use it vs. alternatives, nor does it mention that it complements invoke/send_message or that cancel_run is for termination. The guidance is not misleading but relies on the tool name and context for full clarity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modem_agent_invokeRun Modem AgentA
DestructiveIdempotent
Inspect

Start a durable Modem agent conversation. Returns immediately with conversation_id and run_id; poll modem_agent_get_run for the result. Before your first call, read the skill: modem_skills({ name: "agent-runs" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesNatural-language prompt for the Modem agent.
idempotency_keyYesStable retry key. Reuse only for the exact same prompt.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark idempotentHint and destructiveHint, and the description adds the useful async behavior ('Returns immediately... poll ... for the result') plus a prerequisite skill read. 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: what it does, how to get the result, and the required prerequisite. The most important behavior is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-parameter async invocation with no output schema, the description covers the start behavior, polling path, and prerequisite skill. It could optionally mention how to continue or cancel the conversation, but nothing essential to making the first correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both prompt and idempotency_key are already documented in the schema. The description adds no additional parameter semantics beyond the stable-retry-key concept implied by idempotency_key.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Start a durable Modem agent conversation'), notes it returns immediately with conversation_id and run_id, and distinguishes itself from the polling sibling modem_agent_get_run. This makes its role clear relative to 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit context: use this to start a conversation, poll modem_agent_get_run for the result, and read modem_skills before the first call. It does not formally enumerate when not to use it or contrast with modem_agent_send_message/cancel_run, but the start-vs-poll workflow is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modem_agent_send_messageSend Agent MessageA
DestructiveIdempotent
Inspect

Start a durable follow-up turn in an existing MCP conversation.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptYesFollow-up prompt for the Modem agent.
conversation_idYesExisting MCP conversation ID.
idempotency_keyYesStable retry key for this follow-up.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already convey mutation (readOnlyHint=false), idempotency, open-world side effects, and destructiveness. The description adds 'durable' to suggest persistent execution, but it does not explain what state changes are made, what destructive effects may occur, or how the agent should observe progress. Given annotations carry the safety profile, this is acceptable 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no filler. It states the core action and scope immediately while leaving detailed parameter semantics to the schema, which is appropriately concise for a tool with good annotation coverage.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the sibling tools include modem_agent_get_run and modem_agent_cancel_run, the description could usefully mention that this starts a run and that results can be checked with get_run. There is no output schema, so the agent is left to infer the return behavior. The term 'durable' hints at asynchronous execution, but the definition does not fully explain follow-up mechanics or retry behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides complete, meaningful descriptions for all three parameters (prompt, conversation_id, idempotency_key), so schema coverage is 100%. The description adds no additional parameter-level meaning beyond what the schema already documents, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('start') and a distinct resource/operation ('a durable follow-up turn in an existing MCP conversation'), which clearly communicates the tool's function. It implicitly separates itself from siblings like modem_agent_get_run, modem_agent_cancel_run, and search_modem, though it does not explicitly name the alternative for starting a new conversation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'in an existing MCP conversation' provides clear contextual guidance that this tool is for follow-up turns, not initial invocations or status checks. However, it does not explicitly name alternatives or state when-not-to-use conditions, 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.

modem_docsModem DocsA
Read-onlyIdempotent
Inspect

Search or read Modem's public docs to answer how Modem works: setup, integrations, this MCP server and its scopes, the API, and automations. Not for your organization's data; use search_modem for that. Send a query to search, or a page path from a search result (such as api/modem-mcp-server) to read the whole page. Send exactly one. Read-only, spends no agent credits.

ParametersJSON Schema
NameRequiredDescriptionDefault
pageNoA docs page path exactly as a search result prints it, such as `api/modem-mcp-server`. Returns the whole page.
queryNoWhat to look up in the Modem docs, in plain words. Returns the matching doc sections.

TDQS

A4.7/5.0
Behavior4/5

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 genuinely new behavioral context beyond the annotations: that it spends no agent credits, and that `page` returns the whole page while `query` returns matching sections.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with purpose then scope exclusion then usage mechanics. Every clause carries information: routing, mode selection, and cost.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-param read-only docs tool with no output schema, the description covers purpose, alternatives, mode selection, and what each mode returns. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 real meaning the schema lacks: the mutual-exclusivity rule ('send exactly one'), the workflow relationship (page path comes from a search result), and a concrete path example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb pair (search/read) and resource (Modem's public docs) and enumerates the covered topics: setup, integrations, MCP server and scopes, the API, automations. It explicitly distinguishes itself from the sibling `search_modem` by naming what it is NOT for (your organization's data).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing: use this for how Modem works, use `search_modem` for org data. It also explains the two modes — send `query` to search, send a `page` path from a search result to read — and the constraint 'send exactly one', leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modem_skillsModem SkillsA
Read-onlyIdempotent
Inspect

Skills that teach you how to use THIS Modem MCP server's tools. Call before your first search_modem, modem_agent_invoke, or write-tool call, or when unsure which Modem tool to use. Pass name for the full skill, one of search-modem, agent-runs, write-tools, install-feedback, automations. Omit name to list them with descriptions. This is not the Skills page in dashboard settings.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoA skill from this server's catalog, e.g. "search-modem". Not a path or an outside skill name. Omit to list the catalog.

TDQS

A4.1/5.0
Behavior4/5

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 only needs to add context. It does: it discloses the enumeration of valid skill names, that omitting name lists the catalog, and that this is not the dashboard Skills page. Return shape when a skill is fetched is only loosely implied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the what, then the when, then the parameter behavior, then a one-line disambiguation. No sentence is redundant against another, and the most decision-relevant information (when to call) comes early.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

One optional parameter, full schema coverage, no output schema, read-only annotations – the description supplies the calling preconditions and the value set, which is everything needed to invoke correctly. The only omission is any differentiation from modem_docs among the siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 goes beyond the schema by enumerating the five catalog values ('search-modem', 'agent-runs', 'write-tools', 'install-feedback', 'automations'), which the schema only gestures at with a single example and no enum. That materially reduces wrong-value calls.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource and function: skill documents that teach usage of this server's tools, with the referent 'THIS Modem MCP server' pinned down and an explicit disambiguation from the dashboard Skills page. It does not, however, distinguish itself from the sibling tool modem_docs, which an agent could reasonably confuse it with for 'how do I use this server' questions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete trigger conditions (before the first search_modem, modem_agent_invoke, or write-tool call; when unsure which tool to use) and explains the omit-name behavior. The gap is that it never contrasts itself with modem_docs, so the agent has no routing rule between the two documentation-ish tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_modemSearch ModemA
Read-onlyIdempotent
Inspect

Answer a natural-language question about your Modem data and get matching rows back. Read-only. It does not run the full Modem agent or spend agent credits. Send a question, or send only the cursor from a previous result to fetch its next page. Topic priority in the rows is an integer: very_low (-100), low (-50), default (0), high (50), very_high (100). Before your first call, read the skill: modem_skills({ name: "search-modem" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoPage size. When set, the engine pages the result server-side and returns a cursor when more rows exist.
cursorNoOpaque continuation token from a previous response. Fetches the next page of the same result set without re-running the search.
columnsNoRequested row shape — the columns each returned row must carry, validated against them (see the schema field on the result). Without it the engine returns a sensible default shape for the question — consistent for common intents, but not validated or guaranteed; pass this whenever you need a SPECIFIC, validated, and stable shape. A cursor continuation reuses the first page’s columns, so it stays stable regardless.
contextNoWhat the user is trying to accomplish with this search. It does not change the results, so put every filter in question.
questionNoNatural-language data question. Required unless cursor is provided. Returns matching rows without invoking the paid Modem agent.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, and the description adds value beyond them: no agent invocation and no credit spend, reuse of first-page columns on cursor continuations, and the integer encoding of the priority topic in returned rows. The skill-call prerequisite is a behavioral requirement that appears nowhere in 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and read-only status are front-loaded, followed by the pagination contract, the result-interpretation note, and the skill prerequisite. Every sentence carries information an agent needs and none is redundant with the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-parameter, zero-required search tool with no output schema, the description covers invocation modes, paging, result shape validation, and the mandatory skill step. An agent has everything required to call it correctly on the first attempt.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 goes further by clarifying the cursor-only call pattern, the mutually exclusive relationship between question and cursor, and that context does not affect results so all filters must live in question. The priority value mapping is documented here rather than in any parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource – answer a natural-language question about Modem data and return matching rows – and immediately demarcates itself from the sibling modem_agent_invoke by noting it does not run the full agent or spend credits. An agent can distinguish this from the other search/agent tools 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use (send a question) and when-to-use-alternatively (send only the cursor to page), plus a prerequisite (read the modem_skills skill before first call) and the cost-based reason to prefer this over the paid agent path. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_feedbackSend Feedback to ModemAInspect

Send feedback about Modem to the Modem team. Offer it when a Modem tool fails or returns something you cannot act on, when you need a capability Modem does not have, or when an error is unclear (category agent_friction); and when the user voices feedback or frustration or asks for something Modem cannot do (category user_feedback, the default, in the user’s words). Call it only when the user asks to or agrees, never on your own: tell them what you will send, and tell them when it is sent. In message (up to 4096 characters), describe what you tried, what happened, and what you expected instead. Include only what explains the problem: never credentials, tokens, or personal data unrelated to it. Send the user’s name and email: the Modem team replies to that address, so ask for them if the conversation does not already have them. For a failing tool, send its name in tags as tool_name, its trace ID in trace_id, and what you were attempting in context. Add release for your client’s version when you know it. Your MCP client is attached for you. Returns the id of the feedback event Modem recorded.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNo
nameYes
tagsNo
emailYes
contextNo
messageYes
releaseNo
categoryNo
trace_idNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the generic write/openWorld/non-idempotent profile; the description adds the consequential behavior an agent actually needs: user consent required before sending, PII/credential prohibitions, that the Modem team replies to the given email, and that the call returns a feedback event id. This goes well beyond the structured hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads purpose, then usage, then parameter-filling instructions, so scanning order matches decision order. It is dense with nested parenthetical conditions, which costs some readability, but for a 9-parameter tool every sentence adds real instruction rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers the consent workflow, the required-vs-optional field split, nested object contents (tags, context), the enum decision, and the return value despite there being no output schema. Nothing an agent needs to invoke this correctly is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage the description carries the full burden and delivers: content and length guidance for message (4096), when each category enum applies, tool_name/trace_id/context for failures, release, and the reply semantics of name/email. Only url is left unexplained, a minor gap against otherwise rich compensation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Send feedback about Modem to the Modem team') and clearly separates itself from the sibling create_feedback_channel, which manages channels rather than transmitting feedback. An agent can identify the operation 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.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit triggering conditions for each category (tool failure/unclear error → agent_friction; user frustration/missing capability → user_feedback) and a hard when-not rule: 'Call it only when the user asks to or agrees, never on your own.' The consent protocol (tell them what you will send, and when it is sent) closes the loop.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_automationUpdate AutomationA
Destructive
Inspect

Update an automation. Only provide fields that need to change.

Schedule field accepts the same 5 formats as create:

  • {type: "at", at: "<ISO 8601>"} - one-time execution

  • {type: "every", unit: "minutes"|"hours", n: } - recurring interval (min 30 min)

  • {type: "cron", expr: ""} - cron schedule (min 30 min between runs)

  • {type: "rrule", rrule: ""} - iCalendar rule (min 30 min between occurrences)

  • {type: "event", events: ["", ...]} - event-driven (triggers immediately on ANY of the listed events, up to 20). {type: "event", event: ""} is a legacy single-event alias, still accepted but not canonical. Optionally add {delaySeconds: <int 1..604800>} to defer the run until N seconds after the event fires (max 604800 = 7 days); omit for immediate. GitHub PR triggers may include {targetBranches: ["main", "release/*", ...]} with case-sensitive names or * wildcards. Optionally add {condition: "<natural language, up to 2000 chars>"} to run only for events that satisfy it; omit it to run on every event. conditionMode and conditionSchemaVersion are set by Modem.

Available events: github.pr.created, github.pr.merged, github.pr.dismissed, github.issue.closed, gitlab.mr.created, gitlab.mr.merged, gitlab.mr.closed, topic.created, topic.priority.high, stripe.customer.created, stripe.subscription.created, stripe.subscription.canceled, stripe.subscription.trial_ending, stripe.invoice.payment_failed, sentry.feedback.created, feedback.created, topic.group.added, topic.group.updated, conversation.activity

Send automationId and only the fields that change. The automation's dashboard page is https://app.modem.dev/<org-slug>/automations/<id>. Before your first call, read the skill: modem_skills({ name: "automations" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
promptNoNatural language instructions for what the task should do.
enabledNo
scheduleNoDefines when an automation should run.
timezoneNo
modelLevelNoPersisted model level for automation execution.
automationIdYes
capabilityModeNoCapability mode: "all" (all visible capabilities) or "custom" (only listed capabilities).
outputChannelsNoAllowed output channels and optional destination restrictions.
allowedCapabilitiesNoCapability keys to enable when capabilityMode is "custom". Providing this field implies custom mode when capabilityMode is omitted. An empty array means core-only.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=false, readOnlyHint=false, so the safety profile is covered. The description adds genuinely useful context that this is a patch-style update (omitted fields presumably preserved) and that two fields are server-derived and ignored. However, it never explains what 'destructive' means here, whether omitted fields are cleared, or any auth/rate-limit constraints, so it adds only 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core rule before the schedule details, and the bulleted format is scannable. It is long, but much of the length is justified by a genuinely complex oneOf schedule schema; some content (delaySeconds, targetBranches, legacy event alias) duplicates schema descriptions and could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter mutation tool with no output schema, the description covers the complex schedule/event surface thoroughly and redirects the agent to the automations skill for the rest, which closes most gaps. It omits any description of the non-schedule fields' behavior and the mutation's effects, leaving some reliance on the skill.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 60%, and the description compensates substantially for the hardest parameter: it enumerates all five schedule formats, the 30-minute minimums, the max-20 events cap, the delaySeconds range, targetBranches wildcard semantics, and — critically — the full list of available event names, which the schema does not provide at all. The remaining simpler parameters (name, prompt, timezone, modelLevel, outputChannels) get no description-level treatment, but the schema documents most of them.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource (update an automation) and adds the partial-update rule ('only provide fields that need to change'). Sibling tools create_automation/list_automations make the distinction self-evident, so no explicit differentiation is required. It is clear but not exceptional.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides concrete usage prerequisites: send automationId plus only changed fields, and read the automations skill before the first call. It also warns that conditionMode/conditionSchemaVersion are server-set and ignored on input. It stops short of stating when to prefer this over create_automation or what happens on a nonexistent id.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_companiesUpdate CompaniesB
DestructiveIdempotent
Inspect

Update fields on one or more existing companies. Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
companiesYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=false, idempotentHint=true, and destructiveHint=true, so the description does not need to restate the mutation safety profile. It adds the useful prerequisite that the write-tools skill must be read first, but it does not clarify overwrite/merge semantics for omitted fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, action first, with no filler. The skill prerequisite is a necessary operational instruction and earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The definition covers the prerequisite and basic purpose, but for a mutation tool with destructiveHint=true and no output schema it stays minimal: it omits update semantics, alternative routing, and any mention of what happens to values not supplied. It is adequate for a simple schema but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description should compensate by explaining the companies array, the required companyId, and field update semantics; it only adds 'one or more existing companies,' which the schema's minItems/maxItems already conveys. The nested connections and optional fields are left entirely to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('update') and resource ('existing companies'), which makes the core action clear and separates it from create/merge siblings. It does not explicitly name or contrast any sibling, so it stops short of full differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'existing companies' implies this is for modifying already-created records rather than creating or merging, and the skill-reading instruction provides a clear prerequisite for use. However, it does not explicitly state when to prefer this over update_people, merge_companies, or other alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_peopleUpdate PeopleB
DestructiveIdempotent
Inspect

Update fields on one or more existing people. Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
peopleYes

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=true, readOnlyHint=false and openWorldHint=false, so the safety profile is covered structurally. The description adds the bulk scope and skill prerequisite, but never explains what makes this destructive (e.g., whether null values clear existing fields) even though that is the most consequential behavior here.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the purpose front-loaded and the required prerequisite second. Nothing is wasted and nothing is buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

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, annotations carry the safety story and the skill pointer may offload deeper detail. Still, the description omits how field clearing works and any indication of what a call returns, which leaves a real gap for a destructive, idempotent mutation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single array parameter is entirely undocumented in the schema. The description only implies the array/plural shape and says nothing about which fields are updatable, what a null value does, or the 1-50 item bounds — leaving the agent to reverse-engineer the payload.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Update fields on ... existing people') and adds the scope detail 'one or more', which signals bulk-update capability. It does not explicitly distinguish itself from siblings like merge_people or update_companies, 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.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides a concrete prerequisite ('Before your first call, read the skill: modem_skills(...)'), which is genuinely useful workflow guidance. It gives no when-to-use/when-not-to-use guidance relative to alternatives such as merge_people, so usage is only partially framed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_topicUpdate TopicB
DestructiveIdempotent
Inspect

Update a single topic (priority, lifecycle state, archived status, issue type, or keywords). Before your first call, read the skill: modem_skills({ name: "write-tools" }).

ParametersJSON Schema
NameRequiredDescriptionDefault
topicIdYes
archivedNoSet to true to archive the topic, false to unarchive it.
keywordsNoNot supported: the topic pipeline derives the keywords. Sending this field returns 400.
priorityNoUpdate the topic priority. Valid values: very_low, low, default, high, very_high.
issueTypeNoNot supported: the topic pipeline derives the issue type. Sending this field returns 400.
archivedReasonNoOptional reason for archiving. Only used when archived=true.
lifecycleStateNoUpdate the topic lifecycle state. Valid values: open, in_progress, completed, dismissed. The unknown state is AI-assessed and cannot be set directly.

TDQS

B3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, so the safety profile is partly covered. The description's additional content is actively harmful: it lists 'issue type' and 'keywords' as updatable fields, yet the schema marks both as unsupported and returning 400, which would mislead an agent into a failing call. The skill pointer is the only 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the action front-loaded before the prerequisite pointer; no filler. Slightly diminished because one of the two sentences spends space on fields the tool does not actually accept.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive mutation with no output schema, an agent would want to know what happens to unmentioned fields, whether archivedReason is dropped when archived=false, and permission requirements. The skill pointer covers some of this indirectly, but the description itself leaves the destructive semantics under-explained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 86%, so the baseline would be 3. However, the description's field list contradicts the schema by presenting the two unsupported fields (issueType, keywords) as updatable options, so it degrades rather than augments parameter understanding. It adds nothing about archivedReason, topicId format, or the enum semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

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 a single topic') and enumerates the mutable fields, so the agent knows what the tool does. 'Single' loosely distinguishes it from the sibling bulk_update_topics, though that 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.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a concrete prerequisite ('Before your first call, read the skill: modem_skills(...)'), which is genuinely useful routing. But it never says when to prefer this over bulk_update_topics or merge_topics, nor what conditions make a single-topic update appropriate.

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.

  1. 2 tool updates
    • Changedcreate_automation1 field changed
      • changedInput schema / properties / schedule / oneOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "expr": {
        -        "description": "Standard cron expression string.",
        -        "minLength": 1,
        -        "title": "Cron Expression",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "cron",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "expr"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "rrule": {
        -        "description": "iCalendar recurrence rule (RFC 5545) string.",
        -        "minLength": 1,
        -        "title": "RRule",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "rrule",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "rrule"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "at": {
        -        "description": "ISO 8601 timestamp for one-time execution.",
        -        "minLength": 1,
        -        "title": "At Time",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "at",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "at"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "n": {
        -        "description": "Number of time units between executions.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "title": "Interval",
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "every",
        -        "type": "string"
        -      },
        -      "unit": {
        -        "description": "Time unit for interval scheduling.",
        -        "enum": [
        -          "minutes",
        -          "hours"
        -        ],
        -        "title": "Time Unit",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "unit",
        -      "n"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "channelIds": {
        -        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Channel IDs",
        -        "type": "array"
        -      },
        -      "condition": {
        -        "description": "Optional free-form natural-language condition (\"only run when …\"), up to 2000 characters, evaluated against each trigger event's payload; the automation runs only for events that satisfy it. Omit to run on every matching event.",
        -        "maxLength": 2000,
        -        "minLength": 1,
        -        "title": "Trigger Condition",
        -        "type": "string"
        -      },
        -      "conditionMode": {
        -        "description": "Server-derived; ignored on input. judge = the condition is decided from the event payload before the run starts; agent = the agent decides it at the start of every run.",
        -        "enum": [
        -          "judge",
        -          "agent"
        -        ],
        -        "title": "Condition Mode",
        -        "type": "string"
        -      },
        -      "conditionSchemaVersion": {
        -        "description": "Server-derived; ignored on input. The version of the event field guide the condition was judged against; absent when it was not judged.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "title": "Condition Schema Version",
        -        "type": "integer"
        -      },
        -      "delaySeconds": {
        -        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        -        "maximum": 604800,
        -        "minimum": 1,
        -        "title": "Delay (seconds)",
        -        "type": "integer"
        -      },
        -      "event": {
        -        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        -        "minLength": 1,
        -        "title": "Event Name (legacy single-event form)",
        -        "type": "string"
        -      },
        -      "events": {
        -        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        -        "items": {
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "maxItems": 20,
        -        "minItems": 1,
        -        "title": "Event Names",
        -        "type": "array"
        -      },
        -      "productIds": {
        -        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Product IDs",
        -        "type": "array"
        -      },
        -      "targetBranches": {
        -        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        -        "items": {
        -          "minLength": 1,
        -          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Target Branches",
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "event",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "expr": {
        +        "description": "Standard cron expression string.",
        +        "minLength": 1,
        +        "title": "Cron Expression",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "cron",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "expr"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "rrule": {
        +        "description": "iCalendar recurrence rule (RFC 5545) string.",
        +        "minLength": 1,
        +        "title": "RRule",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "rrule",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "rrule"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "at": {
        +        "description": "ISO 8601 timestamp for one-time execution.",
        +        "minLength": 1,
        +        "title": "At Time",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "at",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "at"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "n": {
        +        "description": "Number of time units between executions.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Interval",
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "every",
        +        "type": "string"
        +      },
        +      "unit": {
        +        "description": "Time unit for interval scheduling.",
        +        "enum": [
        +          "minutes",
        +          "hours"
        +        ],
        +        "title": "Time Unit",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "unit",
        +      "n"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "channelIds": {
        +        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Channel IDs",
        +        "type": "array"
        +      },
        +      "condition": {
        +        "description": "Optional free-form natural-language condition (\"only run when …\"), up to 2000 characters, evaluated against each trigger event's payload; the automation runs only for events that satisfy it. Omit to run on every matching event. A condition also satisfies an event that requires a channel or product scope.",
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "title": "Trigger Condition",
        +        "type": "string"
        +      },
        +      "conditionMode": {
        +        "description": "Server-derived; ignored on input. judge = the condition is decided from the event payload before the run starts; agent = the agent decides it at the start of every run.",
        +        "enum": [
        +          "judge",
        +          "agent"
        +        ],
        +        "title": "Condition Mode",
        +        "type": "string"
        +      },
        +      "conditionSchemaVersion": {
        +        "description": "Server-derived; ignored on input. The version of the event field guide the condition was judged against; absent when it was not judged.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Condition Schema Version",
        +        "type": "integer"
        +      },
        +      "delaySeconds": {
        +        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        +        "maximum": 604800,
        +        "minimum": 1,
        +        "title": "Delay (seconds)",
        +        "type": "integer"
        +      },
        +      "event": {
        +        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        +        "minLength": 1,
        +        "title": "Event Name (legacy single-event form)",
        +        "type": "string"
        +      },
        +      "events": {
        +        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        +        "items": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 20,
        +        "minItems": 1,
        +        "title": "Event Names",
        +        "type": "array"
        +      },
        +      "productIds": {
        +        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Product IDs",
        +        "type": "array"
        +      },
        +      "targetBranches": {
        +        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        +        "items": {
        +          "minLength": 1,
        +          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Target Branches",
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "event",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedupdate_automation1 field changed
      • changedInput schema / properties / schedule / oneOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "expr": {
        -        "description": "Standard cron expression string.",
        -        "minLength": 1,
        -        "title": "Cron Expression",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "cron",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "expr"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "rrule": {
        -        "description": "iCalendar recurrence rule (RFC 5545) string.",
        -        "minLength": 1,
        -        "title": "RRule",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "rrule",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "rrule"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "at": {
        -        "description": "ISO 8601 timestamp for one-time execution.",
        -        "minLength": 1,
        -        "title": "At Time",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "at",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "at"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "n": {
        -        "description": "Number of time units between executions.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "title": "Interval",
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "every",
        -        "type": "string"
        -      },
        -      "unit": {
        -        "description": "Time unit for interval scheduling.",
        -        "enum": [
        -          "minutes",
        -          "hours"
        -        ],
        -        "title": "Time Unit",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "unit",
        -      "n"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "channelIds": {
        -        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Channel IDs",
        -        "type": "array"
        -      },
        -      "condition": {
        -        "description": "Optional free-form natural-language condition (\"only run when …\"), up to 2000 characters, evaluated against each trigger event's payload; the automation runs only for events that satisfy it. Omit to run on every matching event.",
        -        "maxLength": 2000,
        -        "minLength": 1,
        -        "title": "Trigger Condition",
        -        "type": "string"
        -      },
        -      "conditionMode": {
        -        "description": "Server-derived; ignored on input. judge = the condition is decided from the event payload before the run starts; agent = the agent decides it at the start of every run.",
        -        "enum": [
        -          "judge",
        -          "agent"
        -        ],
        -        "title": "Condition Mode",
        -        "type": "string"
        -      },
        -      "conditionSchemaVersion": {
        -        "description": "Server-derived; ignored on input. The version of the event field guide the condition was judged against; absent when it was not judged.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "title": "Condition Schema Version",
        -        "type": "integer"
        -      },
        -      "delaySeconds": {
        -        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        -        "maximum": 604800,
        -        "minimum": 1,
        -        "title": "Delay (seconds)",
        -        "type": "integer"
        -      },
        -      "event": {
        -        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        -        "minLength": 1,
        -        "title": "Event Name (legacy single-event form)",
        -        "type": "string"
        -      },
        -      "events": {
        -        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        -        "items": {
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "maxItems": 20,
        -        "minItems": 1,
        -        "title": "Event Names",
        -        "type": "array"
        -      },
        -      "productIds": {
        -        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Product IDs",
        -        "type": "array"
        -      },
        -      "targetBranches": {
        -        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        -        "items": {
        -          "minLength": 1,
        -          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Target Branches",
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "event",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "expr": {
        +        "description": "Standard cron expression string.",
        +        "minLength": 1,
        +        "title": "Cron Expression",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "cron",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "expr"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "rrule": {
        +        "description": "iCalendar recurrence rule (RFC 5545) string.",
        +        "minLength": 1,
        +        "title": "RRule",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "rrule",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "rrule"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "at": {
        +        "description": "ISO 8601 timestamp for one-time execution.",
        +        "minLength": 1,
        +        "title": "At Time",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "at",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "at"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "n": {
        +        "description": "Number of time units between executions.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Interval",
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "every",
        +        "type": "string"
        +      },
        +      "unit": {
        +        "description": "Time unit for interval scheduling.",
        +        "enum": [
        +          "minutes",
        +          "hours"
        +        ],
        +        "title": "Time Unit",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "unit",
        +      "n"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "channelIds": {
        +        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Channel IDs",
        +        "type": "array"
        +      },
        +      "condition": {
        +        "description": "Optional free-form natural-language condition (\"only run when …\"), up to 2000 characters, evaluated against each trigger event's payload; the automation runs only for events that satisfy it. Omit to run on every matching event. A condition also satisfies an event that requires a channel or product scope.",
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "title": "Trigger Condition",
        +        "type": "string"
        +      },
        +      "conditionMode": {
        +        "description": "Server-derived; ignored on input. judge = the condition is decided from the event payload before the run starts; agent = the agent decides it at the start of every run.",
        +        "enum": [
        +          "judge",
        +          "agent"
        +        ],
        +        "title": "Condition Mode",
        +        "type": "string"
        +      },
        +      "conditionSchemaVersion": {
        +        "description": "Server-derived; ignored on input. The version of the event field guide the condition was judged against; absent when it was not judged.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Condition Schema Version",
        +        "type": "integer"
        +      },
        +      "delaySeconds": {
        +        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        +        "maximum": 604800,
        +        "minimum": 1,
        +        "title": "Delay (seconds)",
        +        "type": "integer"
        +      },
        +      "event": {
        +        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        +        "minLength": 1,
        +        "title": "Event Name (legacy single-event form)",
        +        "type": "string"
        +      },
        +      "events": {
        +        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        +        "items": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 20,
        +        "minItems": 1,
        +        "title": "Event Names",
        +        "type": "array"
        +      },
        +      "productIds": {
        +        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Product IDs",
        +        "type": "array"
        +      },
        +      "targetBranches": {
        +        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        +        "items": {
        +          "minLength": 1,
        +          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Target Branches",
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "event",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  }
        +]
  2. 2 tool updates
    • Changedcreate_automation1 field changed
      • changedInput schema / properties / schedule / oneOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "expr": {
        -        "description": "Standard cron expression string.",
        -        "minLength": 1,
        -        "title": "Cron Expression",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "cron",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "expr"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "rrule": {
        -        "description": "iCalendar recurrence rule (RFC 5545) string.",
        -        "minLength": 1,
        -        "title": "RRule",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "rrule",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "rrule"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "at": {
        -        "description": "ISO 8601 timestamp for one-time execution.",
        -        "minLength": 1,
        -        "title": "At Time",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "at",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "at"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "n": {
        -        "description": "Number of time units between executions.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "title": "Interval",
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "every",
        -        "type": "string"
        -      },
        -      "unit": {
        -        "description": "Time unit for interval scheduling.",
        -        "enum": [
        -          "minutes",
        -          "hours"
        -        ],
        -        "title": "Time Unit",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "unit",
        -      "n"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "channelIds": {
        -        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Channel IDs",
        -        "type": "array"
        -      },
        -      "delaySeconds": {
        -        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        -        "maximum": 604800,
        -        "minimum": 1,
        -        "title": "Delay (seconds)",
        -        "type": "integer"
        -      },
        -      "event": {
        -        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        -        "minLength": 1,
        -        "title": "Event Name (legacy single-event form)",
        -        "type": "string"
        -      },
        -      "events": {
        -        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        -        "items": {
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "maxItems": 20,
        -        "minItems": 1,
        -        "title": "Event Names",
        -        "type": "array"
        -      },
        -      "productIds": {
        -        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Product IDs",
        -        "type": "array"
        -      },
        -      "targetBranches": {
        -        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        -        "items": {
        -          "minLength": 1,
        -          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Target Branches",
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "event",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "expr": {
        +        "description": "Standard cron expression string.",
        +        "minLength": 1,
        +        "title": "Cron Expression",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "cron",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "expr"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "rrule": {
        +        "description": "iCalendar recurrence rule (RFC 5545) string.",
        +        "minLength": 1,
        +        "title": "RRule",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "rrule",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "rrule"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "at": {
        +        "description": "ISO 8601 timestamp for one-time execution.",
        +        "minLength": 1,
        +        "title": "At Time",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "at",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "at"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "n": {
        +        "description": "Number of time units between executions.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Interval",
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "every",
        +        "type": "string"
        +      },
        +      "unit": {
        +        "description": "Time unit for interval scheduling.",
        +        "enum": [
        +          "minutes",
        +          "hours"
        +        ],
        +        "title": "Time Unit",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "unit",
        +      "n"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "channelIds": {
        +        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Channel IDs",
        +        "type": "array"
        +      },
        +      "condition": {
        +        "description": "Optional free-form natural-language condition (\"only run when …\"), up to 2000 characters, evaluated against each trigger event's payload; the automation runs only for events that satisfy it. Omit to run on every matching event.",
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "title": "Trigger Condition",
        +        "type": "string"
        +      },
        +      "conditionMode": {
        +        "description": "Server-derived; ignored on input. judge = the condition is decided from the event payload before the run starts; agent = the agent decides it at the start of every run.",
        +        "enum": [
        +          "judge",
        +          "agent"
        +        ],
        +        "title": "Condition Mode",
        +        "type": "string"
        +      },
        +      "conditionSchemaVersion": {
        +        "description": "Server-derived; ignored on input. The version of the event field guide the condition was judged against; absent when it was not judged.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Condition Schema Version",
        +        "type": "integer"
        +      },
        +      "delaySeconds": {
        +        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        +        "maximum": 604800,
        +        "minimum": 1,
        +        "title": "Delay (seconds)",
        +        "type": "integer"
        +      },
        +      "event": {
        +        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        +        "minLength": 1,
        +        "title": "Event Name (legacy single-event form)",
        +        "type": "string"
        +      },
        +      "events": {
        +        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        +        "items": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 20,
        +        "minItems": 1,
        +        "title": "Event Names",
        +        "type": "array"
        +      },
        +      "productIds": {
        +        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Product IDs",
        +        "type": "array"
        +      },
        +      "targetBranches": {
        +        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        +        "items": {
        +          "minLength": 1,
        +          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Target Branches",
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "event",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  }
        +]
    • Changedupdate_automation1 field changed
      • changedInput schema / properties / schedule / oneOf
        Previous value: -[
        -  {
        -    "properties": {
        -      "expr": {
        -        "description": "Standard cron expression string.",
        -        "minLength": 1,
        -        "title": "Cron Expression",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "cron",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "expr"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "rrule": {
        -        "description": "iCalendar recurrence rule (RFC 5545) string.",
        -        "minLength": 1,
        -        "title": "RRule",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "rrule",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "rrule"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "at": {
        -        "description": "ISO 8601 timestamp for one-time execution.",
        -        "minLength": 1,
        -        "title": "At Time",
        -        "type": "string"
        -      },
        -      "type": {
        -        "const": "at",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "at"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "n": {
        -        "description": "Number of time units between executions.",
        -        "exclusiveMinimum": 0,
        -        "maximum": 9007199254740991,
        -        "title": "Interval",
        -        "type": "integer"
        -      },
        -      "type": {
        -        "const": "every",
        -        "type": "string"
        -      },
        -      "unit": {
        -        "description": "Time unit for interval scheduling.",
        -        "enum": [
        -          "minutes",
        -          "hours"
        -        ],
        -        "title": "Time Unit",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type",
        -      "unit",
        -      "n"
        -    ],
        -    "type": "object"
        -  },
        -  {
        -    "properties": {
        -      "channelIds": {
        -        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Channel IDs",
        -        "type": "array"
        -      },
        -      "delaySeconds": {
        -        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        -        "maximum": 604800,
        -        "minimum": 1,
        -        "title": "Delay (seconds)",
        -        "type": "integer"
        -      },
        -      "event": {
        -        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        -        "minLength": 1,
        -        "title": "Event Name (legacy single-event form)",
        -        "type": "string"
        -      },
        -      "events": {
        -        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        -        "items": {
        -          "minLength": 1,
        -          "type": "string"
        -        },
        -        "maxItems": 20,
        -        "minItems": 1,
        -        "title": "Event Names",
        -        "type": "array"
        -      },
        -      "productIds": {
        -        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        -        "items": {
        -          "format": "uuid",
        -          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Product IDs",
        -        "type": "array"
        -      },
        -      "targetBranches": {
        -        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        -        "items": {
        -          "minLength": 1,
        -          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        -          "type": "string"
        -        },
        -        "minItems": 1,
        -        "title": "Target Branches",
        -        "type": "array"
        -      },
        -      "type": {
        -        "const": "event",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "type"
        -    ],
        -    "type": "object"
        -  }
        -]New value: +[
        +  {
        +    "properties": {
        +      "expr": {
        +        "description": "Standard cron expression string.",
        +        "minLength": 1,
        +        "title": "Cron Expression",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "cron",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "expr"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "rrule": {
        +        "description": "iCalendar recurrence rule (RFC 5545) string.",
        +        "minLength": 1,
        +        "title": "RRule",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "rrule",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "rrule"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "at": {
        +        "description": "ISO 8601 timestamp for one-time execution.",
        +        "minLength": 1,
        +        "title": "At Time",
        +        "type": "string"
        +      },
        +      "type": {
        +        "const": "at",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "at"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "n": {
        +        "description": "Number of time units between executions.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Interval",
        +        "type": "integer"
        +      },
        +      "type": {
        +        "const": "every",
        +        "type": "string"
        +      },
        +      "unit": {
        +        "description": "Time unit for interval scheduling.",
        +        "enum": [
        +          "minutes",
        +          "hours"
        +        ],
        +        "title": "Time Unit",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type",
        +      "unit",
        +      "n"
        +    ],
        +    "type": "object"
        +  },
        +  {
        +    "properties": {
        +      "channelIds": {
        +        "description": "Optional channel scope: message channel UUIDs this automation is limited to. Omit for all channels (global). Only valid when every selected event supports channel scoping (see EVENT_CHANNEL_SCOPING).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Channel IDs",
        +        "type": "array"
        +      },
        +      "condition": {
        +        "description": "Optional free-form natural-language condition (\"only run when …\"), up to 2000 characters, evaluated against each trigger event's payload; the automation runs only for events that satisfy it. Omit to run on every matching event.",
        +        "maxLength": 2000,
        +        "minLength": 1,
        +        "title": "Trigger Condition",
        +        "type": "string"
        +      },
        +      "conditionMode": {
        +        "description": "Server-derived; ignored on input. judge = the condition is decided from the event payload before the run starts; agent = the agent decides it at the start of every run.",
        +        "enum": [
        +          "judge",
        +          "agent"
        +        ],
        +        "title": "Condition Mode",
        +        "type": "string"
        +      },
        +      "conditionSchemaVersion": {
        +        "description": "Server-derived; ignored on input. The version of the event field guide the condition was judged against; absent when it was not judged.",
        +        "exclusiveMinimum": 0,
        +        "maximum": 9007199254740991,
        +        "title": "Condition Schema Version",
        +        "type": "integer"
        +      },
        +      "delaySeconds": {
        +        "description": "Optional delay, in seconds, before running the automation after its trigger event fires (e.g. 1800 = 30 minutes after the event). Omit for immediate execution. Maximum 604800 (7 days).",
        +        "maximum": 604800,
        +        "minimum": 1,
        +        "title": "Delay (seconds)",
        +        "type": "integer"
        +      },
        +      "event": {
        +        "description": "Legacy single-event trigger (e.g., github.pr.created). Still accepted on read/write for backwards compatibility; prefer `events` for new writes. When both are present, `events` is canonical.",
        +        "minLength": 1,
        +        "title": "Event Name (legacy single-event form)",
        +        "type": "string"
        +      },
        +      "events": {
        +        "description": "Trigger events for this automation (e.g., [\"github.pr.created\", \"github.pr.dismissed\"]). The automation fires once per matching event occurrence. Canonical form — prefer this over the legacy `event` field.",
        +        "items": {
        +          "minLength": 1,
        +          "type": "string"
        +        },
        +        "maxItems": 20,
        +        "minItems": 1,
        +        "title": "Event Names",
        +        "type": "array"
        +      },
        +      "productIds": {
        +        "description": "Optional product scope: the products this automation is limited to. Omit for all products (global); an empty array is rejected so 'global' has one representation. Acts as a channel preset — at dispatch time the scoped products' currently linked message channels (product_channels) are resolved and the automation fires when the triggering event's channels intersect ANY of them. It additionally instructs the agent to scope the run's output to those products. May be combined with channelIds — both scopes must pass (AND semantics).",
        +        "items": {
        +          "format": "uuid",
        +          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Product IDs",
        +        "type": "array"
        +      },
        +      "targetBranches": {
        +        "description": "Optional case-sensitive allowlist of GitHub PR base_ref branches. Names match exactly; * matches zero or more characters, including slashes. Only valid for GitHub PR triggers. Omit for all target branches; channel and product scopes must also pass. Nonmatching events are skipped before launching a workflow or agent.",
        +        "items": {
        +          "minLength": 1,
        +          "pattern": "^[^\\s\\p{Cc}~^:?[\\]\\\\]+$",
        +          "type": "string"
        +        },
        +        "minItems": 1,
        +        "title": "Target Branches",
        +        "type": "array"
        +      },
        +      "type": {
        +        "const": "event",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "type"
        +    ],
        +    "type": "object"
        +  }
        +]
  3. 1 tool update
    • Changedupdate_people1 field changed
      • changedInput schema / properties / people / items / properties / primaryEmail / anyOf
        Previous value: -[
        -  {
        -    "format": "email",
        -    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "format": "email",
        +    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
  4. 3 tool updates
    • Addedcreate_automation
    • Addedlist_automations
    • Addedupdate_automation
  5. 1 tool update
    • Changedsend_feedback1 field changed
      • addedInput schema / properties / category
        Added value: +{
        +  "enum": [
        +    "agent_friction",
        +    "user_feedback"
        +  ],
        +  "type": "string"
        +}
  6. 2 tool updates
    • Addedcreate_feedback_channel
    • Addedsend_feedback
  7. 1 tool update
    • Changedupdate_topic2 fields changed
      • changedInput schema / properties / issueType / description
        Previous value: -"Update the topic issue type classification. Valid values: bug_report, feature_request, complaint, praise, or null to clear."New value: +"Not supported: the topic pipeline derives the issue type. Sending this field returns 400."
      • changedInput schema / properties / keywords / description
        Previous value: -"Replace the topic keywords/categories. Provide the full list of keywords."New value: +"Not supported: the topic pipeline derives the keywords. Sending this field returns 400."
  8. 1 tool update
    • Addedmodem_docs
  9. 1 tool update
    • Changedsearch_modem1 field changed
      • addedInput schema / properties / context
        Added value: +{
        +  "description": "What the user is trying to accomplish with this search. It does not change the results, so put every filter in question.",
        +  "maxLength": 1000,
        +  "type": "string"
        +}
  10. 1 tool update
    • Addedmodem_skills
  11. 14 tool updates
    • First observedadd_people_to_company
    • First observedbulk_update_topics
    • First observedcreate_companies
    • First observedmerge_companies
    • First observedmerge_people
    • First observedmerge_topics
    • First observedmodem_agent_cancel_run
    • First observedmodem_agent_get_run
    • First observedmodem_agent_invoke
    • First observedmodem_agent_send_message
    • First observedsearch_modem
    • First observedupdate_companies
    • First observedupdate_people
    • First observedupdate_topic

Related MCP Connectors

Related MCP Servers

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources