Skip to main content
Agam is a Hebrew-speaking voice assistant for Egged, Israel’s largest public bus company. It provides real-time bus schedules, route planning, and line information to users, with a special focus on serving elderly and Haredi community members with limited technical literacy.

View Agent

Open in Wonderful Platform

Overview

FieldValue
MarketIsrael - Public Transportation
VerticalTransportation
CompanyEgged (אגד)
ModelGPT-4 Realtime
PersonaFemale, Friendly, Calm
LanguageHebrew
ChannelVoice

Skills

Egged - Core transportation skill containing 11 tools for bus line lookups, route planning, station details, and data validation

Key Tools

ToolPurpose
stop_details()Get details about specific bus stations
field_judge()Determine query type and validate required fields
missing_data_policy()Identify missing information in user requests
transportation_data()Retrieve general transportation data

Prompting Techniques

Strict data grounding - The agent is explicitly prohibited from hallucinating and must only use tool-retrieved data:
CRITICAL RESTRICTION :
- IF the data is not in the tools, state you cannot find it.
- DO NOT hallucinate or invent times/routes.
Persona with linguistic constraints - Maintains female gender in Hebrew grammar:
- Maintain the **female gender** in Hebrew (מדברת, בודקת, ממליצה) at all times.
Audience-adaptive tone - Designed for accessibility:
**Audience Profile:** Elderly people, Haredi community, limited technical/Hebrew literacy.
**Tone Guidelines:**
- Respectful, slow-paced, patient, and very clear.
- Use short, simple sentences.
- **NO** technical jargon
- **NO** information overload: Give one clear answer at a time.
Multi-step workflow orchestration - Structured 5-step process for handling queries:
Step 1: Missing Information → Call missing_data_policy()
Step 2: Query Reconstruction
Step 3: Data Arrangement → Call field_judge()
Step 4: Action Execution
Step 5: Response Generation

Lessons Learned

What worked
  • Explicit step-by-step workflows ensure consistent tool calling order
  • Strict “no hallucination” rules with fallback responses maintain accuracy
  • Audience-specific tone guidelines (elderly, Haredi) improve accessibility
  • Language policy (Hebrew only) prevents confusion in multilingual scenarios
  • Duration formatting rules (“x שעות ו-y דקות”) ensure consistent output
Challenges
  • Multiple similar tools (two line_details tools exist) - consolidated naming needed
  • Balancing completeness vs. information overload for accessibility-focused audience
  • Hebrew grammar maintenance (female gender) requires explicit instruction

Deep Dive

1. field_judge(query) - Query Parser & Intent Classifier

Purpose: This is the brain of the query understanding pipeline. It takes raw user input and extracts structured transportation features while classifying the intent - the final propose is building a ready payload and send it automatically to the API call.
What it does:
  1. Time Context Calculation - Computes current Israel local time, date, and weekday in both Hebrew and English, accounting for DST
  2. Relative Date Resolution - Converts Hebrew/English relative dates to concrete YYYY-MM-DD format:
    • “היום/today” → current date
    • “מחר/tomorrow” → +1 day
    • “מחרתיים” → +2 days
    • Weekday names like “יום ראשון” → next occurrence of that day
    • “שבוע הבא” (next week) handling
  3. LLM Feature Extraction - Uses GPT with structured output to extract:
{
  "date": "YYYY-MM-DD",
  "fromTime": "HH:mm",
  "toTime": "HH:mm",
  "fromAddress": "string",
  "toAddress": "string",
  "fromStation": "string",
  "toStation": "string",
  "lineIdentifier": "string (e.g., '5א')",
  "transitType": "BUS|RAIL|TRAM|etc."
}
  1. Intent Classification - Parallel LLM call to classify as:
    • LINE_SCHEDULE - Questions about specific bus lines, schedules, first/last departures
    • DIRECTIONS - Route planning from A to B
  2. Station Name Refinement - For fuzzy station names, calls Moovit API to get candidate stops, then uses LLM to pick the best match
  3. Persistence - Saves extracted features and intent to context.kv for downstream tools
Key prompting techniques:
  • Extensive rules for Hebrew date/time parsing
  • Special handling for “מוצאי שבת” (Saturday night)
  • Address formatting rules (comma-separated, not “in”)
  • Station number priority over station name
  • Line identifier preservation (keeps Hebrew suffixes like “37א”)

2. missing_data_policy(query) - Smart Data Validation - Mini Ai Agent

Purpose: Identifies what information is missing from a user’s request and generates clarifying questions.
What it does:
  1. Street Length Check Tool - Defines an internal tool that the internal LLM uses when needed (llm choice) that uses Google Maps API to:
    • Geocode street names
    • Calculate street length from viewport bounds
    • If street > 0.7km, prompts for building number (streets in Israel can be long)
  2. LLM Analysis - Uses GPT to analyze the query against a comprehensive ruleset:
    • Universal Blockers:
      • AM/PM ambiguity (e.g., “at 5” needs clarification)
      • Station number overrides (no follow-up needed)
      • One question per piece of info
    • Route Planning Requirements:
      • Origin city + Destination city + Time
      • Street name recognition without “רחוב” prefix
      • City-to-city queries are sufficient (no intra-city details needed)
    • Line Schedule Requirements:
      • Line number OR location is sufficient
      • Station name without city → ask for city
  3. Question Generation - Returns JSON array of English questions to ask the user
  4. System Message Delivery - Sends questions via context.agent.sendSystemMessage()
Key logic:
// Street length check determines if building number needed
if (lengthKm > 0.7) {
  // Street is long → ask for building number
} else {
  // Street is short → building number not needed
}

3. transportation_data() - Moovit API Gateway

Purpose: The actual data fetcher. Calls Moovit’s API based on the intent determined by field_judge.
Two execution paths:

A. runLineSchedule() - For LINE_SCHEDULE intent

  1. API Call - POST to Moovit’s SearchAI endpoint with:
{
  "intent": "LINE_SCHEDULE",
  "userLanguage": "he",
  "searchLocation": { "location": { "latitude": 31917827, "longitude": 34803918 } },
  "features": { /* from KV */ }
}
  1. Response Processing:
    • Filters and sorts lines (Egged first)
    • Limits to 5 lines max
    • Normalizes stop names (e.g., “ת.” → “תחנה ”)
    • Transliterates line number suffixes (“37א” → “37 alef” for TTS)
    • Detects duplicate lines (same line in opposite directions)
    • Identifies live arrival data availability
  2. Output:
{
  "linesSchedule": { "date": "...", "lines": [...] },
  "error": "",
  "current_time": "2025-01-15 14:30"
}

B. runDirections() - For DIRECTIONS intent

  1. API Call - Same endpoint but with:
{ "intent": "DIRECTIONS", ... }
  1. Response Processing:
    • Extracts itinerary with legs
    • Processes each leg (Bus, Walk, Wait, etc.)
    • Flattens location names
    • Removes Wait/Walk/PathWayWalk legs from final output
    • Calculates total trip time from startTime/endTime
    • Sorts legs by startTime
  2. Output:
{
  "itinerary": { "legs": [...], "total_trip_time": "1h 30m" },
  "error": "",
  "current_time": "2025-01-15 14:30"
}
Shared features:
  • Retry logic (3 attempts with 100ms delay)
  • 424 status special handling (surface error text)
  • Hebrew stop name normalization
  • Metadata persistence for debugging
  • Current time in Israel timezone

How They Work Together

User Query: "מתי יוצא קו 5 מחיפה מחר בבוקר?"

1. missing_data_policy() → Checks if all required info present
   ↓ (no questions needed)
   
2. field_judge() → Extracts:
   - lineIdentifier: "5"
   - fromAddress: "חיפה"
   - date: "2025-01-16"
   - fromTime: "09:00"
   - intent: "LINE_SCHEDULE"
   ↓ (saves to KV)
   
3. transportation_data() → Reads intent from KV
   ↓ Calls Moovit LINE_SCHEDULE API
   ↓ Returns schedule data
   
4. Agent formats response based on prompt rules