BotRouter. This page documents every public attribute in the PolyBot.Attributes namespace.
Handler attributes
Handler attributes mark a method as a handler for a specific TelegramUpdateType. They are generated at build time by the source generator — you do not write these classes; the generator emits one per UpdateType into the PolyBot.Attributes namespace.
Generated handler attributes derive from
HandlerAttribute (the base class documented here). They carry an [UpdateHandlerDescriptorAttribute] annotation that records their UpdateType and the corresponding Update property name, which is how the generator maps methods to router switch cases.UpdateType enum from Telegram.Bot:
HandlerAttribute base
Target: Method · AllowMultiple: false
All generated handler attributes inherit from HandlerAttribute. The only property on the base is:
int
default:"0"
Controls the order in which handlers for the same
UpdateType are evaluated. Higher values run earlier. Handlers with equal priority run in source-file declaration order.UpdateHandlerDescriptorAttribute
Target: Class — stamped on each generated handler attribute class by the generator itself.
UpdateType
The
UpdateType this handler attribute corresponds to.string
The property name on
Telegram.Bot.Types.Update that holds the payload (e.g. "Message", "CallbackQuery").Routing attributes
[Command]
Target: Method · AllowMultiple: false
Restricts a handler to messages whose first entity is a bot command. Only meaningful on handlers whose payload is Message. The @botname suffix is automatically verified against PolyBotOptions.BotUsername.
Aliases can be declared positionally through the constructor — [Command("start", "begin")] is equivalent to [Command(Aliases = ["start", "begin"])]; both forms can also be combined.
string[]
default:"[]"
Command names without the leading
'/', matched case-insensitively. Example: Aliases = ["start", "begin"].char
default:"'/'"
Matching mode.
'/' matches via BotCommand message entities (the default Telegram command format). ' ' or '\0' matches via string.StartsWith (ordinal-ignore-case). Any other character requires that character at the start of the text followed by the alias.bool
default:"false"
When
true, throws CommandArgsParseException if the message contains any tokens after the command name. Extra tokens are silently ignored by default.string?
BotFather menu description for this command. Missing descriptions produce
CUR021 (warning) unless IsHidden = true. Descriptions longer than 256 characters are CUR022 (error).string?
BotFather localization code (
"en", "ru", etc.). null (default) registers the command for all languages.CommandScope
default:"CommandScope.Default"
The BotFather audience for this command. See
CommandScope below.When
true, the command is matched for routing but excluded from BotFather synchronization. Also suppresses the missing-description warning.CommandScope
Enum that maps to Telegram’s BotCommandScope variants used during BotFather command synchronization.
[Pattern]
Target: Method · AllowMultiple: false
Declares a route template over CallbackQuery.Data for a [CallbackQueryHandler] method. Segments are separated by Separator (default ':').
string
required
The segment template. Literal segments (
cart:checkout) match exactly. {name} captures one segment into the [Arg] parameter of the same name. {name:int} adds a type constraint. A trailing {*name} wildcard captures everything remaining (possibly empty).char
default:"':'"
The character that splits template segments.
[State<TEnum>]
Target: Method · AllowMultiple: true
Restricts the handler to updates whose stored TEnum state (keyed by the update’s identity) equals State. Multiple [State<TEnum>] attributes for the same (TEnum, StateKey) pair are OR-ed; attributes for different pairs are AND-ed.
TEnum
required
The state value that must be active for this handler to run.
StateKey
default:"StateKey.UserId"
Which identity of the incoming update is used to look up the state. See
StateKey in the Interfaces reference.[NoState<TEnum>]
Target: Method · AllowMultiple: true
Restricts the handler to updates where the identity was resolved but has no stored TEnum state. Useful for “entry” handlers that kick off a conversation flow. Updates whose key cannot be resolved do not match [NoState].
StateKey
default:"StateKey.UserId"
Which identity to check for the absence of state.
Parameter attributes
These attributes go on individual method parameters to control how the generator binds them.[Arg]
Target: Parameter · AllowMultiple: false
Binds a parameter to one positional whitespace-separated argument token from the command text, or to a named {placeholder} segment in a [Pattern] template. Only effective on [Command]-restricted or [Pattern]-restricted handlers; on other handlers it is CUR003 (warning) and the parameter is resolved from DI.
string?
Explicit argument name used in parse error messages. When
null (default), the C# parameter name is used.bool
default:"false"
When
true, a missing token yields default(T) instead of a parse error.T, Nullable<T>, or object. Other types produce CUR005 (warning) and fall back to DI.
[Rest]
Target: Parameter · AllowMultiple: false
Binds a string parameter to everything remaining in the message text after all positional [Arg] tokens have been consumed. There can be at most one [Rest] parameter per handler; the result is never null. Multiple [Rest] attributes produce CUR006 (warning); non-string type produces CUR007 (warning).
[Parse]
Target: Parameter · AllowMultiple: false
Binds a string parameter to the match of a regular expression scanned (not anchored) over the remaining text. With no capturing groups the whole match is bound; with groups, Groups[1].Value is used. [Parse] after [Rest] is CUR008 (warning); non-string type is CUR009 (warning).
string
required
The regular expression to scan against the remaining text.
[Key]
Target: Parameter · AllowMultiple: false
Resolves a handler or exception-handler parameter from the DI container as a keyed service using the specified key.
object
required
The key passed to
IKeyedServiceProvider.GetRequiredKeyedService<T>(key). Must be a constant string or integer so the generator can emit it inline.Rate limiting
[Throttled]
Target: Method · AllowMultiple: false
Applies a sliding-window rate limit to a handler. The generator inlines a ThrottleGate.TryEnter call at the top of the handler’s routing branch — before filter resolution or handler invocation — so non-matching updates never consume budget. Gates are static per handler and thread-safe.
int
default:"1"
Maximum number of allowed requests within the window.
int
default:"1000"
The sliding-window duration in milliseconds.
ThrottleScope
default:"ThrottleScope.User"
Which identity the rate-limit bucket is keyed by. See
ThrottleScope below.ThrottleAction
default:"ThrottleAction.Ignore"
What happens when the limit is exceeded. See
ThrottleAction below.ThrottleScope
ThrottleAction
Keyboard generation
[CallbackButton]
Target: Method, Property · AllowMultiple: true
Declares one button of a generated inline keyboard on a partial method or property returning InlineKeyboardMarkup. The generator emits the implementation. Each attribute list (one line of [CallbackButton(...), CallbackButton(...)]) forms one keyboard row; attributes within the list form the columns.
string
required
The button label displayed to the user.
string
required
The callback data string. May contain
{parameterName} placeholders referencing the declaring method’s parameters (not supported on properties, which have no parameters). Unknown placeholders produce CUR017 (warning).partial. Non-partial members produce CUR019 (warning). A non-InlineKeyboardMarkup return type produces CUR018 (error).
Exception handling
[ExceptionHandler]
Target: Method · AllowMultiple: false
Marks the bot’s single exception handler. The generated BotRouter.HandleErrorAsync calls this method for every update-processing failure instead of silently swallowing the error.
Parameter resolution follows the same rules as regular handlers, with these sources available in the error path: Exception, HandleErrorSource, ITelegramBotClient, CancellationToken, DI services, and keyed services ([Key]). There is no current update in the error path — update-bound parameters are CUR032 (error). The method must return Task or ValueTask (CUR034 otherwise). Declaring more than one [ExceptionHandler] is CUR033 (error); the first declaration wins.
A throw from inside the exception handler itself is swallowed so the polling loop survives.