A family group chat is a surprisingly difficult place to put an AI agent.
One person wants to visit every landmark. Someone else wants less walking. Food preferences appear halfway through the conversation. A ticket screenshot gets buried under twenty messages.
Then the flight gets delayed.
Suddenly, “make us an itinerary” becomes a much more interesting problem:
Can an assistant understand the conversation, remember who needs what, check real information, explain the trade-offs, and recover when things change?
That question became Trippy, my family travel companion built with Switch, Telegram, and Python.
This was my first time building with Switch. I started with a travel-assistant idea and ended up learning much more about agent coordination, evidence, identity, and failure recovery than I expected.
The family should talk naturally. The system should behave carefully.
I wanted Trippy to work where my family already talks: Telegram.
A request should sound like this:
“Compare two outings tomorrow, starting from Mecca Masjid and visiting Charminar. Make Chowmahalla Palace an optional extra stop, consider the weather, and show the comparison visually.”
The family should not need to know which agent handles weather, which tool calculates routes, or which command opens memory.
Behind that simple request, however, several things need to happen:
- Resolve the places and requested date.
- Retrieve walking routes and relevant weather.
- Apply saved preferences and constraints.
- Compare the options.
- Explain missing information.
- Return a readable answer and visual.
The interface stays conversational. The implementation needs structure.
My central architectural decision was:
Agents propose. Application code validates and controls execution.
Why Switch became the backbone
The part I appreciated most about Switch was that it gave the agents a place to collaborate around an actual conversation.
Trippy uses a Telegram connector for the family-facing chat and a separate private Switch workroom for internal assignments.
That separation matters. The family gets readable replies instead of a stream of agent JSON, tool requests, and internal commentary.
The model roles communicate with the Coordinator through structured messages. Switch carries those interactions; my application checks what they mean and whether they are allowed.
Family Telegram group
↕
Switch
↕
Python Coordinator ───── SQLite
↕
Private Switch workroom
↕
Planner and specialist roles
For a first Switch project, this was a satisfying discovery: I could focus on the travel workflow while using a shared communication layer for Telegram messages, agent assignments, and media.
Switch made the collaboration practical. The Coordinator made it controlled.
Those responsibilities complement each other.
Six roles, without six agents talking at once
Trippy has three core roles and three optional specialists.
The Coordinator is deterministic Python application code. It is not another model improvising what should happen next.
| Role | Responsibility |
|---|---|
| Coordinator | Routing, identity checks, state, validation, approvals, and delivery |
| Planner | Conversation, permitted tool requests, and proposed changes |
| Reservation | Requests execution of approved simulated reservation changes |
| Researcher | Gathers bounded evidence when a request needs focused research |
| Mediator | Explains compromises between computed options |
| Watcher | Assesses relevant sourced weather events |
The optional specialists join only when useful.
A weather question can follow the direct Planner-and-tool path. A more involved comparison may benefit from research or mediation.
Researcher and Mediator handoffs are bounded, and they share the discussion’s tool budget. Delegation does not create an unlimited new allowance or an endless agent conversation.
The Mediator also cannot make an infeasible option acceptable through persuasive wording. It explains existing computed options; hard constraints remain enforced by code.
More roles should mean clearer responsibilities, not more noise.
A recommendation needs evidence behind it
Travel recommendations are easy to make sound convincing.
“Just walk there—it’s nearby.”
But nearby for whom? Using which route? Does that include walking inside the venue?
Trippy integrates:
- Open-Meteo for weather.
- OpenStreetMap data, through Nominatim and Overpass, for places and available tags.
- Routing services for mapped journey estimates.
Tool results are saved as evidence. Model replies declare factual claims against specific fields in that evidence.
For example, a walking-distance claim can point to:
/plans/0/walking_m
The backend checks the declared value against the stored result before rendering the sourced fact.
Forecast dates matter too. A forecast for today does not answer a question about tomorrow simply because the temperature looks plausible.
There are deliberate boundaries here. Field-level validation does not prove every sentence true, and an OpenStreetMap accessibility tag is not a guarantee.
If venue walking, stairs, or current opening status are unknown, the answer should expose that uncertainty.
“I don’t have enough evidence” is a useful planning result.
Memory should remember who said what
Personalization becomes unreliable when an assistant remembers a preference but forgets its owner.
“Dad prefers less walking” is different from “I prefer less walking.” A nickname is also different from a verified identity.
Trippy separates those concepts.
Saved preferences can retain an owner or reporter, source-message evidence, timestamps, importance, and whether the preference is a hard or soft constraint.
The interaction changes with the consequence:
“Call me Sarvesh.”
A display-name update happens directly.
“I prefer vegetarian meals.”
A clear personal soft preference can save with an undo option.
“I must walk at most 800 metres.”
A hard limit requires confirmation because it changes which plans are allowed.
Memory inspection makes stored information visible, and conflicting corrections can show the previous and proposed values.
Group privacy adds another boundary. Sensitive mobility, health, and expense requests need explicit sharing permission before group processing.
One lesson from testing: a technically correct privacy rejection can still be a terrible conversation. Trippy now gives clearer guidance instead of exposing a cryptic internal error.
A dependency graph, stored in SQLite
I considered whether itinerary relationships needed a graph database.
For Phase 1, they did not.
The useful structure is straightforward:
Flight arrival
↓
Airport transfer
↓
Hotel check-in
↓
Dinner
SQLite stores itinerary items and dependency edges in relational tables. A recursive query finds downstream items affected by a disruption.
Separate tables hold discussions, tool jobs, preferences, proposals, actions, processed events, and outgoing messages.
This gives the project graph-style traversal alongside ordinary transactions, foreign keys, and versioned Alembic migrations.
For a single local Coordinator, that is a practical fit. A server database becomes a stronger choice when deployment and concurrency requirements demand it.
I wanted the architecture to earn its complexity.
Disruption recovery has an approval boundary
A simulated flight delay is one of Trippy’s most revealing demonstrations.
The disruption identifies affected dependencies and starts repair planning. The proposal shows the intended changes, including timings, cost differences, alternatives, and expiry.
Then the family reviews it.
Execution requires the exact proposal approval from an authorized linked account. The application checks identity, scope, expiry, and replay protection.
A friendly “sounds good” does not become permission to spend money.
Reservation actions are currently simulated. No real supplier booking or payment occurs.
That boundary lets me demonstrate the workflow honestly while building the fundamentals needed before introducing higher-consequence integrations.
The most useful debugging lesson: good data can still produce a bad experience
One outing request successfully fetched routes and weather—and still failed.
The weather was nested inside the comparison result. The reply validator expected it through the weather contract and could not see it.
To the user, the assistant looked broken. Underneath, the provider calls had succeeded.
The fix was to expose the exact stored forecast through the same dated evidence contract used by a standalone weather request.
Testing also revealed that “show comparison visually” was being missed by the visual-request check.
These were integration failures between otherwise working components.
I added a recovery path: when the computed comparison exists but the extra narration fails or times out, Trippy can deliver that request’s saved comparison and requested schematic, with limitations visible.
It does not substitute an unrelated fictional plan.
That became a broader design principle:
A failure in generated narration should not automatically discard useful computed results.
Reliability needs more than a convincing reply
Trippy uses a durable inbox and outbox to separate message processing from delivery.
Processed event IDs prevent duplicate handling. Unique action keys protect against duplicate local execution. Assignment IDs, trip versions, and deadlines help reject stale results.
Uncertain delivery is held for review rather than blindly resent.
I am not claiming exactly-once Telegram delivery. I am making delivery state visible and giving the application a controlled recovery path.
The latest local suite passed 233 tests. The project also includes deterministic scenario checks and a process-crash recovery demonstration.
Those checks establish application behavior under controlled conditions. They are not a substitute for evaluating realistic family conversations.
The dashboard helps connect both worlds: itinerary dependencies, evidence, verification records, proposal history, and delivery state can be inspected behind the chat.
Phase 1 is the foundation
Trippy already brings together conversation, sourced outing comparisons, accountable memory, image understanding, expense bookkeeping, reminders, visual plans, calendar exports, and simulated disruption recovery.
But this is Phase 1, not the finished product.
My next priorities are:
- Test more real multi-person conversations, including Hinglish, ambiguous references, and corrections.
- Improve provider fallbacks while preserving source and freshness labels.
- Gather better venue-level accessibility, walking, opening-hour, and rest information.
- Expand deployment monitoring and conversation-quality evaluations.
- Explore real travel-status events and booking handoffs with proper reconciliation.
Trying Switch for the first time helped me move beyond “an AI that answers travel questions” toward a system where agents collaborate through explicit workflows.
That is the part I am proudest of.
The family gets one companion to talk to. Underneath, the system keeps track of evidence, ownership, decisions, and what actually happened.
Top comments (0)