Lex via SDK Best Practices
Intent design and fallback-handling for production bots.
Search across all documentation pages
Intent design and fallback-handling for production bots.
This is the checklist to run before shipping a Lex V2 bot built through the SDK. Each item is a rule stated positively with a one-line rationale, grouped from intent/slot design outward through build/publish hygiene, code-hook reliability, session/cost management, and security. Work top to bottom - early groups keep the bot's conversations correct; later ones keep it fast, cheap, and safe.
AMAZON.FallbackIntent catch the rest. Don't try to enumerate every possible input as an intent - handle the fallback deliberately (clarify, escalate, or hand off) instead of ignoring it.AMAZON.Date, AMAZON.Number, AMAZON.City, and others already handle common data shapes with locale-aware parsing.TopResolution for slot values your code branches on. Normalizing synonyms to a canonical value avoids fragile string matching against raw user text later.Required slot. A vague prompt (or none) increases retries and abandonment; tell the user exactly what format you expect.BuildBotLocale only ever compiles DRAFT - changes are not testable or live until you rebuild.DRAFT, publishing a new version, and moving the alias - never assume an existing version can change under you.prod) and repoint the alias's botVersion to promote a new release.TSTALIASID for pre-publish testing. It always tracks the current DRAFT, so you can validate changes before cutting a version.sessionState, don't reconstruct it. Modify only what you mean to change in the response; wholesale rebuilding risks silently dropping slots or attributes.ElicitSlot without nulling the bad value can cause Lex to re-offer it instead of prompting cleanly.intent.state explicitly on every fulfillment path. Distinguish Fulfilled from Failed so your channel and any downstream logging can tell success from failure.lambda:InvokeFunction grant for principal lexv2.amazonaws.com scoped to the bot alias is the most common "code hook doesn't fire" cause.sessionId per conversation and reuse it for every turn. A new sessionId per call resets context and breaks multi-turn dialog.sessionAttributes you want kept. They aren't merged automatically if you send an explicit sessionState - omitted attributes are dropped for the next turn.idleSessionTTLInSeconds deliberately. Too short abandons legitimate slow-paced conversations; too long holds session state (and any PII in it) longer than needed.roleArn to least privilege. Grant only what the bot needs (conversation logging, invoking its specific fulfillment Lambdas), not broad service access.lexv2-models (managing bots) and lexv2-runtime (running conversations) are different permission sets - don't grant runtime callers management access they don't need.A missing resource-based Lambda permission - Lex needs explicit lambda:InvokeFunction access for principal lexv2.amazonaws.com scoped to the bot alias, separate from wiring the ARN into botAliasLocaleSettings.
Keep the hook well under the 30-second non-streaming ceiling, set tight timeouts on anything it calls, and always set intent.state explicitly so success and failure are distinguishable downstream.
Usually thin or narrow sample utterances, or genuinely out-of-scope requests. Add more varied phrasing to existing intents first, and treat a persistently high fallback rate as a signal to review intent coverage.
One sessionId per conversation, a deliberately chosen idleSessionTTLInSeconds, and explicit re-inclusion of sessionAttributes whenever you send a sessionState yourself.
Be careful - they can contain PII. Log intent names, slot names, and confidence scores by default; enable full conversation logging only deliberately, with retention and access controls in mind.
Change DRAFT, rebuild the locale, test against TSTALIASID, then publish a new version and move your prod alias to point at it - never edit a published version in place.
Cramming multiple distinct user goals into one intent with internal branching. Split them into separate intents with their own sample utterances - it keeps NLU matching accurate and fulfillment logic simple.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 25, 2026