You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Bot Framework:用户10秒无活动时如何发送指定提醒消息?

Implementing 10-Second Inactivity Reminder in Azure Bot Framework

Got it, let's figure out how to make your Azure Bot send that inactivity reminder after 10 seconds of user silence. I'll walk you through the implementation with Bot Framework SDK v4, covering both C# and JavaScript since those are the most common stacks.

Core Approach

The idea is straightforward:

  • Track the user's last activity timestamp using ConversationState (so we persist this data across conversation turns)
  • Cancel any pending reminder tasks whenever the user sends a new activity
  • Start a new 10-second delay task after each user interaction; if no new activity comes in by then, send the reminder

C# Implementation

First, define a state class to hold our tracking data:

public class UserActivityState
{
    // Stores the last time the user interacted with the bot
    public DateTimeOffset LastActivityTime { get; set; }
    // Cancellation token to stop pending reminder tasks if user becomes active
    public CancellationTokenSource ReminderCts { get; set; }
}

Next, set up your bot to use ConversationState and handle turns:

using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using System;
using System.Threading;
using System.Threading.Tasks;

public class InactivityReminderBot : ActivityHandler
{
    private readonly ConversationState _conversationState;
    private readonly IStatePropertyAccessor<UserActivityState> _userActivityStateAccessor;

    // Inject ConversationState via constructor (dependency injection)
    public InactivityReminderBot(ConversationState conversationState)
    {
        _conversationState = conversationState;
        _userActivityStateAccessor = _conversationState.CreateProperty<UserActivityState>("UserActivityState");
    }

    public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
    {
        // Get or initialize the user's activity state
        var userActivityState = await _userActivityStateAccessor.GetAsync(
            turnContext, 
            () => new UserActivityState(), 
            cancellationToken
        );

        // Cancel any existing reminder task if the user is active again
        if (userActivityState.ReminderCts != null)
        {
            userActivityState.ReminderCts.Cancel();
            userActivityState.ReminderCts.Dispose();
        }

        // Update the last activity timestamp (use UTC to avoid timezone issues)
        userActivityState.LastActivityTime = turnContext.Activity.Timestamp ?? DateTimeOffset.UtcNow;

        // Handle user messages (replace this with your bot's actual conversation logic)
        if (turnContext.Activity.Type == ActivityTypes.Message)
        {
            await turnContext.SendActivityAsync($"You said: {turnContext.Activity.Text}", cancellationToken: cancellationToken);
        }

        // Start a new reminder task
        userActivityState.ReminderCts = new CancellationTokenSource();
        _ = SendReminderAfterInactivity(turnContext, userActivityState.ReminderCts.Token, cancellationToken);

        // Save the updated state to persist changes
        await _conversationState.SaveChangesAsync(turnContext, false, cancellationToken);
    }

    private async Task SendReminderAfterInactivity(ITurnContext turnContext, CancellationToken reminderToken, CancellationToken cancellationToken)
    {
        try
        {
            // Wait 10 seconds before sending the reminder
            await Task.Delay(TimeSpan.FromSeconds(10), reminderToken);

            // If the task wasn't canceled (user stayed inactive), send the reminder
            var reminderMessage = @"Looks like you aren't there for now. Bot
Ping me again once you are back. Bye for now.";
            await turnContext.SendActivityAsync(reminderMessage, cancellationToken: cancellationToken);
        }
        catch (TaskCanceledException)
        {
            // User became active again, so we just ignore this exception
        }
    }
}

JavaScript Implementation

First, set up your bot with ConversationState and tracking logic:

const { ActivityHandler, ConversationState, MemoryStorage } = require('botbuilder');

class InactivityReminderBot extends ActivityHandler {
    constructor(conversationState) {
        super();
        this.conversationState = conversationState;
        // Create an accessor to manage our activity state
        this.userActivityStateAccessor = this.conversationState.createProperty('UserActivityState');
    }

    async onTurn(context) {
        // Get or initialize the user's activity state
        let userActivityState = await this.userActivityStateAccessor.get(context, () => ({
            lastActivityTime: null,
            reminderTimeout: null
        }));

        // Clear any pending reminder timeout if the user sends a new activity
        if (userActivityState.reminderTimeout) {
            clearTimeout(userActivityState.reminderTimeout);
            userActivityState.reminderTimeout = null;
        }

        // Update the last activity timestamp
        userActivityState.lastActivityTime = context.activity.timestamp || new Date();

        // Handle user messages (replace with your bot's custom logic)
        if (context.activity.type === 'message') {
            await context.sendActivity(`You said: ${context.activity.text}`);
        }

        // Set a new 10-second timeout for the reminder
        userActivityState.reminderTimeout = setTimeout(async () => {
            const reminderMessage = `Looks like you aren't there for now. Bot
Ping me again once you are back. Bye for now.`;
            await context.sendActivity(reminderMessage);
            // Clear the timeout reference after sending the reminder
            userActivityState.reminderTimeout = null;
            await this.conversationState.saveChanges(context);
        }, 10000); // 10,000ms = 10 seconds

        // Save the updated state to persist changes
        await this.conversationState.saveChanges(context);
    }
}

// Initialize storage and state (use Azure Blob/Cosmos DB in production)
const memoryStorage = new MemoryStorage();
const conversationState = new ConversationState(memoryStorage);
const bot = new InactivityReminderBot(conversationState);

Key Notes

  • Production Storage: The examples use MemoryStorage which works for testing, but in production, use Azure Blob Storage or Azure Cosmos DB to persist state across bot restarts.
  • Activity Types: This code tracks all user activities (not just messages) — if you want to limit it to only messages, adjust the logic to update the timestamp only when ActivityTypes.Message is received.
  • Time Zones: Always use UTC timestamps to avoid issues with different time zones across users.
  • Task Cleanup: Make sure to cancel/dispose of pending tasks to prevent memory leaks and duplicate reminders.

内容的提问来源于stack exchange,提问作者Shwetanjali Dubey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 19:57:46