Scenes
Build multi-step conversation flows with shared state.
Creating a scene
Use the predefined answerHandler() helper to create a named scene that listens for follow-up user input.
const collectEmail = answerHandler('collect_email');
collectEmail.enter((ctx) => {
ctx.reply('Please enter your email address:');
});
collectEmail.on('message', async (ctx) => {
await db.setProp(ctx.from.id, 'email', ctx.message.text);
await ctx.reply('Email saved ✓');
ctx.scene.leave();
});
Entering & leaving
ctx.scene.enter('collect_email');
ctx.scene.leave();
Scene state
Pass data: ctx.scene.enter('scene', { id: 1 }). Read: ctx.scene.state.id.
Multi-step flows
The legacy docs used scenes primarily for collecting information step by step. That is still the cleanest pattern for guided input.
const userInfoScene = answerHandler('userInfoScene');
const ageScene = answerHandler('ageScene');
userInfoScene.on('text', async (ctx) => {
await db.operation.setProp(ctx.from.id, 'name', ctx.message.text);
await ctx.reply('Thanks. Now enter your age:');
await ctx.scene.enter('ageScene');
});
ageScene.on('text', async (ctx) => {
await db.operation.setProp(ctx.from.id, 'age', ctx.message.text);
await ctx.reply('All set. Your information has been saved.');
await ctx.scene.leave();
});
bot.command('userinfo', async (ctx) => {
await ctx.reply('Please enter your name:');
await ctx.scene.enter('userInfoScene');
});
How did this page feel?
Quick feedback helps improve the docs.
Last updated March 22, 2026