In this second part, we’ll be looking at the flows (Copilot Studio Tools), and add our instructions. Finally we’ll test our agent from a user perspective.
Agent Flows
Our first flow was to make sure the agent returned the correct number of trainings. By doing this, we have a predictable output rather than letting AI guess.
In the Number of Trainings Available flow, we have no inputs, and we filter rows where 127420000 is representative of the “Active” choice value in Dataverse.

And we get the number of active trainings using a simple Compose action:
length(outputs('List_rows_from_Trainings_Catalogue')?['body/value'])

Finally, we send the outputs of that Compose in the Respond to the agent action.
The other flow is Create Training Placeholder. This is the final step when a user wants to register for a training.
This flow has multiple inputs that will be used to find the user requesting the training, and also book the training in their calendar. We then pass the UserGUID input to find the matching user in the EntraID table.


We format the Start date:
formatDateTime(triggerBody()?['text_2'], 'yyyy-MM-ddTHH:mm:ss')
And the End date:
formatDateTime(triggerBody()?['text_3'], 'yyyy-MM-ddTHH:mm:ss')
Finally, we add a condition to check if the training is online or in-person! 😉

👉🏻 If you receive a placeholder instead of a Teams meeting (i.e.: Teams Meeting toggle is off, and you’ve got no link attached), make sure that the Outlook add-in is turned on in the Teams admin center under Settings and policies >> Meeting scheduling.
That concludes the flow; There’s nothing to pass on to the Respond to the agent action, and each input in the Copilot agent are set to Dynamically fill with AI + add a description.

Agent Instructions
Probably the part everyone is waiting for! 🙂
Instructions are extremely important. We’ll have a mix of very descriptive natural language, and call for the tools we’ve created.
As with all things with AI, it’s highly recommended to fine tune your instructions, or any sort of prompts to give the agent the best directions as possible in what we expect.
Below are my instructions. The first part is defining the role of the agent, the objectives with examples, and specifics when it comes to remaining seats.

Then the last part is about mandatory expected formatting (i.e.: “/systemusers(<GUID>)“), as well as the chain of events.
Observe that we’re also attempting to make the agent do some maths by adding 1 to the Attendees Confirmed field! If that doesn’t work consistently, then we should integrate in the process by amending our flow.

Results
Time has come to give it a go!
First test went well. The agent called our flow, and also return some useful information about how many tokens it used. This will be greatly appreciated when it comes to:
- Costing the interactions or overall
- Make the agent more performant

Then we’re going to be a lot more direct, and also use some of our entities (i.e.: pbi). And the results are very positive!

Next, let’s go straight to the point and see if it can register us for a training without giving the full training name. There’s a (sample) training called “SharePoint Survival Skills” active on the 31-Aug from 9am till 1pm, so let’s register for this one.
Below we can see the steps it went through (expandable for full details), and it found the training we wanted.

The Registration table has been updated and the placeholder was sent! 🥳


Conclusion
There are many other things to pay attention to when building an agent with the most important being about security & boundaries. But there’s also performance (to avoid “wasting” tokens), error handling in your flows (what if an action fails?), and user experience (formal or friendly tone?).
Make sure to extensively test your agent for better and faster outcomes!
Thanks for reading! 🙂