Category : Applied Solution Showcase
Planning a trip today means juggling scattered tasks across many tabs: skim blogs and forums, check weather basics, map a realistic day-by-day plan, estimate costs (with currency conversion), and hunt for flights/hotelsβthen redo everything when dates, prices, or weather change. This workflow is:
Fragmented and time-intensive: constant context-switching among research, itinerary building, budgeting, and bookings.
Not reusable: outputs arenβt standardized into a brief you can share or iterate on.
Whatβs needed is a reproducible way to coordinate distinct capabilitiesβresearch, itinerary design, budgeting, and booking suggestionsβeach with the right tools, clear handoffs, and guardrails, producing a concise, shareable Final Travel Brief.
Solution approach (scope):
Use an agentic architecture with role-specialized agents and a Supervisor to enforce order and prevent loops.
Ground select steps with tools (weather, FX conversion, demo bookings) for verifiability.
Expose a simple Streamlit UI and standardize outputs into a brief suitable for travelers and reviewers.
Constraints & considerations:
Prices/FX/weather vary; treat budgets as estimates.
Respect third-party ToS; demo booking lookups are illustrativeβswap in official APIs for production.
Control LLM cost/latency via bounded turns and minimal tool calls; persist state for traceability.
Python: 3.9+ (3.10/3.11 recommended)
OS: macOS / Linux / Windows
Hardware: CPU-only is sufficient; no GPU required
Network: outbound HTTPS access (OpenAI, Open-Meteo, Frankfurter; optional booking sources)
Orchestration: LangGraph (StateGraph + MemorySaver) coordinating nodes: supervisor, research, itinerary, budget, booking, final.
Agent Runtime: LangChain (OpenAI Functions agent + AgentExecutor).
LLM Backbone: OpenAI chat model (e.g., gpt-4o) with function/tool calling; swappable to any functions-capable provider.
User Interface: Streamlit single-page app (text input, slider for max turns, chat transcript rendering).
Environment Management: python-dotenv for secrets and config.
Weather Tool: Open-Meteo geocoding + forecast (no API key).
Foreign Exchange Tool: Frankfurter API (ECB rates, no key).
Bookings Tool (educational): requests + BeautifulSoup scrapers for flights/hotels; replace with official provider APIs for production (e.g., Amadeus, Duffel, Skyscanner partners).
langgraph
langchain
langchain-openai
langchain-community
streamlit
python-dotenv
requests
beautifulsoup4
wikipedia # used by WikipediaAPIWrapper
duckduckgo-search # if not bundled via langchain_community
Pin exact versions in requirements.txt after a clean install on your target machine.
OPENAI_API_KEY β required for LLM calls
(Optional) HTTP_PROXY / HTTPS_PROXY β if your network requires it
Provide a .env_example and do not commit real keys.
You type a travel goal once, and a small team of AI βspecialistsβ work in orderβresearch β itinerary β budget β bookingβthen hand you a single, polished Final Travel Brief in the app.
The moving parts:
What it does: Takes your trip goal and a βmax turnsβ slider, then shows the Final Travel Brief and a chat-style log of everything the agents did.
Why it matters: Keeps the experience simple and watchableβno terminals, no configs.
What it does: Think of this as the project manager. It keeps track of state and decides which specialist works next.
Why it matters: Prevents chaos. Ensures agents work in a sensible order and donβt loop forever.
What it does: After each step, it looks at progress and says, βNext up: research / itinerary / budget / bookingβ¦ or weβre done.β
Why it matters: Keeps the workflow moving forward. If things look stuck, it skips ahead to βfinal.β
Research: Finds quick, trustworthy context (weather snapshot, areas, transit basics).
Itinerary: Turns your goal + research into a realistic day plan (AM/PM/Evening) with backups.
Budget: Adds up flights, hotel, food/day, transit, activities; converts to local currency.
Booking: Suggests 2β3 flight and hotel options with short pros/cons.
Why they matter: Each agent has one job. That focus makes them clearer, faster, and easier to improve.
What it does: Merges everything into one clean Final Travel Brief you can copy/share.
Why it matters: You get a single answer, not scattered notes.
Why they matter: Agents donβt guess basic facts; they pull them from reliable sources.
What it does: Powers each agentβs reasoning and writing, with built-in support for calling tools safely.
Why it matters: Good reasoning + tool use = practical answers, not just pretty text.
What it does: Tracks the conversation and turn count for this run.
Why it matters: Makes every step traceable and caps the work so it stays quick and affordable.
What happens when you press βPlan My Tripβ
You submit a goal (e.g., β5 days in Tokyo in October, $3k, from DFWβ). Orchestrator starts at Supervisor, who picks the first phase (usually βresearchβ). Research runs, calling weather (and light references) only if needed, and adds a short, cited summary. Supervisor checks progress and routes to Itinerary, which builds a walkable day plan and tips. Supervisor routes to Budget, which does one clean calculation pass and currency conversion, then writes a tidy breakdown. Supervisor routes to Booking, which proposes 2β3 options with pros/cons. Supervisor says βfinalβ, and the Finalizer stitches everything into your Final Travel Brief. Streamlit displays the brief on top and the full conversation below (for transparency).
Input you give: A single natural-language goal, plus the max number of hand-offs (βturnsβ).
Output you get:
One Final Travel Brief with:
Snapshot (dates, destination, trip length, budget)
Day-by-day (AM/PM/Evening + backups)
Budget totals (USD + local currency)
Top flight/hotel picks (pros/cons)
Quick tips (weather, transit, payments)
Guardrails (how it stays sane)
Default order: research β itinerary β budget β booking β final.
No endless loops: a strict turn cap stops runaway back-and-forth.
Tool discipline: prompts limit how often tools are called (e.g., budget does one short Python calc).
Fail safe: if a step errors or stalls, Supervisor skips ahead to keep momentum.
Image_source: https://blog.langchain.com/langgraph-multi-agent-workflows/
# Your python code here
# agents.py from typing import TypedDict, Literal, List, Dict, Any from langchain_core.messages import HumanMessage, AIMessage class AgentState(TypedDict, total=False): messages: List[Any] # chat history (HumanMessage/AIMessage) next: Literal["research","itinerary","budget","booking","final"] shared: Dict[str, Any] # e.g., {"thread_id": "...", "turns": 3}
A single, minimal contract keeps all nodes interchangeable and easy to test.
# graph.py from langgraph.graph import StateGraph from langgraph.checkpoint.memory import MemorySaver from agents import AgentState, supervisor_node, research_node, itinerary_node, budget_node, booking_node, final_node def build_graph(): g = StateGraph(AgentState) for name, fn in [ ("supervisor", supervisor_node), ("research", research_node), ("itinerary", itinerary_node), ("budget", budget_node), ("booking", booking_node), ("final", final_node), ]: g.add_node(name, fn) # workers β supervisor; finish at "final" for n in ("research","itinerary","budget","booking"): g.add_edge(n, "supervisor") g.set_finish_point("final") # supervisor chooses next hop via state["next"] def route_decider(state: AgentState) -> str: return state.get("next", "final") g.add_conditional_edges("supervisor", route_decider, { "research":"research","itinerary":"itinerary","budget":"budget","booking":"booking","final":"final" }) g.set_entry_point("supervisor") return g.compile(checkpointer=MemorySaver())
Why: explicit nodes + conditional edges make the flow self-documenting and easy to extend.
# agents.py (excerpt) def supervisor_node(state: AgentState) -> AgentState: turns = state.setdefault("shared",{}).get("turns",0) + 1 state["shared"]["turns"] = turns if turns >= 12: # hard stop to avoid loops/cost state["next"] = "final" return state order = ["research","itinerary","budget","booking","final"] curr = state.get("next","research") state["next"] = order[order.index(curr)+1] if curr in order[:-1] else "final" return state
Why: a tiny, deterministic policy that prefers the default order and bails out if progress stalls.
# agents.py (excerpt) from langchain_openai import ChatOpenAI from langchain.agents import create_openai_functions_agent, AgentExecutor from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnableLambda from langchain_core.messages import AIMessage def make_agent(llm: ChatOpenAI, tools: list, system_prompt: str): prompt = ChatPromptTemplate.from_messages([ ("system", system_prompt), ("user", "{input}"), ("assistant", "{agent_scratchpad}") ]) def _run(state: AgentState) -> AgentState: text = "\n".join(f"{type(m).__name__}: {getattr(m,'content',m)}" for m in state.get("messages",[])) runnable = create_openai_functions_agent(llm, tools, prompt) execu = AgentExecutor(agent=runnable, tools=tools, verbose=False) out = execu.invoke({"input": text})["output"] return {**state, "messages": state.get("messages", []) + [AIMessage(content=out)]} return RunnableLambda(_run) # Example: Budget agent with FX tool, tuned for determinism from langchain_core.tools import tool @tool def fx_convert_tool(amount: float, from_ccy: str, to_ccy: str) -> dict: return {"amount": amount, "from": from_ccy, "to": to_ccy, "converted_amount": round(amount*0.92,2)} budget_node = make_agent(ChatOpenAI(model="gpt-4o", temperature=0.2), [fx_convert_tool], "You are the Budget agent. Return a clear USD + local total.")
Why: every agent uses the same skeleton; only the model temperature, tools, and system prompt differ.
# agents.py (excerpt) def final_node(state: AgentState) -> AgentState: brief = ( "Final Travel Brief\n" "- Snapshot: ...\n- Day-by-day: ...\n- Budget: ...\n- Top picks: ...\n- Tips: ..." ) return {**state, "messages": state.get("messages", []) + [AIMessage(content=brief, name="Finalizer")]}
# main.py import uuid, streamlit as st from langchain_core.messages import HumanMessage from graph import build_graph from agents import AgentState st.title("π Multi-Agent Travel Planner") goal = st.text_area("Enter your travel goal:", height=100) turns = st.slider("Max turns:", 6, 40, 12) if st.button("Plan My Trip π", use_container_width=True): thread_id = str(uuid.uuid4()) state: AgentState = {"messages":[HumanMessage(goal or "5 days in Tokyo...")], "next":"research", "shared":{"thread_id": thread_id}} graph = build_graph() final_state = graph.invoke( state, config={"configurable":{"thread_id": thread_id}, "recursion_limit": turns} ) st.subheader("Final Travel Brief") st.success(final_state["messages"][-1].content) st.subheader("Conversation Log") for m in final_state["messages"]: st.markdown(f"**{type(m).__name__}:** {getattr(m,'content',m)}")
Why: minimal UI, clear control over depth (turns), and transparent output (final brief + full log).
The system outputs a single Final Travel Briefβa concise, shareable summary with a snapshot (dates, destination, trip length, budget), a practical day-by-day plan (AM/PM/Evening + backups), a budget breakdown in USD and local currency, two or three flight/hotel picks with quick pros/cons, and helpful tips (weather, transit, payments). A transparent Conversation Log shows each agentβs contribution and any tool calls. To demo, run streamlit run travel_planner/main.py, paste a goal like β5 days in Tokyo in October 2025, $3000, from DFW, prefer food/culture + one day trip,β click Plan My Trip, and review the final brief at the top (with optional screenshots placed where you showcase Research β Itinerary β Budget β Booking β Final). Itβs CPU-friendly (typically 20β90s per run), and for production you can swap the demo bookings tool for a provider API.
Time-to-plan drops from hours of tab-juggling to ~[10β20] minutes per trip (single input β Final Travel Brief).
Confidence & transparency improve via a Conversation Log that shows exactly how each step was produced.
Cost clarity: a simple USD + local-currency breakdown reduces βsurprise spend,β targeting Β±[10β15]% variance vs. actuals.
Consistency at scale: Supervisor-guided flow produces uniform outputs across travelers, routes, and seasons.
Lower run cost: bounded turns and minimal tool calls cap LLM usage to ~[N] calls / plan (β $[X].YY per run).
Fast iteration: modular agents/tools let you swap providers (e.g., bookings API) without rewriting the graph.
Portable & accessible: CPU-only, Streamlit front end, .env configurationβeasy to run in dev or a lightweight container.
Travelers/Clients: actionable plans in minutes; clearer budgets; fewer back-and-forth emails.
Agencies/Operators: repeatable briefs; staff time saved; smoother handoffs to booking desks.
Developers/Educators: a compact, production-shaped example of agentic orchestration with LangGraph + LangChain.
Average end-to-end runtime: [mm
]Average cost per plan: $[X].YY
Tool calls per plan (weather/FX/booking): [a/b/c]
Budget delta vs. actual spend: Β±[N]%
User satisfaction (Brief usefulness, 1β5): [4.2β4.7]
% runs needing human edits before sharing: [β€ 20%]
Data reliability & ToS: Demo booking scrapers are brittle and risk violating site policies; DOM changes and anti-bot measures can silently break results.
Latency & cost control: Multi-agent handoffs, external API calls, and retries can spike run time and spend without strict caps and caching.
Determinism & quality: Agents may drift (hallucinate, overuse tools, or loop); itinerary realism (timings, transfers, closures) is hard without strong grounding.
Observability & debugging: Tracing which prompt/tool caused an issue is non-trivial; need clear logs, errors, and metrics per phase.
Evaluation at scale: No automated way yet to score itinerary quality, budget accuracy, or booking plausibility beyond manual review.
Locale complexity: Time zones, holidays, seasonality, currencies, and languages introduce subtle edge cases.
Security & privacy: API keys, user inputs, and any PII must be protected; no secrets should live in the repo.
Production-grade bookings: Replace scrapers with provider APIs (e.g., Amadeus/Duffel), add rate limiting, retries, and circuit breakers.
Grounded realism: Integrate maps/transit/time-on-foot estimates, opening hours, and live events; enrich with city/POI knowledge via RAG.
Personalization loop: User profiles (interests, pace, dietary prefs), thumbs-up/down feedback, and iterative re-planning.
Quality & eval harness: Define KPIs (budget delta, timing feasibility, user rating), add unit/integration tests and synthetic evals per agent.
Observability: Structured logs, per-agent metrics, trace IDs, and a simple dashboard; error taxonomy with graceful fallbacks.
Cost/latency optimizations: Caching (weather/FX), shared context across agents, streaming responses, and adaptive max_turns.
Safety & compliance: Content filters, ToS checks for sources, and a privacy policy; redact PII in logs.
Features & exports: Multi-city trips, price tracking/alerts, calendar (ICS) export, shareable links, and PDF/Markdown brief generation.
Model flexibility: Pluggable LLMs per role (cheaper deterministic for Budget, creative for Itinerary), JSON-schema tool I/O, and offline stubs for demos.
The Multi-Agent Travel Planner shows how an agentic workflowβSupervisor β Research β Itinerary β Budget β Booking β Finalβcan turn a single natural-language goal into a clear, shareable Final Travel Brief in minutes. By pairing role-focused agents with small, purpose-built tools (weather, FX, booking) and routing them with LangGraph, the system delivers predictable outputs, transparent reasoning (via the conversation log), and easy extensibility (swap tools/models, add agents) without rewriting the app.
This is an applied template you can run today and evolve tomorrow: replace the demo booking lookup with a provider API, add evaluation metrics and observability, and personalize itineraries with lightweight profiles. The result is a practical foundation for AI-assisted trip planning that teams can adapt for real users and real operations.
Try it, fork it, extend it. Run the Streamlit app, review the Final Travel Brief, and iterate on agents or tools to match your use case. Contributions and feedback are welcomeβespecially around production booking integrations, evaluation harnesses, and export workflows.
Github link at : https://github.com/Ns90322/Multi-Agent-System