Slot Best Practices
Six slot anti-patterns that break in production and how to fix them.
Slots look simple in the UI. Pick a name, write a description, choose a type. But the wrong choices here cascade through every action and conversation that touches the slot. These six patterns are the ones that break in production, not in testing.
Bloated Descriptions
Slot descriptions tell the reasoning engine what a slot represents. They’re semantic labels, not rule engines. When you stuff validation logic, formatting rules, or behavioral instructions into a description, none of it gets enforced.
What it looks like
Why it breaks
The reasoning engine reads slot descriptions to understand what a slot represents, not how to handle it. When you pack rules into descriptions:
- Rules aren’t enforced. The engine might ignore them or hallucinate compliance.
- Context bloat. Every character in the description consumes tokens in every reasoning call.
- Maintenance nightmare. Rules scattered across descriptions instead of centralized in policies.
Real consequence
User submits “yesterday” as due date. The engine sees the rule in the description but has no enforcement mechanism. Bad data hits your API, which returns a cryptic error like "Invalid date range". User sees a generic failure message. Support ticket filed.
The fix
Description says what the slot is and what format to expect. Validation policy enforces the rules. The engine shows the error_message to the user and re-collects the slot automatically.
Formatting hints like “Expected format: YYYY-MM-DD” are fine in descriptions — they help the engine collect the right shape of data. What doesn’t belong is behavioral logic: “if the user says X, do Y” or “reject and ask again.”
Rule of thumb: Descriptions should say what, not how. Format hints are fine. Behavioral rules are not. If your description has instructions for the engine rather than context about the data, move those rules to validation policies, decision policies, or resolver strategies. Know the trade-off between deterministic enforcement (policies, DSL) and non-deterministic prompting (descriptions) — use the platform’s built-in tools wherever the behavior should be consistent and reliable.
Wrong Slot Type for People
Using string to collect people is the single most common slot mistake. It forces the reasoning engine to parse structured data from free text, which is unreliable and skips the platform’s built-in identity resolution.
What it looks like
Why it breaks
You’re asking the engine to parse a comma-separated string into individual identities. This requires:
- An LLM call to parse the string into a list
- Another call to resolve each email to a user
- Error handling for malformed input (“john at company dot com”)
- No fuzzy matching (“John” won’t find “john.smith@company.com”)
Real consequence
User says “invite John and the marketing team”. Your string slot captures "John and the marketing team". The engine tries to parse this as emails. Fails. User tries "john@company.com, marketing-team@company.com". Engine parses it. But marketing-team is a distribution list, not a user. API call fails with "Invalid attendee".
The fix
The platform’s User resolver:
- Fuzzy matches “John” to “john.smith@company.com”
- Shows disambiguation UI if multiple matches
- Validates users exist before proceeding
- Handles display names, partial matches, and typos
Rule of thumb: If you’re collecting people, use User or list[User]. Always.
Missing Validation Policy
Free text slots without validation accept whatever the user provides. “Priority 99” passes through. “Start date: last Tuesday” passes through. Your API receives garbage, returns errors, and the user sees a generic failure.
What it looks like
Why it breaks
Without a validation policy, the engine accepts whatever the user provides. The “1-5” constraint lives in the description only — which means it’s a suggestion, not a rule.
Real consequence
HR system only accepts priority 1-5. User says “make it priority 10 — super urgent!” Engine passes priority: 10. API returns 400 Bad Request: priority must be between 1 and 5. User sees “Something went wrong. Please try again.”
The fix
When validation fails, the engine shows the error_message and re-collects the slot. The user gets a clear, specific prompt instead of a cryptic API error.
Common Validation Patterns
Validation policies use the same DSL functions available in output mappers. $PARSE_TIME, $TIME, $LENGTH, and comparison operators all work inside rule expressions.
Timezone Without Resolver
Users say “PST” or “Pacific Time”. APIs need “America/Los_Angeles”. Without a resolver mapping display values to IANA identifiers, the raw user input flows straight to your API and breaks.
What it looks like
Why it breaks
Users say “PST” or “Pacific Time”. Calendar APIs (MS Graph, Google Calendar) need IANA format: America/Los_Angeles. Without a resolver:
- User enters “PST”
- Slot stores “PST”
- API receives
timezone: "PST" - API fails or interprets incorrectly
Real consequence
Meeting scheduled for “9 AM PST”. MS Graph Calendar API receives timeZone: "PST". Graph doesn’t recognize “PST” — it needs IANA format. Meeting created with wrong timezone. Attendees in different timezones see the wrong time. Everyone shows up at different times.
The fix
User sees “Pacific Time (PT)” in the selection. Slot stores "America/Los_Angeles". API gets the right format. Meetings are correct. Note the description also specifies the expected format (IANA) — this helps the engine understand what shape the resolved value takes, even though the resolver handles the actual mapping.
Yes, static resolvers add an LLM call. For timezone mapping, it’s worth it — the alternative is broken meetings.
Static Resolver for Boolean
Static resolvers add an LLM call to resolve the user’s input to a value. For binary yes/no choices, this adds latency and cost with zero benefit over a native boolean slot.
What it looks like
Why it breaks
Static resolvers add an LLM call to resolve the user’s input to a matched value. For two options that map to yes/no, this is overhead:
- Extra latency (~200-500ms per resolution)
- Extra cost (LLM tokens)
- No benefit over simple
boolean
Real consequence
Every meeting request takes 500ms longer than necessary. Multiply by thousands of requests. Your plugin is “slow” compared to others. Users notice.
The fix
When to Use a Resolver vs Boolean
Every resolver adds an LLM call. A boolean slot is resolved without one. If you’re building a two-option choice (approve/reject, yes/no, enable/disable), always use boolean over a static resolver. See Decision Frameworks — Slot Type Selection for the full decision tree.
Conditional Slot Collection
You can’t conditionally collect one slot based on another slot’s value through slot configuration alone. Comments like “required if meeting_type is in-person” in a description are ignored — the engine either always collects the slot or never does.
There is one exception: context passing in resolver strategies. If a slot’s resolver needs another slot’s value to fetch its options (like fetching time-off types for a specific user, or subcategories based on a selected category), you can pass collected slot values into the resolver via strategy mapping. But context passing is for resolver inputs, not for controlling whether a slot gets collected at all.
What it looks like
Why it breaks
You can’t conditionally skip slot collection based on another slot’s value. Putting “required if” logic in a description doesn’t make the engine obey it. The reasoning engine will either:
- Always collect the slot (ignoring your “required if” comment)
- Never collect the slot
- Randomly decide based on context
Real consequence
User schedules a virtual meeting. Engine asks “What conference room?” User confused — “It’s virtual, I don’t need a room.” User types “none” or “N/A”. Your API receives room: "none". Room booking system tries to book a room named “none”. Fails or books the wrong room.
The fix
Use a decision policy in your conversation process to control flow based on collected slot values:
The conversation process collects is_virtual first (as a boolean slot — no resolver needed). Then the decision policy routes to the right activity based on the value. Users scheduling virtual meetings never see a room prompt.
Context passing vs decision policies: If your second slot’s resolver options depend on the first slot’s value (e.g. fetching subcategories based on a selected category), use context passing in your resolver strategy. If you need to skip collecting a slot entirely based on a condition, use a decision policy in the conversation process. They solve different problems.
Rule of thumb: If you see “required if” or “only when” in a slot description, you need a decision policy in your conversation process. If one slot’s resolver options depend on another slot’s value, use context passing.
Quick Reference
Six decision trees including slot type selection and resolver vs boolean.
Never chain action activities without a slot barrier. Slots are the breakpoints.
How the platform converts natural language into business objects.
Static and dynamic resolver configuration with output cardinality.