Skip to main content
Glama

Add a topic

cs_add_topic

Create a Copilot Studio topic YAML file from a declarative spec, preview the exact changes as a diff, then confirm to write it after approval.

Instructions

Create topics/.topic.mcs.yml from a declarative spec: trigger phrases (or a system trigger) plus message / question / condition / redirect / setVariable / searchKnowledge / http / invokeFlow / end / raw nodes. Validates the result. Push to apply. The first call changes nothing: it returns the files it would write, as a diff against what is there now, for the user to approve. Call it again with the same arguments plus confirm: true to write them.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYes
actionsYes
confirmNoRequired to write the change to the file. Without it the tool returns a preview - the changed lines against the current ones, and the character count - and writes nothing.
priorityNo
overwriteNo
workspaceNoPath to (or inside) the agent workspace. Defaults to CPS_WORKSPACE or the current directory.
descriptionNo
triggerKindNoSystem trigger instead of phrases
triggerPhrasesNoUser phrases that start the topic (OnRecognizedIntent)

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed4 schema fields changedv0.1.8
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / definitions
      Added value: +{
      +  "__schema0": {
      +    "oneOf": [
      +      {
      +        "properties": {
      +          "speak": {
      +            "anyOf": [
      +              {
      +                "type": "string"
      +              },
      +              {
      +                "items": {
      +                  "type": "string"
      +                },
      +                "type": "array"
      +              }
      +            ]
      +          },
      +          "text": {
      +            "anyOf": [
      +              {
      +                "type": "string"
      +              },
      +              {
      +                "items": {
      +                  "type": "string"
      +                },
      +                "type": "array"
      +              }
      +            ]
      +          },
      +          "type": {
      +            "const": "message",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "text"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "allowInterruption": {
      +            "type": "boolean"
      +          },
      +          "choices": {
      +            "description": "Multiple-choice options (closed list) instead of an entity",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "entity": {
      +            "enum": [
      +              "String",
      +              "Boolean",
      +              "Number",
      +              "Email",
      +              "Date",
      +              "DateTime",
      +              "PhoneNumber",
      +              "URL",
      +              "Money",
      +              "PersonName",
      +              "City",
      +              "CountryOrRegion",
      +              "Organization",
      +              "Percentage",
      +              "Age",
      +              "Duration",
      +              "Color",
      +              "Language",
      +              "ZipCode",
      +              "StreetAddress",
      +              "File"
      +            ],
      +            "type": "string"
      +          },
      +          "prompt": {
      +            "type": "string"
      +          },
      +          "type": {
      +            "const": "question",
      +            "type": "string"
      +          },
      +          "variable": {
      +            "description": "Topic.Name (prefix optional)",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "prompt",
      +          "variable"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "cases": {
      +            "items": {
      +              "properties": {
      +                "actions": {
      +                  "items": {
      +                    "$ref": "#/definitions/__schema0"
      +                  },
      +                  "type": "array"
      +                },
      +                "condition": {
      +                  "description": "Power Fx, e.g. Topic.Choice = \"Yes\"",
      +                  "type": "string"
      +                }
      +              },
      +              "required": [
      +                "condition",
      +                "actions"
      +              ],
      +              "type": "object"
      +            },
      +            "type": "array"
      +          },
      +          "else": {
      +            "items": {
      +              "$ref": "#/definitions/__schema0"
      +            },
      +            "type": "array"
      +          },
      +          "type": {
      +            "const": "condition",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "cases"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "replace": {
      +            "type": "boolean"
      +          },
      +          "topic": {
      +            "description": "Topic name or full reference",
      +            "type": "string"
      +          },
      +          "type": {
      +            "const": "redirect",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "topic"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "type": {
      +            "const": "setVariable",
      +            "type": "string"
      +          },
      +          "value": {
      +            "type": [
      +              "string",
      +              "number",
      +              "boolean"
      +            ]
      +          },
      +          "variable": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "variable",
      +          "value"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "autoSend": {
      +            "type": "boolean"
      +          },
      +          "endIfAnswered": {
      +            "type": "boolean"
      +          },
      +          "sources": {
      +            "description": "Restrict to these knowledge sources (file stems from knowledge/, or full references)",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "type": {
      +            "const": "searchKnowledge",
      +            "type": "string"
      +          },
      +          "variable": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "card": {
      +            "anyOf": [
      +              {
      +                "additionalProperties": {},
      +                "propertyNames": {
      +                  "type": "string"
      +                },
      +                "type": "object"
      +              },
      +              {
      +                "type": "string"
      +              }
      +            ],
      +            "description": "Adaptive Card JSON (object or string), version 1.5"
      +          },
      +          "outputTypes": {
      +            "additionalProperties": {
      +              "enum": [
      +                "String",
      +                "Number",
      +                "Boolean"
      +              ],
      +              "type": "string"
      +            },
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "outputs": {
      +            "additionalProperties": {
      +              "type": "string"
      +            },
      +            "description": "Input card: card field id -> Topic variable; omit for a display-only card",
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "type": {
      +            "const": "card",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "card"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "message": {
      +            "description": "Message to the human agent",
      +            "type": "string"
      +          },
      +          "phoneNumber": {
      +            "description": "Transfer to a phone number instead of an agent",
      +            "type": "string"
      +          },
      +          "type": {
      +            "const": "transfer",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "type": {
      +            "const": "endConversation",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "body": {},
      +          "headers": {
      +            "additionalProperties": {
      +              "type": "string"
      +            },
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "method": {
      +            "enum": [
      +              "Get",
      +              "Post",
      +              "Put",
      +              "Patch",
      +              "Delete"
      +            ],
      +            "type": "string"
      +          },
      +          "responseVariable": {
      +            "type": "string"
      +          },
      +          "type": {
      +            "const": "http",
      +            "type": "string"
      +          },
      +          "url": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "url",
      +          "responseVariable"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "flowId": {
      +            "type": "string"
      +          },
      +          "input": {
      +            "additionalProperties": {
      +              "type": "string"
      +            },
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "output": {
      +            "additionalProperties": {
      +              "type": "string"
      +            },
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "type": {
      +            "const": "invokeFlow",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "flowId"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "clearTopicQueue": {
      +            "type": "boolean"
      +          },
      +          "type": {
      +            "const": "end",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type"
      +        ],
      +        "type": "object"
      +      },
      +      {
      +        "properties": {
      +          "node": {
      +            "additionalProperties": {},
      +            "description": "A full DialogAction node; 'id' is added if missing",
      +            "propertyNames": {
      +              "type": "string"
      +            },
      +            "type": "object"
      +          },
      +          "type": {
      +            "const": "raw",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "type",
      +          "node"
      +        ],
      +        "type": "object"
      +      }
      +    ]
      +  }
      +}
    • addedInput schema / properties / actions / items / $ref
      Added value: +"#/definitions/__schema0"
    • removedInput schema / properties / actions / items / anyOf
      Removed value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "speak": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          }
      -        ]
      -      },
      -      "text": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "items": {
      -              "type": "string"
      -            },
      -            "type": "array"
      -          }
      -        ]
      -      },
      -      "type": {
      -        "const": "message",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "text"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "allowInterruption": {
      -        "type": "boolean"
      -      },
      -      "choices": {
      -        "description": "Multiple-choice options (closed list) instead of an entity",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "entity": {
      -        "enum": [
      -          "String",
      -          "Boolean",
      -          "Number",
      -          "Email",
      -          "Date",
      -          "DateTime",
      -          "PhoneNumber",
      -          "URL",
      -          "Money",
      -          "PersonName",
      -          "City",
      -          "CountryOrRegion",
      -          "Organization",
      -          "Percentage",
      -          "Age",
      -          "Duration",
      -          "Color",
      -          "Language",
      -          "ZipCode",
      -          "StreetAddress",
      -          "File"
      -        ],
      -        "type": "string"
      -      },
      -      "prompt": {
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "question",
      -        "type": "string"
      -      },
      -      "variable": {
      -        "description": "Topic.Name (prefix optional)",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "prompt",
      -      "variable"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "cases": {
      -        "items": {
      -          "additionalProperties": false,
      -          "properties": {
      -            "actions": {
      -              "items": {
      -                "$ref": "#/properties/actions/items"
      -              },
      -              "type": "array"
      -            },
      -            "condition": {
      -              "description": "Power Fx, e.g. Topic.Choice = \"Yes\"",
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "condition",
      -            "actions"
      -          ],
      -          "type": "object"
      -        },
      -        "type": "array"
      -      },
      -      "else": {
      -        "items": {
      -          "$ref": "#/properties/actions/items"
      -        },
      -        "type": "array"
      -      },
      -      "type": {
      -        "const": "condition",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "cases"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "replace": {
      -        "type": "boolean"
      -      },
      -      "topic": {
      -        "description": "Topic name or full reference",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "redirect",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "topic"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "type": {
      -        "const": "setVariable",
      -        "type": "string"
      -      },
      -      "value": {
      -        "type": [
      -          "string",
      -          "number",
      -          "boolean"
      -        ]
      -      },
      -      "variable": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "variable",
      -      "value"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "autoSend": {
      -        "type": "boolean"
      -      },
      -      "endIfAnswered": {
      -        "type": "boolean"
      -      },
      -      "sources": {
      -        "description": "Restrict to these knowledge sources (file stems from knowledge/, or full references)",
      -        "items": {
      -          "type": "string"
      -        },
      -        "type": "array"
      -      },
      -      "type": {
      -        "const": "searchKnowledge",
      -        "type": "string"
      -      },
      -      "variable": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "card": {
      -        "anyOf": [
      -          {
      -            "additionalProperties": {},
      -            "type": "object"
      -          },
      -          {
      -            "type": "string"
      -          }
      -        ],
      -        "description": "Adaptive Card JSON (object or string), version 1.5"
      -      },
      -      "outputTypes": {
      -        "additionalProperties": {
      -          "enum": [
      -            "String",
      -            "Number",
      -            "Boolean"
      -          ],
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "outputs": {
      -        "additionalProperties": {
      -          "type": "string"
      -        },
      -        "description": "Input card: card field id -> Topic variable; omit for a display-only card",
      -        "type": "object"
      -      },
      -      "type": {
      -        "const": "card",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "card"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "message": {
      -        "description": "Message to the human agent",
      -        "type": "string"
      -      },
      -      "phoneNumber": {
      -        "description": "Transfer to a phone number instead of an agent",
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "transfer",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "type": {
      -        "const": "endConversation",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "body": {},
      -      "headers": {
      -        "additionalProperties": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "method": {
      -        "enum": [
      -          "Get",
      -          "Post",
      -          "Put",
      -          "Patch",
      -          "Delete"
      -        ],
      -        "type": "string"
      -      },
      -      "responseVariable": {
      -        "type": "string"
      -      },
      -      "type": {
      -        "const": "http",
      -        "type": "string"
      -      },
      -      "url": {
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "url",
      -      "responseVariable"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "flowId": {
      -        "type": "string"
      -      },
      -      "input": {
      -        "additionalProperties": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "output": {
      -        "additionalProperties": {
      -          "type": "string"
      -        },
      -        "type": "object"
      -      },
      -      "type": {
      -        "const": "invokeFlow",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "flowId"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "clearTopicQueue": {
      -        "type": "boolean"
      -      },
      -      "type": {
      -        "const": "end",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "node": {
      -        "additionalProperties": {},
      -        "description": "A full DialogAction node; 'id' is added if missing",
      -        "type": "object"
      -      },
      -      "type": {
      -        "const": "raw",
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "type",
      -      "node"
      -    ],
      -    "type": "object"
      -  }
      -]
  2. Changed1 schema field changedv0.1.7
    • addedInput schema / properties / confirm
      Added value: +{
      +  "description": "Required to write the change to the file. Without it the tool returns a preview - the changed lines against the current ones, and the character count - and writes nothing.",
      +  "type": "boolean"
      +}
  3. First observedv0.1.5

TDQS

A4.1/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does so well: it discloses the two-phase preview/confirm behavior, that the first call writes nothing, that it returns a diff, and that it validates the result. It omits permission/auth requirements and the semantics of the overwrite flag, which holds it back from a 5.

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

Conciseness4/5

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

Front-loaded with what gets created, followed by the node taxonomy and the confirm workflow. Dense but efficient; the fragment 'Validates the result. Push to apply.' is slightly cryptic and could be tightened.

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 9-parameter tool with a large nested action schema and no output schema, the description covers the essential create/validate/preview/confirm loop and the node vocabulary. It leaves overwrite and priority semantics unaddressed, but nothing critical to invoking it correctly 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?

At 44% schema coverage the description must compensate, and it partially does by explaining trigger phrases vs. system trigger and enumerating the action node kinds (message/question/condition/redirect/etc.). However priority, overwrite, workspace, and description are unexplained in both places, so the gap is only partly closed — baseline 3.

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 (Create) and the exact resource it produces (topics/<name>.topic.mcs.yml), then enumerates the node kinds it accepts. This cleanly separates it from cs_edit_topic and other cs_add_* siblings without the agent needing to open 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 Guidelines4/5

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

Gives a strong operational flow: first call previews a diff, second call with confirm:true writes. What it lacks is explicit routing — it never names cs_edit_topic as the alternative for modifying an existing topic, so the agent must infer when-not-to-use from context.

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

Deploy Server

Other Tools