Skip to content

Extractors API

Extractors use the LLM to pull structured data from natural language.

Built-in Extractors

name()

Extracts names from text.

typescript
import { name } from "@andresaya/flowkit";

.ask("get_name", "What's your name?", name(), "user_name")

Input examples:

  • "My name is John" → "John"
  • "I'm Sarah Smith" → "Sarah Smith"
  • "Call me Bob" → "Bob"

email()

Extracts email addresses.

typescript
import { email } from "@andresaya/flowkit";

.ask("get_email", "What's your email?", email(), "user_email")

Input examples:


number()

Extracts numbers.

typescript
import { number } from "@andresaya/flowkit";

.ask("get_age", "How old are you?", number(), "age")

Input examples:

  • "I'm 25 years old" → 25
  • "Twenty five" → 25
  • "About 30" → 30

yesNo()

Extracts yes/no responses.

typescript
import { yesNo } from "@andresaya/flowkit";

.ask("confirm", "Is this correct?", yesNo(), "confirmed")

Input examples:

  • "Yes" → "yes"
  • "Yeah, that's right" → "yes"
  • "No thanks" → "no"
  • "Nope" → "no"

oneOf(options)

Extracts from a list of options.

typescript
import { oneOf } from "@andresaya/flowkit";

.ask("category", "Is this billing, support, or other?", 
     oneOf(["billing", "support", "other"]), "category")

Input examples:

  • "I need billing help" → "billing"
  • "It's a technical issue" → "support"

text()

Extracts free-form text (captures everything).

typescript
import { text } from "@andresaya/flowkit";

.ask("issue", "Describe your problem:", text(), "issue_description")

custom(description)

Creates a custom extractor with your own description.

typescript
import { custom } from "@andresaya/flowkit";

// Custom date format
.ask("date", "When would you like to schedule?", 
     custom("A date in YYYY-MM-DD format"), "appointment_date")

// Phone number with specific format
.ask("phone", "What's your phone number?",
     custom("A phone number in format XXX-XXX-XXXX"),
     "phone_number")

// Product code
.ask("product", "What product are you asking about?",
     custom("An alphanumeric product code like ABC-123"),
     "product_code")

Using Extractors

All extractors are used in .ask() steps:

typescript
.ask(stepId, message, extractor, slotName)

The extracted value is stored in the slot and can be used in subsequent messages:

typescript
.ask("name", "What's your name?", name(), "user_name")
.then("greet")
.say("greet", "Hello {{user_name}}!")

How Extraction Works

  1. User provides input
  2. LLM receives the message + extraction instructions
  3. LLM returns structured JSON with extracted value
  4. Value is validated and stored in slot
  5. If extraction fails, retry or ask again
typescript
// Behind the scenes, the LLM sees:
{
  "systemPrompt": "Extract a name from the user's message...",
  "userMessage": "I'm John Smith",
  "responseFormat": { "name": "string" }
}

// LLM returns:
{ "name": "John Smith" }

ExtractType Type

typescript
type ExtractType =
  // Basic types
  | "text"       // Free text
  | "name"       // Person's name
  | "yesno"      // Yes/no response
  | "number"     // Any number
  | "email"      // Email address
  | "phone"      // Phone number
  | "date"       // Date
  | "url"        // URL/link
  | "time"       // Time (HH:MM)
  | "integer"    // Integer only
  | "currency"   // Money amount
  | "percentage" // Percentage
  | "address"    // Physical address
  | "zipcode"    // Postal code
  | "creditcard" // Credit card number
  // Choice types
  | { oneOf: string[]; hints?: Record<string, string[]> }
  | { multiSelect: string[]; hints?: Record<string, string[]> }
  // Advanced types
  | { custom: string }
  | { regex: string; flags?: string; errorMessage?: string }
  | { range: { min?: number; max?: number; step?: number } }
  | { length: { min?: number; max?: number } }
  | { list: { separator?: string; minItems?: number; maxItems?: number } };

Advanced: Custom Validation

For complex extraction needs, use inline actions:

typescript
.ask("date", "When?", custom("date"), "raw_date")
.do(async (ctx) => {
  const parsed = parseDate(ctx.slots.raw_date);
  if (!parsed) {
    throw new Error("Invalid date");
  }
  ctx.slots.appointment_date = parsed.toISOString();
})

Best Practices

Choose the Right Extractor

  • name() - For person names
  • email() - For email addresses
  • number() - For numeric values
  • yesNo() - For confirmations
  • oneOf() - For categorization
  • text() - For open-ended responses
  • custom() - For specific formats

Provide Context

Good prompts help extraction accuracy:

typescript
// Less accurate
.ask("info", "Info?", email(), "email")

// More accurate
.ask("info", "What email should we send the confirmation to?", email(), "email")

Extraction Retries

FlowKit automatically retries extraction on failure. Configure with maxRetries in engine config.

Released under the MIT License.