Kereta Sewa Jalan-jalan

Core Source Code & Agentic AI Implementation

Python 3.8+ FastAPI Gemini 2.5 Flash Code-as-Action

About This Code Showcase

This code snippet shows the M5 Agentic Workflow pattern applied to car rental bookings. The LLM generates Python code that queries vehicles, checks date conflicts, computes rental cost, and inserts new bookings.

The full implementation (main.py) is under 200 lines and handles all rental flow logic through code-as-action.

Core: Agentic Booking Engine (main.py)

FastAPI backend wraps Gemini 2.5 Flash to generate executable Python code for each rental request. Helper functions are injected into the execution namespace:

main.py — FastAPI App & Code Execution
from fastapi import FastAPI, HTTPException import google.generativeai as genai from tinydb import TinyDB, Query from datetime import datetime, timedelta app = FastAPI(title="Kereta Sewa Jalan-jalan API") db = TinyDB('kereta_sewa_bookings.json') vehicles_tbl = db.table('vehicles') bookings_tbl = db.table('bookings') PICKUP_LOCATIONS = ["KLIA", "KL Sentral", "Subang Airport (SZB)", "TBS"] BOOKING_DEPOSIT = 100.0 HOTEL_DELIVERY_FEE = 50.0 def get_daily_rate(tier): return {"Economy": 120, "Compact": 160, "SUV": 250, "MPV": 220, "Premium": 350}.get(tier, 150) def calculate_rental_cost(tier, days, hotel_delivery=False): # Weekly rate only applies for full-week economy/compact rentals weekly = {"Economy": 700, "Compact": 950}.get(tier) daily = get_daily_rate(tier) base = weekly if (weekly and days == 7) else daily * days total = base + BOOKING_DEPOSIT if hotel_delivery: total += HOTEL_DELIVERY_FEE return {"base": base, "deposit": BOOKING_DEPOSIT, "delivery": HOTEL_DELIVERY_FEE if hotel_delivery else 0, "total": total} def has_date_conflict(vehicle_id, pickup_date, return_date, bookings_tbl): start = datetime.strptime(pickup_date, "%Y-%m-%d") end = datetime.strptime(return_date, "%Y-%m-%d") existing = bookings_tbl.search( (Query().vehicle_id == vehicle_id) & (Query().status.one_of(["rented", "booked"])) ) for b in existing: ex_start = datetime.strptime(b["pickup_date"], "%Y-%m-%d") ex_end = datetime.strptime(b["return_date"], "%Y-%m-%d") if not (end <= ex_start or start >= ex_end): return True return False

Agentic Workflow: Code Generation Prompt

The LLM receives a strict prompt that lists available helpers and expected output format. It writes Python code that sets STATUS and answer_text variables:

main.py — Gemini Prompt & Code Execution
PROMPT = """You are Kereta Sewa Jalan-jalan car rental booking assistant. WRITE PYTHON CODE. Database: vehicles_tbl, bookings_tbl Functions: next_booking_id, get_daily_rate, calculate_rental_cost, has_date_conflict, datetime, timedelta Fleet: 56 vehicles across Economy/Compact/SUV/MPV/Premium tiers Pricing: Economy RM120/day RM700/week | Compact RM160/day RM950/week SUV RM250/day | MPV RM220/day | Premium RM350/day Booking deposit: RM 100 (deducted from final bill) Hotel delivery: RM 50 add-on Pickup locations (free): KLIA, KL Sentral, Subang Airport (SZB), TBS Required: customer_name, phone, license_no Booking prefix: RNT. Min 1 day, max 7 days. Reference: Wednesday, 8 Apr 2026 Set STATUS (success|vehicle_unavailable|date_conflict|invalid_request) and answer_text Output: Python code in markdown block Request: {question}""" def execute_code(code, user_request): SAFE = {"Query": Query, "next_booking_id": next_booking_id, "get_daily_rate": get_daily_rate, "calculate_rental_cost": calculate_rental_cost, "has_date_conflict": has_date_conflict, "datetime": datetime, "timedelta": timedelta, "user_request": user_request} LOCALS = {"db": db, "vehicles_tbl": vehicles_tbl, "bookings_tbl": bookings_tbl} try: exec(code, SAFE, LOCALS) except Exception: return {"error": traceback.format_exc()} return { "answer": LOCALS.get("answer_text", "No response"), "status": LOCALS.get("STATUS", "unknown") }

Example: AI-Generated Booking Code

When a user says "Book a Myvi for 3 days from KLIA. Name: Ahmad, Phone: 0123456789, License: D1234567", Gemini produces code like:

Example Generated Code
# Parse request from user_request pickup_date = "2026-04-09" days = 3 return_date = (datetime.strptime(pickup_date, "%Y-%m-%d") + timedelta(days=days)).strftime("%Y-%m-%d") # Find first available Myvi candidates = vehicles_tbl.search( (Query().model == "Perodua Myvi") & (Query().status != "maintenance") ) vehicle = None for v in candidates: if not has_date_conflict(v["vehicle_id"], pickup_date, return_date, bookings_tbl): vehicle = v break if vehicle is None: STATUS = "vehicle_unavailable" answer_text = "No Myvi available for those dates." else: cost = calculate_rental_cost("Economy", days, hotel_delivery=False) bk_id = next_booking_id(bookings_tbl, "RNT") bookings_tbl.insert({ "booking_id": bk_id, "vehicle_id": vehicle["vehicle_id"], "model": vehicle["model"], "customer_name": "Ahmad", "phone": "0123456789", "license_no": "D1234567", "pickup_location": "KLIA", "pickup_date": pickup_date, "return_date": return_date, "days": days, "total_amount_myr": cost["total"], "status": "booked" }) STATUS = "success" answer_text = f"Booking {bk_id} confirmed for {vehicle['model']} " \ f"({pickup_date} to {return_date}). Total RM {cost['total']}."

Key Points:

FastAPI Endpoints

main.py — REST API Routes
@app.post("/api/chat", response_model=ChatResponse) async def chat(request: ChatRequest): content = generate_code(PROMPT.format(question=request.message)) result = execute_code(extract_code(content), request.message) if result["error"]: raise HTTPException(500, detail=result["error"]) return ChatResponse(answer=result["answer"], status=result["status"]) @app.get("/api/vehicles") async def get_vehicles(status=None, tier=None): vehicles = [v for v in vehicles_tbl.all() if (not status or v["status"] == status) and (not tier or v["tier"] == tier)] return {"vehicles": vehicles, "total": len(vehicles)} @app.get("/api/bookings") async def get_bookings(status=None, date=None): bookings = [b for b in bookings_tbl.all() if (not status or b["status"] == status) and (not date or b["pickup_date"] == date)] return {"bookings": bookings, "total": len(bookings)}