This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle

What I Built

I'm a frequent traveler in Brazil, and keeping costs down is my top priority when comparing flights. But finding a cheap option is only part of the work: I also need to compare departure times, stops, dates, personal preferences, and calendar conflicts, which often means opening dozens of tabs :/

That frustration led me to build AirGem: an open-source, privacy-first flight-search copilot that turns a natural-language travel request into a small set of evaluated, explainable flight options.

A user can ask:

Find cheap flights from GRU to POA from January 1, 2027, to January 8, 2027, with a maximum budget of 1500 BRL.

AirGem parses the request, searches current flight data, evaluates candidates, considers calendar conflicts, and explains the selected options. It also shows alternative flights and booking links when the provider returns enough information.

The product idea is a focused travel-planning assistant for frequent travelers, remote workers, and people who want help making a travel decision. These are the users I could imagine paying for a reliable, explainable itinerary shortlist.

My motivation

Flight-search assistants already exist. Google, for example, has an AI-powered Flight Deals experience that interprets natural-language travel ideas and searches its own flight inventory. These products are convenient, but they also tend to keep the experience inside a particular vendor's ecosystem.

That creates a question I kept coming back to: what if the most useful context is my calendar, but I don't want to give a travel platform ongoing access to it?

AirGem takes a narrower and more portable approach. Instead of connecting directly to a primary calendar account, the user can upload an .ics export with one button and set a travel buffer. The calendar is used to rule out conflicts during the search, then discarded with the rest of the transient session data.

The creative part is not trying to build another general-purpose travel chatbot. Rather, I tried to combine four pieces:

  • Gemma for interpreting preferences and explaining tradeoffs
  • SerpApi for current flight-search data
  • deterministic Python logic for filtering and ranking
  • a local calendar export for practical schedule awareness

That combination makes the assistant useful without requiring the user to trust one company with the entire travel-planning context. It also means the application can be self-hosted, the inference provider can be changed, and the calendar data can remain under the user's control.

Demo

Try the live demo: https://airgem.onrender.com

The demo asks users to provide their own SerpApi key. The key is sent over HTTPS, kept only in server memory for the transient session, never logged, and cleared after the session expires or the search completes. Optional calendars are handled in the same transient way.

AirGem flight search form and transient-key notice

AirGem flight search results

Code

✈️AirGem

Live Demo Python 3.12+ FastAPI License: MIT

A privacy-first flight-search copilot that finds flights around your real calendar.

AirGem turns a natural-language travel request into a small set of practical flight options. It keeps calendar data local, uses Gemma for semantic work and keeps search, validation, availability checks, and trade-off filtering deterministic.

🚀 Hacktoberfest Week 2: Side Hustle

AirGem is being built as a submission for the Hacktoberfest Open-Source AI Challenge: Week 2 — Side Hustle.

This challenge asks for a new project with open-weight or open-source AI that solves a real problem someone could plausibly pay for. With this, AirGem's target user is a frequent traveler, consultant, freelancer, or remote worker who wants to find an affordable trip without manually comparing flight times against work, classes, appointments, or family commitments.

Why open models?

AirGem uses Gemma through Ollama by default, with OpenRouter as an optional fallback. This keeps the model replaceable and makes…

The project includes local setup instructions, a FastAPI web app, Render deployment configuration, and tests.

How I Built It

AirGem uses Gemma as a bounded interpretation and synthesis layer, not as the source of truth for flight facts.

AirGem architecture and data flow

The application separates model judgment from deterministic application logic:

  1. Gemma parses the user's request into structured travel preferences.
  2. SerpApi provides current flight-search results.
  3. Python code filters, ranks, and normalizes the candidates.
  4. Gemma synthesizes a concise explanation of why the selected options fit the request.
  5. The UI presents the result, alternatives, calendar conflicts, and booking links.

This division matters. Gemma can understand that a traveler who prefers the afternoon may reject an evening departure for a meaningful reason, but application-side logic still controls prices, times, availability, and booking actions.

For the hosted demo, inference uses Gemma through OpenRouter and the application runs on Render. A local setup can use Ollama for a more private inference path.

Why Does Open Innovation Matter?

Open innovation made it possible to keep the system modular and honest about what each component does.

Gemma can be run locally through Ollama or accessed through a hosted inference provider. SerpApi supplies live flight data, while the ranking, calendar handling, and safety boundaries remain in the application code. FastAPI and Render make the web experience easy to run locally or deploy as a small public demo.

This also keeps the project from being locked to one model or infrastructure provider. A user can self-host the application, change the inference backend, or inspect the deterministic parts of the decision process.

The hosted version uses rate limiting, bounded request sizes, transient credentials, and in-memory session state. Users still verify the final itinerary and complete booking with the airline or booking provider.

My Agent Session

AirGem: building a privacy-first flight-search copilot
You

Use caveman ultra. Read the README for context. Help create initial scaffolding for AirGem, a Hacktoberfest Week 2 side-hustle project. Start with local Ollama Gemma, DigitalOcean infrastructure, and OpenRouter Gemma free as fallback.

Agent

Read the project context and scaffolded the first slice around replaceable LLM providers, strict flight-request parsing, and the existing project conventions.

You

Choose a first slice: minimal Ollama and OpenRouter Gemma providers under llm/, plus a core natural-language parser for cheap flights. Keep SerpAPI abstract so fastflights can be added later.

Agent

Implemented the provider interfaces and strict natural-language flight request parsing with a small testable core.

You

Commit this first slice using a conventional commit.

Agent

Committed the first slice with a conventional commit.

You

Next work item: implement SerpAPI integration under search/. Use Google Flights API, deep_search by default, departure_id and arrival_id, exact dates, price sorting, and one-way calls for outbound and return. Leave TODOs for multiple airports, flexible dates, and native round trips. Do not commit the temporary serpapi.json.

Agent

Added the SerpAPI provider and abstract search models. Kept booking URLs out of the core search result and added the requested TODOs.

You

Commit your work.

Agent

Committed the SerpAPI integration.

You

Explain what was done in the commit message.

Agent

Followed up with a clearer conventional commit description.

You

Can we run a first test? I moved the project-direction README to PROJECT and need the setup README.

Agent

Checked the setup path and described a local test using Ollama/OpenRouter, SerpAPI, and environment variables.

You

OpenRouter returned a 429 because the free Gemma provider pool was rate-limited, even after sourcing .env.

Agent

Explained that the error was upstream OpenRouter rate limiting, not local environment loading, and suggested Ollama or provider routing.

You

Can quantized Gemma 4B run through Ollama or only llama.cpp?

Agent

Explained the Ollama-compatible quantized model path and the distinction between Ollama model packages and direct llama.cpp GGUF usage.

You

Ollama returns model gemma3:4b not found even though .env has the right model. What is the best way to load .env automatically?

Agent

Added/confirmed automatic dotenv loading and explained that the model must also be pulled into Ollama with the exact configured model name.

You

The parsed request is GRU to POA on two ISO dates with USD and no missing fields. Is this right?

Agent

Confirmed the normalized FlightRequest shape and default USD currency.

You

What is next?

Agent

Connected the parser to the CLI and then wired the search path.

You

Default currency to USD and evaluate a date stabilizer for phrases like next Thursday.

Agent

Evaluated date stabilization and recommended delegating relative-date interpretation in this first slice while keeping exact ISO dates reliable.

You

LLMs can be bad at mapping this weekend to ISO dates. Could a small tool stabilize dates and be exposed as an agent tool?

Agent

Discussed a deterministic date helper/tool, but kept it out of the first v1 to avoid adding a second date-resolution policy prematurely.

You

Delegate dates for v1 and wire the full CLI path.

Agent

Wired the CLI through parsing, search, itinerary construction, and human/JSON output.

You

The CLI says SerpAPI is missing departure_id.

Agent

Diagnosed that the parsed request was not being mapped to the provider parameter names.

You

The same departure_id error remains.

Agent

Traced the request construction and fixed the mapping path.

You

Now SerpAPI says outbound_date is missing.

Agent

Identified the provider's required outbound_date field and corrected request construction.

You

Now it says return_date is required when type is round trip. Is return date defaulted to 1?

Agent

Explained that type=1 means round trip and return_date must be explicitly supplied; fixed the round-trip request mapping.

You

Are we forgetting anything else in SerpAPI?

Agent

Reviewed required and useful Google Flights parameters, including localization, deep search, exact dates, and route identifiers.

You

Is booking lookup being done for every possible ticket? That seems wrong.

Agent

Confirmed it was too eager and separated core search from booking URL resolution.

You

Commit before changing the booking slice.

Agent

Committed the current work before changing booking resolution.

You

What is outbound index?

Agent

Explained that it identifies the selected outbound result used for a later return expansion.

You

Why not use an agent loop already?

Agent

Added the bounded state-machine agent around deterministic search and selection tools.

You

The JSON has one outbound result with a booking URL.

Agent

Explained the result shape and why booking URL resolution should be deferred.

You

Remove booking URLs and keep search pure.

Agent

Removed booking URL resolution from the pure search result.

You

Commit that.

Agent

Committed the pure-search change.

You

Add airline to the JSON.

Agent

Added airline serialization to flight options.

You

Commit that.

Agent

Committed the airline field.

You

What do we need next for the project?

Agent

Recommended itinerary construction, better CLI output, and bounded agent follow-ups.

You

Add itinerary first, then improve CLI output.

Agent

Implemented itinerary construction and improved human-readable CLI formatting.

You

Give CLI examples.

Agent

Added practical one-way, round-trip, budget, stops, currency, calendar, JSON, and debug examples.

You

The round-trip output returned around 300 results, likely every outbound/return pair.

Agent

Explained the combinatorial pairing and moved toward native round-trip search plus selected-outbound return expansion.

You

How should round-trip progression work? Let the agent choose the best outbound first, then the return?

Agent

Implemented selected-outbound expansion before return selection.

You

What is the advantage versus two one-way searches paired by airline?

Agent

Compared native round-trip search, one-way pairing, price consistency, booking fidelity, and provider semantics.

You

Would a Pareto set be a good helper/filtering mechanism? Objectives: price, duration, stops, calendar fit, buffer, and other useful factors.

Agent

Designed the Pareto helper around hard constraints first, then price, duration, and stops, with calendar availability and buffer applied before Pareto filtering.

You

Think of other useful objectives.

Agent

Considered schedule fit, airline consistency, airport changes, connection risk, fare confidence, and timezone handling, while keeping hard constraints small.

You

Commit current work, then implement that.

Agent

Implemented the focused filtering/Pareto slice and committed it.

You

Keep hard constraints small.

Agent

Kept budget, stop count, exact dates, route validity, and calendar availability as the small hard-constraint set.

You

What is next for the agent?

Agent

Recommended a bounded raw LLM loop with deterministic tools and explicit state transitions.

You

Implement that.

Agent

Implemented the bounded agent state machine for outbound selection, return expansion, return selection, and deterministic fallback.

You

Commit your changes.

Agent

Committed the agent changes.

You

What can we do for agent/LLM now?

Agent

Outlined structured candidate selection, follow-ups, safe action schemas, and preserving deferred outbound choices.

You

Does that work for one-way searches? Is raw LLM, LangChain, PydanticAI, Genkit, or something else best?

Agent

Confirmed the bounded approach works for one-way and round-trip searches, and recommended raw bounded control for this small deterministic state machine.

You

What about Genkit?

Agent

Compared Genkit with the current Python stack and kept the simpler bounded controller.

You

Go with a raw bounded loop and small state machine.

Agent

Kept the implementation framework-free and bounded.

You

Can I test it through the CLI?

Agent

Added CLI testing guidance and debug output.

You

Enable debug thinking to stdout.

Agent

Added safe debug logs for state transitions, provider calls, candidate IDs, and deterministic fallbacks without exposing hidden reasoning or secrets.

You

The model chooses an invalid candidate and SerpAPI then says departure_id is missing. Commit before fixing.

Agent

Committed before fixing the expansion parameter mapping.

You

The next run selects invalid candidates but return expansion works. How exactly is the agentic loop working?

Agent

Explained the searching → selecting outbound → expanding return → selecting return → complete state sequence, turn budget, candidate IDs, and fallback behavior.

You

Tune the prompt for Gemma.

Agent

Tightened selector instructions: exact JSON, exact allowed IDs, no indexes or invented IDs, and explicit preference ordering.

You

Is Pareto also working on the return date?

Agent

Confirmed return expansion is filtered and Pareto-ranked after the selected outbound is expanded.

You

Commit your work.

Agent

Committed the Gemma prompt tuning.

You

The agent now returns selected and alternative flights with rationale and notes. Anything worth investigating, or is this a good v1?

Agent

Identified useful follow-up work: calendar integration, better UX, deferred alternatives, booking resolution, date flexibility, and evaluation.

You

Look at PROJECT and research what is missing.

Agent

Reviewed the project direction and prioritized calendar-aware availability for the next slice.

You

Implement calendar integration. Consider local ICS versus Google Calendar.

Agent

Implemented local calendar support first, keeping Google Calendar as a later integration because it adds auth and operational overhead.

You

Availability matching/filtering should happen before Pareto filtering.

Agent

Applied calendar availability and travel buffer filtering before Pareto selection.

You

Implement that and add README setup instructions for local ICS.

Agent

Added local ICS setup documentation and availability filtering.

You

Why use ics or icalendar?

Agent

Compared the libraries and recommended icalendar for parsing, with recurring-ical-events for recurrence expansion.

You

Refactor to icalendar; it is already installed.

Agent

Refactored calendar parsing to icalendar and recurring-ical-events.

You

An ICS search returned six flights and says one calendar event was applied. Is this good?

Agent

Confirmed the calendar was applied before Pareto filtering and explained the selected return expansion.

You

I added recurring-ical-events.

Agent

Integrated recurring event expansion into the calendar window.

You

Commit your work.

Source:https://dev.to/r0liveir/i-travel-often-so-i-built-an-ai-copilot-for-comparing-flights-meet-airgem-2hlb

Related posts