The gap this fills

You can take a photo of a whiteboarded call flow, hand it to AI tool, and get back Copilot Studio topic YAML that includes a working handoff to Dynamics 365 Contact Center. You still have to review it line by line, but it removes the most tedious part of the build.

Every contact center project I’ve worked on starts the same way: a Visio, a whiteboard photo, or a sticky-note wall showing how a customer moves from greeting to resolution or to a live representative. Then someone rebuilds that picture by hand in the Copilot Studio canvas.

Copilot Studio’s built-in Add from description with Copilot doesn’t help. Microsoft documents that it creates only Message, Question, and Condition nodes. It won’t build the Transfer conversation action, which is the one action a Contact Center flow can’t live without. It also takes text, not an image.

Why YAML is the right target

Every Copilot Studio topic is stored as YAML. Open any topic, select More (…) > Open code editor, and you see the full definition: trigger, variables, conditions. Paste valid YAML in, save, and the canvas redraws from it.

That makes YAML the natural output for an AI model. The model reads your diagram and writes text; Copilot Studio turns that text into nodes.

Be clear about Microsoft’s position, though:

  • The code editor docs warn that syntax errors can break the conversation.
  • The topic authoring docs state that designing a topic entirely in the code editor, or pasting complex topics, isn’t fully supported.
  • Microsoft’s own open-source Skills for Copilot Studio plugin is labeled an experimental research project and warns the YAML schema may change without notice.

In other words: this is a productivity technique, not a supported deployment path. Treat generated YAML as a first draft.

What you need

  • A Copilot Studio agent already connected to Dynamics 365 Contact Center (the Omnichannel / Contact Center channel configured and the agent added to a workstream). The YAML only builds the conversation; it doesn’t do the integration.
  • AI tool that accepts images (Claude, GitHub Copilot, Microsoft 365 Copilot, and others).
  • A non-production environment to test in.

Step 1: Prepare the image

The model can only generate what it can read. A clean diagram saves more time than any prompt trick.

  1. A full IVR map with branches produces sprawling YAML that’s hard to review. Split it into topics (Order Status, Billing, Escalate) and feed them one at a time.
  2. Write the actual condition on each branch line, such as “Order found” or “Customer says yes.” Unlabeled arrows force the model to guess.
  3. Write “TRANSFER TO REP” on the box, plus any message the representative should see.
  4. If you want any specific formatting, write it out. Otherwise the model invents names.
  5. Export from Visio or Lucid as PNG. Blurry photos produce wrong labels, and wrong labels produce wrong logic.

Step 2: Ground before you show it the picture

The biggest failure can be the model types that look possible but don’t exist. Microsoft doesn’t publish a complete public schema reference for topic YAML, so don’t rely on the model’s memory of it.

The most reliable grounding is your own tenant. Before generating anything, build a throwaway topic in the canvas with one of each node you need: a Message, a Question, a Condition, a Set variable, and a Transfer conversation. Open the code editor, copy the YAML, and paste it into your prompt as the reference. Now the model is copying the exact schema your environment emits today, not a version from its training data.

Then use a prompt like this:

You are generating a Microsoft Copilot Studio topic in YAML for the code editor.
The agent is connected to Dynamics 365 Contact Center.
Reference YAML from my environment (copy its structure exactly):
<paste your reference topic here>
Rules:
- Root is kind: AdaptiveDialog with a single beginDialog.
- Use ONLY node kinds that appear in the reference. If the diagram needs
something not in the reference, add a YAML comment saying so instead of
inventing a node.
- Every node id must be unique within the topic.
- Power Fx expressions start with "=".
- First assignment of a variable uses init:, e.g. init:Topic.OrderNumber.
- Every box marked TRANSFER becomes a TransferConversationV2 node with
transferType kind TransferToAgent.
- Use the variable names written in the diagram. Do not rename them.
- Output only the YAML, then a separate list of every assumption you made
where the diagram was unclear.
Now convert the attached diagram.

The assumptions list matters. It tells you exactly where to look first during review.

A real prompt, before and after

Here’s the diagram I’m working from: a fairly typical customer service IVR with a welcome message, a language menu, a five-option main menu, four-option submenus, “Issue resolved?” decisions, specialist transfers, and a queue with wait time and callback.

Image to YAML

And here’s the prompt I first used with it. It’s a reasonable first instinct, and it shows exactly where these requests go wrong.

Please take this diagram that is from an existing IVR contact center solution. When reviewing this, please leverage best practices and other information on how to deploy this to D365 Contact Center. As part of this, generate the YAML file that can be used to help with the import into Copilot Studio.

What’s wrong with it

  • Three jobs in one pass. “Review,” “apply best practices,” and “generate YAML” are separate tasks. Combined, the model spreads its effort thin and usually skimps on the YAML, which is the part you actually paste.
  • “Best practices” isn’t grounded. With no sources or reference YAML, the model fills that phrase from training data. You get confident, generic advice and node types that may not exist in your tenant’s schema.
  • “The YAML file” doesn’t exist. The code editor works one topic at a time. A full IVR map is many topics, so asking for one file produces a giant topic or a multi-topic blob you can’t paste anywhere.
  • It treats an IVR port as a 1:1 translation. “Press 1 for billing” menus don’t map cleanly to a conversational agent. Copying the DTMF tree faithfully gives you a menu-driven bot that fights generative orchestration.
  • Missing inputs. No Contact Center context variable names, no transfer targets or queues, and no request for an assumptions list.

The rewrite: two passes

Pass 1 is analysis only:

This diagram is an existing DTMF-based IVR. We're moving it to a voice-enabled
Copilot Studio agent in Dynamics 365 Contact Center.
1. List every distinct customer intent in the diagram. Each becomes one topic.
2. For each, list: questions asked, decisions, data lookups, and transfer points.
3. Flag menu layers that exist only because of DTMF and should become
natural-language intent recognition instead.
4. List anything unreadable or ambiguous in the image.
Do not generate YAML yet.

Pass 2 runs once per topic from the Pass 1 list:

Generate Copilot Studio topic YAML for the "<intent>" topic only.
Reference YAML from my environment (copy its structure exactly):
<paste>
Rules: only node kinds in the reference; unique ids; transfers use
TransferConversationV2 / TransferToAgent; use these Contact Center
context variable names exactly: <list>.
Output the YAML, then every assumption you made.

The split pays off in review. Pass 1 gives you a topic inventory to check against the original IVR before any YAML exists, so a misread diagram gets caught while it’s still cheap to fix.

Mapping IVR to Agent

Run Pass 1 on this diagram and the biggest finding is that roughly half of it shouldn’t be in topic YAML at all. Menus, “press 0” options, the queue, and callback all belong to Contact Center configuration or disappear entirely in a conversational design.

IVR elementContact Center approachBuilt in
Welcome messageGreeting in the Conversation Start topicCopilot Studio
Language selection (1 English, 2 Spanish, 3 other)Keep a language choice in the agent, set va_CustomerLocale, and route to language-specific queues on customer languageCopilot Studio + workstream routing
Main menu and four submenusOne topic per intent (Check Balance, Track an Order, Troubleshooting, and so on), about 16 in all. Keep DTMF as a fallback, not the primary pathCopilot Studio
“Press 0: Return to Main Menu”Drop it. Callers can switch topics at any point in a conversational agentNothing to build
“Issue resolved?” / “More questions?”Question node + Condition: yes ends with the confirmation message, no transfersCopilot Studio
Transfer to Billing, Orders, Tech Support, SalesTransferConversationV2, plus a global variable for department that route-to-queue rules readCopilot Studio + unified routing
Representative routing menu (press 1–4)Ask what the caller needs instead, then set the same department variableCopilot Studio
Callback (press 1)Direct callback, configured as a queue overflow actionContact Center admin
Skill-based connection to a live agentUnified routing with skills on the workstreamContact Center admin
Caller ID & CRM lookupCaller’s number is Activity.From.Name, available only in Conversation Start. Copy it to a global variable for lookupCopilot Studio
Time-based routingOperating hours on the workstream and queuesContact Center admin
Call analyticsContact Center historical analytics plus Copilot Studio analyticsBuilt in

That table is the real value of the exercise. It turns “generate the YAML for this IVR” into a short list of topics worth generating, and a separate admin backlog for everything else.

Step 3: What good output looks like

Here’s the kind of YAML you should expect from a simple “Order Status” diagram: ask if the customer has an order number, collect it if yes, transfer to a representative if no.

The transfer block mirrors the structure Microsoft publishes in its own Escalate topic sample.

kind: AdaptiveDialog
beginDialog:
kind: OnRecognizedIntent
id: main
intent:
displayName: Order Status
triggerQueries:
- Where is my order
- Check order status
- Track my package
actions:
- kind: Question
id: question_hasOrderNumber
interruptionPolicy:
allowInterruption: true
variable: init:Topic.HasOrderNumber
prompt: Do you have your order number handy?
entity: BooleanPrebuiltEntity
- kind: ConditionGroup
id: condition_hasOrderNumber
conditions:
- id: condition_yes
condition: =Topic.HasOrderNumber = true
actions:
- kind: Question
id: question_orderNumber
variable: init:Topic.OrderNumber
prompt: What's your order number?
entity: StringPrebuiltEntity
# TODO: order lookup (flow/tool) not in diagram - add manually
elseActions:
- kind: SendActivity
id: send_transferNotice
activity: No problem. I'll connect you with a representative who can find it.
- kind: TransferConversationV2
id: transfer_noOrderNumber
transferType:
kind: TransferToAgent
messageToAgent: Order status inquiry - customer has no order number.
context:
kind: AutomaticTransferContext

Three things to notice. The TODO comment is the model admitting the diagram didn’t specify the lookup, which is exactly the behavior the prompt asked for. messageToAgent is the private note the representative sees, not the customer. And AutomaticTransferContext sends the conversation context along with the transfer.

Practical advice: add your Contact Center context variable names to the prompt as a list. Tell the model to use those exact names for anything that should reach the representative.

Step 4: Paste, validate, test

Image to YAML
  1. Microsoft’s own guidance: if you’re new to YAML, copy the topic before editing it in the code editor.
  2. Create a blank topic, open the code editor, clear it, paste the YAML, and save. If it won’t save, the error usually names the line. Fix it there, not by regenerating everything.
  3. Close the code editor and walk the flow visually against the original diagram. Every branch, every label.
  4. confirm each one.
  5. Set variable properties (Global, External sources can set values) for anything going to Contact Center.
  6. Test the handoff end to end through the actual Contact Center chat widget or voice channel. The Copilot Studio test pane can’t show you what the representative receives. Confirm the conversation lands in the right queue and the context variables show up.
Image to YAML

Where this breaks

  • Support won’t troubleshoot code editor errors, and complex pasted topics aren’t fully supported.
  • Microsoft says the YAML schema can change without notice. Refresh your reference YAML regularly
  • Workstreams, queues, routing rules, and the Contact Center channel connection are configured in Contact Center admin center, not in topic YAML.

The bottom line

Image-to-YAML turns a whiteboard session into a reviewable first draft in minutes instead of an afternoon of clicking. It works best when you ground the model in YAML from your own environment, keep diagrams to one topic, and name your Contact Center variables up front. Treat the result like a first draft: fast, useful, and never tested without review.

Sources

Leave a Reply

I’m Pat

Welcome to Insights, where we will discuss all things Microsoft, including the latest features and updates in Microsoft 365 and Dynamics 365, integration strategies to streamline your workflows, comprehensive training programs designed to enhance user skills, and effective user enablement tactics essential for boosting adoption of technology in your organization. We aim to provide valuable insights and practical tips that will empower you to leverage these powerful tools to their fullest potential, driving productivity and innovation in today’s fast-paced digital landscape.

Let’s connect

Discover more from Pat Petersen

Subscribe now to keep reading and get access to the full archive.

Continue reading