Skip to content
Learn Agentic AI
Learn Agentic AI10 min read8 views

Slot Filling in Conversational AI: Collecting Required Information Through Natural Dialog

Learn how to implement slot filling patterns in conversational AI agents that collect required information through natural, multi-turn dialog instead of rigid form-like interactions.

What Is Slot Filling?

Slot filling is a dialog management pattern where an AI agent identifies pieces of information (slots) it needs to complete a task and collects them through natural conversation. Rather than presenting users with a rigid form, the agent extracts values from free-form utterances and asks follow-up questions only for missing pieces.

Consider a restaurant booking agent. It needs a date, time, party size, and optionally a seating preference. A user might say "Book a table for four this Friday" — providing party size and date in a single utterance. The agent should extract both and only ask about the missing time slot.

Defining Slots with Validation

Start by modeling each slot with its constraints, extraction logic, and confirmation behavior.

Hear it before you finish reading

Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.

Try Live Demo →
flowchart LR
    INPUT(["User intent"])
    PARSE["Parse plus<br/>classify"]
    PLAN["Plan and tool<br/>selection"]
    AGENT["Agent loop<br/>LLM plus tools"]
    GUARD{"Guardrails<br/>and policy"}
    EXEC["Execute and<br/>verify result"]
    OBS[("Trace and metrics")]
    OUT(["Outcome plus<br/>next action"])
    INPUT --> PARSE --> PLAN --> AGENT --> GUARD
    GUARD -->|Pass| EXEC --> OUT
    GUARD -->|Fail| AGENT
    AGENT --> OBS
    style AGENT fill:#4f46e5,stroke:#4338ca,color:#fff
    style GUARD fill:#f59e0b,stroke:#d97706,color:#1f2937
    style OBS fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
    style OUT fill:#059669,stroke:#047857,color:#fff
from dataclasses import dataclass, field
from typing import Any, Callable, Optional
import re
from datetime import datetime, timedelta

@dataclass
class Slot:
    name: str
    prompt: str
    required: bool = True
    value: Any = None
    confirmed: bool = False
    validator: Optional[Callable] = None
    extractor: Optional[Callable] = None

    def is_filled(self) -> bool:
        return self.value is not None

    def validate(self) -> bool:
        if self.validator and self.value is not None:
            return self.validator(self.value)
        return True

def extract_party_size(text: str) -> Optional[int]:
    patterns = [
        r"for (d+)",
        r"(d+) people",
        r"(d+) guests",
        r"party of (d+)",
    ]
    for pattern in patterns:
        match = re.search(pattern, text, re.IGNORECASE)
        if match:
            return int(match.group(1))
    return None

def extract_date(text: str) -> Optional[str]:
    today = datetime.now()
    text_lower = text.lower()
    if "today" in text_lower:
        return today.strftime("%Y-%m-%d")
    if "tomorrow" in text_lower:
        return (today + timedelta(days=1)).strftime("%Y-%m-%d")
    days = ["monday","tuesday","wednesday","thursday","friday","saturday","sunday"]
    for i, day in enumerate(days):
        if day in text_lower:
            current_day = today.weekday()
            diff = (i - current_day) % 7
            if diff == 0:
                diff = 7
            target = today + timedelta(days=diff)
            return target.strftime("%Y-%m-%d")
    return None

Each slot carries its own extraction function so the agent can pull values from any user utterance, not just direct answers to prompts.

The Slot Filling Engine

The engine iterates over unfilled slots, attempts extraction from each user message, and only prompts for slots that remain empty.

class SlotFillingEngine:
    def __init__(self, slots: list[Slot]):
        self.slots = {s.name: s for s in slots}
        self.conversation_history: list[dict] = []

    def extract_all(self, user_message: str):
        """Try to fill every empty slot from the user message."""
        for slot in self.slots.values():
            if not slot.is_filled() and slot.extractor:
                value = slot.extractor(user_message)
                if value is not None:
                    slot.value = value

    def get_next_unfilled(self) -> Optional[Slot]:
        for slot in self.slots.values():
            if slot.required and not slot.is_filled():
                return slot
        return None

    def all_required_filled(self) -> bool:
        return all(
            s.is_filled() for s in self.slots.values() if s.required
        )

    def process_message(self, user_message: str) -> str:
        self.conversation_history.append(
            {"role": "user", "content": user_message}
        )
        self.extract_all(user_message)

        # Validate filled slots
        for slot in self.slots.values():
            if slot.is_filled() and not slot.validate():
                name = slot.name
                slot.value = None
                response = f"The {name} you provided is not valid. {slot.prompt}"
                self.conversation_history.append(
                    {"role": "assistant", "content": response}
                )
                return response

        if self.all_required_filled():
            return self._build_confirmation()

        next_slot = self.get_next_unfilled()
        if next_slot:
            self.conversation_history.append(
                {"role": "assistant", "content": next_slot.prompt}
            )
            return next_slot.prompt

        return self._build_confirmation()

    def _build_confirmation(self) -> str:
        filled = {
            name: slot.value
            for name, slot in self.slots.items()
            if slot.is_filled()
        }
        details = ", ".join(f"{k}: {v}" for k, v in filled.items())
        return f"I have everything. Confirming: {details}. Shall I proceed?"

Multi-Turn Collection in Action

engine = SlotFillingEngine([
    Slot("date", "What date would you like?", extractor=extract_date),
    Slot("party_size", "How many guests?", extractor=extract_party_size),
    Slot("time", "What time works for you?", extractor=lambda t:
        re.search(r"(d{1,2}(?::d{2})?s*(?:am|pm))", t, re.I)
        and re.search(r"(d{1,2}(?::d{2})?s*(?:am|pm))", t, re.I).group(1)
    ),
])

print(engine.process_message("Table for 4 this Friday"))
# Extracts date=Friday, party_size=4, asks for time

print(engine.process_message("7pm"))
# Extracts time=7pm, confirms all slots

The key insight is that extraction runs against every unfilled slot on every message, so users can volunteer information in any order and the agent adapts.

FAQ

How does slot filling differ from form filling?

Form filling presents fields in a fixed order and expects one answer per turn. Slot filling extracts multiple values from free-form text, handles any ordering, and only asks about genuinely missing information. This makes conversations feel natural rather than scripted.

Still reading? Stop comparing — try CallSphere live.

CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.

What happens when the user changes a previously filled slot?

The engine should detect override intent — phrases like "actually make it 6 people" — and update the corresponding slot value. Add an override extraction pass that checks already-filled slots for new values when the user expresses correction intent.

How do you handle ambiguous slot values?

When an extractor returns multiple possible values, present them as disambiguation options rather than guessing. For example, if "next week" could mean any day, ask "Which day next week?" to narrow down the value before filling the slot.


#SlotFilling #ConversationalAI #DialogManagement #NLU #Python #AgenticAI #LearnAI #AIEngineering

Share

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.

Related Articles You May Like

Agentic AI

Building Your First Agent with the OpenAI Agents SDK in 2026: A Hands-On Walkthrough

Step-by-step build of a working agent with the OpenAI Agents SDK — Agent class, tools, handoffs, tracing — plus an eval pipeline that catches regressions before merge.

Agentic AI

Voice Agent Quality Metrics in 2026: WER, Latency, Grounding, and the Ones Most Teams Miss

The full metric set for evaluating production voice agents — STT word error rate, end-to-end latency budgets, RAG grounding, prosody, and the metrics that actually correlate with retention.

Agentic AI

Building OpenAI Realtime Voice Agents with an Eval Pipeline (2026)

Build a working voice agent with the OpenAI Realtime API + Agents SDK, then bolt on an eval pipeline that catches barge-in failures, hallucinated grounding, and latency regressions.

Agentic AI

Multilingual Chat Agents in 2026: The 57-Language Gap and How to Close It

Amazon's MASSIVE-Agents research shows top models hit 57% on English vs 6.8% on Amharic. Here is what 50+ language chat agents actually need.

Agentic AI

Smolagents: Hugging Face's Code-First Agent Framework Reviewed

Smolagents lets agents write Python instead of JSON. Why code-as-action reduces tool errors and where the security trade-offs are for production deployments.

AI Strategy

Enterprise CIO Guide: ElevenLabs Conversational AI 2.0 — Voice Agents Get Real Tools

Enterprise CIO Guide perspective on ElevenLabs Conversational 2.0 ships native MCP tool use, sub-second turn-taking, and a redesigned dashboard that makes voice agents feel like real software.