Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Learn how to configure inactivity triggers, with guidance on setup, channel support, limitations, and troubleshooting.
Overview
The inactivity trigger, also called OnInactivity, or The user is inactive for awhile, is a system trigger in Copilot Studio that automatically fires a topic when a user doesn't send any message for a specified duration. It runs server-side, so the agent evaluates the timer and executes the topic even if the user's client is idle.
Common use cases include:
- Send a reminder asking if the user is still there
- Free up agent capacity by automatically closing idle conversations
- Collect feedback (for example, a customer satisfaction survey) before a session ends
- Clean up session state for abandoned conversations
How the inactivity trigger works
This section explains how Copilot Studio evaluates inactivity triggers, schedules timers, and runs topics when a conversation is idle.
Architecture overview
The user sends a message.
The runtime evaluates all OnInactivity triggers.
The runtime groups triggers by duration and selects one per duration tier. The lowest priority number wins; earliest creation date breaks ties.
The runtime orders the selected triggers by duration, shortest first.
The runtime arms a timer for the next trigger in Azure Service Bus. Only one timer is active at a time.
The user is inactive for the configured duration.
The timer fires, and the inactivity event is sent to the runtime.
The runtime matches and executes the inactivity topic.
The runtime calculates the remaining time to the next trigger and arms a new timer.
Key behaviors
Timer resets on every user message.
Each time a user sends a message, the system reevaluates all inactivity triggers and arms the next one (shortest duration first). Only one timer is active at any time.
Multiple triggers are supported.
You can have multiple OnInactivity triggers at different durations (for example, 5 minutes and 10 minutes). The system processes them in ascending order of duration. Only one trigger is selected per duration tier. If two triggers have the same duration, the trigger with the lower
Prioritynumber fires. If there's still a tie, the earlier-created trigger wins. The system discards other triggers at the same duration.Triggers are queued, not parallel.
Only one timer is active at a time. After the current trigger executes, the runtime calculates the remaining time to the next trigger and arms a new timer for the difference. The net effect is that triggers fire at the correct offsets from the original inactivity point, though minor drift might occur if trigger execution takes significant time.
Background execution.
The inactivity event is a background trigger. It doesn't require user interaction to fire.
Transcript recording.
The system records inactivity events in conversation transcripts. A new transcript record is created after 30 minutes of inactivity.
Example timeline (multiple triggers)
| Time | Event |
|---|---|
| 0:00 | User sends last message |
| 5:00 | Trigger A (300 s) fires, sends warning |
| 10:00 | Trigger B (600 s) fires, ends conversation |
If the user sends a message at 4:30, both timers reset. Trigger A fires at 9:30, and Trigger B fires at 14:30.
Configure the inactivity trigger
This section shows how Copilot Studio starts, resets, and runs inactivity timers so you can predict what happens when a conversation goes idle.
Create an inactivity trigger topic
In Copilot Studio, go to Topics > Add a topic > From blank.
Select the trigger phrase. Instead of a phrase, select "After a period of inactivity".
Set the Inactivity duration property. In Manual input mode, choose a preset from the dropdown (15 minutes, 30 minutes, 45 minutes, or 1 hour). To enter a custom value in seconds or a Power Fx formula (for example,
Global.TimeoutSeconds), switch the mode selector to Formula and type the value directly.Design the topic flow (send a message, ask a question, end the conversation, and so on).
Save and publish your agent.
Duration reference
| Desired timeout | Value (seconds) |
|---|---|
| 30 seconds | 30 |
| 2 minutes | 120 |
| 5 minutes | 300 |
| 10 minutes | 600 |
| 1 hour | 3600 |
Important
The property uses seconds, not minutes, or milliseconds. A value of 60000 means about 16.7 hours, not 60 seconds.
Example: Single warning trigger
[OnInactivity - 600 seconds]
Message: "Are you still there? Reply to continue."
End Topic
Example: 5-minute warning and 10-minute autoclose
This pattern is the most common. Create two inactivity topics:
Topic 1: Inactivity warning (5 minutes)
- Trigger: After a period of inactivity
durationInSeconds:300- Actions: Send a message: "Are you still there? This conversation closes in 5 minutes if there's no response."
Topic 2: Autoclose (10 minutes)
- Trigger: After a period of inactivity
durationInSeconds:600- Actions:
- Set
Global.DeactivateInactivity = true(guard variable - see Best Practices) - Send a message: "This conversation closes due to inactivity."
- End conversation
- Set
Example: Feedback collection
- Trigger: After a period of inactivity
- durationInSeconds:
120 - Actions:
- Ask: "Before you go, would you rate your experience? (1-5)"
- Store the response
- End conversation
Add a condition to the trigger
Add a Condition node right after the trigger so it only runs in certain situations:
- Only fire on a specific channel:
=Activity.ChannelId = "msteams" - Only fire if a guard variable isn't set:
=Global.DeactivateInactivity = false
Recommended pattern for multiple triggers (shared topic)
If you have multiple triggers with Question nodes, use a shared topic to avoid dialog stacking problems:
Create a shared topic called
HandleInactivity:- Add a global variable
Global.InactivityStage(Text) - Check its value:
"warning"→ Send a warning message with a Question node ("Continue?" / "End?")"close"→ Send a closing message and end conversation
- Add a global variable
First OnInactivity trigger (300 seconds):
- Set
Global.InactivityStage = "warning" - Redirect to
HandleInactivity
- Set
Second OnInactivity trigger (600 seconds):
- Set
Global.InactivityStage = "close" - Redirect to
HandleInactivity
- Set
This approach prevents Question nodes from stacking and creating prompt loops.
Channel-specific configuration
Channel support matrix
| Channel | Support level | Notes |
|---|---|---|
| Demo website | Fully supported | Best channel for testing inactivity triggers. |
| Custom website (Direct Line) | Fully supported | Works the same as the demo website. |
| Microsoft Teams | Supported | Works, but see Teams-specific guidance in the next section. Auth tokens might expire during long inactivity periods. |
| Dynamics 365 Customer Service | Fully supported | Requires extra steps to close Dynamics 365 Customer Service conversations. Learn more in Dynamics 365 Customer Service configuration. |
| Microsoft 365 Copilot | Trigger fires, but messages aren't delivered | This scenario is a known limitation. The trigger executes server-side, but the Microsoft 365 Copilot UI doesn't display proactive messages from agents. No workaround. |
| Test panel | Not supported | This scenario is by design. Timers are disabled for the Studio channel ID. Use the demo website or a published channel to test. |
| DirectEngine | Not supported | This scenario is by design. Timers are disabled for the DirectEngine channel ID (design/test environment). |
| Telephony/IVR | Not supported | For voice channels, use the OnSilence trigger instead. |
Teams configuration
Teams uses a persistent, single-conversation model. The conversation never truly "ends" from Teams' perspective. This model means inactivity triggers keep refiring even after the user considers the conversation done.
Recommended Teams pattern:
Create a global variable
Global.IsConversationClosed(Boolean, default:false).At the start of your inactivity topic, check:
If Global.IsConversationClosed = true→ End Topic (exit immediately).When the conversation logically ends (user says "goodbye," customer satisfaction completes, and so on), set
Global.IsConversationClosed = true.The inactivity trigger might still fire, but it exits immediately without showing a message.
Dynamics 365 Customer Service configuration
- Conversations autoclose after 30 minutes of inactivity by default.
- Calling EndConversation alone doesn't_ close the Dynamics 365 Customer Service session. Agent capacity isn't freed.
- To fully close the conversation, set the
CloseOmnichannelConversationcontext variable totruevia a Power Automate flow, then use a Transfer to Agent node.
Known limitations
Quick reference: What can disrupt the inactivity timer?
| Feature or Action | Effect on inactivity timers |
|---|---|
| End conversation | Permanently clears all timers |
| User sends a message | Resets all timers to zero (by design) |
| Trigger condition with uninitialized variable | Timer is silently excluded - never arms |
| Duration exceeds 7 days (604,800 seconds) | Timer is silently ignored |
| Clearing global variables in an inactivity topic | agent loses conversation context |
| Transfer to customer service representative | Timer stays active and might fire during the customer service representative conversation |
Test panel doesn't support inactivity triggers
The Copilot Studio test panel doesn't fire inactivity triggers. This limitation is by design. Publish your agent and test on a live channel (demo website, Teams, and so on).
Microsoft 365 Copilot doesn't display inactivity messages
The trigger executes server-side, but any output (messages, cards) isn't delivered to the user in the Microsoft 365 Copilot experience. There's no workaround. See Teams known limitations.
Generative AI orchestration
Inactivity triggers are implemented as classic orchestration topic triggers and use a separate timer-based event pipeline. When Generative AI orchestration is turned on, topic routing no longer relies on classic trigger recognition, so inactivity topics might not reliably fire in all configurations. If inactivity handling is required, classic orchestration is the recommended and fully validated configuration.
Connected agents: child agent inactivity isn't supported
In connected agent configurations, inactivity triggers in child agents don't work and return "Invalid Connected Agent Response." Put all inactivity logic in the parent agent.
Maximum duration: 7 days (604,800 seconds)
Published bots silently ignore triggers with durations longer than 604,800 seconds. No error appears. In design mode, an error might appear. There's no enforced minimum - short durations (under about 15 seconds) might behave unpredictably due to timer infrastructure latency.
End conversation clears inactivity timers
When you call End conversation in a topic, it permanently stops all active inactivity timers for that conversation. The timers are cleared entirely; they're not reset or paused. The operation discards any pending inactivity events that are already scheduled.
If you want to end a topic's flow without disrupting inactivity timers, use one of the alternative actions:
| Action (in Copilot Studio) | Effect on inactivity timers |
|---|---|
| End conversation | Clears all timers; timers stop permanently |
| End current topic (EndDialog) | Doesn't affect timers; timers continue running |
| Cancel all topics (CancelAllDialogs) | Doesn't affect timers; timers continue running |
Tip
If your topic needs to close the current flow but you still want the inactivity timer to fire later (for example, a JIRA search topic that finishes but the conversation should still time out), use End current topic instead of End conversation.
Using a guard variable to prevent refiring remains a recommended defensive practice.
Trigger fires after agent escalation
After the system transfers a conversation to a customer service representative, the inactivity trigger stays active. It might fire during the human agent conversation and send agent messages unexpectedly. Always call EndConversation before transfer, or use a guard variable.
Trigger messages might appear in transcripts after conversation ends
Even after a conversation closes, the trigger might still fire and its messages are recorded in the transcript. This condition doesn't affect the user experience but might appear in analytics.
Phone, voice, and IVR channels
The inactivity trigger isn't available for phone and voice channels. Use the OnSilence trigger instead.
Common misconfigurations
Use this section to identify and fix common configuration issues that can prevent inactivity triggers from working as expected.
End conversation in the inactivity topic (loop risk)
Problem: When you call End conversation from an inactivity topic, you clear all inactivity timers. However, on channels with persistent conversations (especially Teams), the underlying conversation stays active. In some configurations, the trigger can still refire, causing repeated "session ended" messages.
Solution (recommended as defensive practice): Use a guard variable:
Create
Global.DeactivateInactivity(Boolean, default:false).At the top of every inactivity topic, add a condition: only proceed if
Global.DeactivateInactivity = false.Set
Global.DeactivateInactivity = truebefore calling EndConversation.
Note
The guard variable pattern is especially important for Teams channels, where the persistent conversation model means the conversation never truly ends.
Duration set to the wrong value
Problem: durationInSeconds is in seconds. A value of 60000 is about 16.7 hours, not 60 seconds.
Solution: Double-check your values against the reference table in Section 3.
Question nodes in multiple inactivity topics (prompt stacking)
Problem: If multiple triggers each have a Question node, the second trigger's Question node interrupts the first. When the user answers, the first Question node resumes and reprompts, creating a loop.
Solution: Use the shared topic pattern. Consolidate Question node logic into a single topic, or ensure only one trigger has a Question node.
Clearing global variables in the inactivity topic
Problem: If the inactivity topic clears global variables, the agent loses all conversation context and appears unresponsive when the user returns.
Solution: Only reset inactivity-specific variables, not the entire conversation state.
Not gating inactivity triggers in Teams
Problem: In Teams, the persistent conversation model means triggers fire indefinitely. Users receive repeated "are you still there?" messages hours or days later.
Solution: Always use the gating variable pattern for Teams.
Not calling closeOmnichannelConversation
Problem: For Dynamics 365 Customer Service agents, calling EndConversation alone doesn't close the Dynamics 365 Customer Service session. Conversations pile up in the agent queue.
Solution: Set CloseOmnichannelConversation to true via Power Automate in your inactivity topic.
Dynamic duration from an uninitialized variable
Problem: Using a Power Fx expression like =Environment.InactivityTimeout for the duration works, but if the variable is uninitialized or null, the trigger is silently excluded.
Solution: Ensure all variables used in trigger conditions and duration expressions have valid default values.
Expecting triggers to work after agent escalation
Problem: After the system transfers to a customer service representative, the trigger fires on the original agent conversation and sends messages during the human agent session.
Solution: Either end the agent conversation at escalation time, or use a guard variable Global.IsEscalated = true and check it at the start of the inactivity topic.
Troubleshoot when the inactivity trigger isn't working
Use this decision tree to diagnose the problem:
Where are you testing?
- If you're using the test panel, stop. The test panel doesn't support inactivity triggers. Publish and test on a live channel.
What channel are you using?
- Microsoft 365 Copilot? This channel has a known limitation. Trigger fires but messages aren't delivered. No workaround.
- Telephony/IVR? This channel isn't supported. Use the OnSilence trigger instead.
Is Generative AI orchestration enabled?
- Inactivity triggers use a separate timer pipeline from recognition-based routing. However, their behavior with generative AI orchestration isn't fully validated. If inactivity handling is critical, classic orchestration is the recommended configuration.
Is your
durationInSecondsgreater than 604,800?- If yes, the trigger is silently ignored. Reduce to 604,800 or lower.
Is the agent a child agent in a Connected Agent setup?
- If yes, child agent inactivity triggers aren't supported. Move the logic to the parent agent.
Do you have multiple inactivity triggers?
- They fire in order of duration (shortest first). Make sure you're waiting long enough. Any user message resets all timers.
Does the trigger have a condition referencing an uninitialized variable?
- If a condition references a variable not yet set, the trigger is silently excluded. Ensure all condition variables have default values.
Was the agent republished after the conversation started?
- A republish might reset the inactivity timer for active sessions. Start a new conversation and test again.
If the inactivity trigger still isn't working, try the following options:
- Check conversation transcripts for any inactivity topic activity. If the topic appears but the user didn't see the message, the issue is channel-specific delivery.
- Verify the topic isn't disabled or archived.
- Confirm the trigger type is "After a period of inactivity," not a phrase trigger.
Best practices
Always test on a published channel. Use the demo website for quick testing. Never rely on the test pane.
Use a guard variable to prevent loops. Create
Global.DeactivateInactivity(Boolean, defaultfalse). Set it totruebefore calling EndConversation. Check it at the start of every inactivity topic.Keep durations reasonable. Minimum ~15 seconds, maximum 604,800 seconds (7 days).
Verify your units. The property is in seconds. 5 minutes =
300, not5.For Dynamics 365 Customer Service: Always pair
EndConversationwithcloseOmnichannelConversationvia Power Automate.For multi-trigger scenarios: Limit Question nodes to one trigger, or use the shared topic pattern.
Call
EndConversationbefore transferring to a customer service representative to deactivate inactivity triggers.Monitor conversation transcripts after deployment to verify messages appear at expected times.
FAQ
Why doesn't the inactivity trigger work in the test panel?
Timers are disabled in the test panel by design. Publish your agent and test on a live channel.
Can I use dynamic durations (for example, from a variable)?
Yes. The duration field accepts Power Fx expressions. You can use an environment variable or calculated value. The expression is evaluated at runtime when the timer is armed. Ensure the variable is initialized and contains a valid number.
What happens if I publish a new agent version while conversations are active?
The runtime picks up the new version. If the trigger ID changed (topic deleted and recreated), the system falls back to matching by duration. If no trigger matches by ID or duration, the pending inactivity event is dropped.
How do I completely stop inactivity triggers in Teams?
You can't stop them at the platform level. Use the gating variable pattern: set a boolean when the conversation logically ends, and check it at the start of the inactivity topic to exit early.
Does the inactivity trigger work with authentication?
Yes, but for long session timeouts (for example, 24 hours), the user's auth token might expire before the trigger fires. Ensure your agent handles reauthentication gracefully.
What happens if my inactivity topic calls a connector that takes a long time?
Connector calls have a timeout limit (30 seconds default, 60 seconds max). Optimize the connector or handle the timeout gracefully.
Related content
- Set topic triggers
- System variables — InactivityTimer.Continue, InactivityTimer.Count
- Use Power Fx in Copilot Studio
- Configure Dynamics 365 Customer Service handoff
- Voice configuration and silence detection
- Deploy agents to Teams
- Connected agents
- Conversation transcripts in Copilot Studio
- Automatically close Omnichannel conversations
- Known limitations in Microsoft 365 Copilot