Skip to content

03 · Travel Planner

A travel-planner Agent walks through five turns of a single conversation: kicking off the trip, layering on budget and travel-mode constraints, swapping a day's activity, and producing a final itinerary summary. Each turn uses reply.ask() so the conversation context (constraints from earlier turns) carries forward without the caller re-supplying it.

What it covers#

  • Holding a multi-turn conversation by chaining reply.ask(...) instead of calling agent.ask(...) each time.
  • How conversation history persists across turns so the Agent doesn't "forget" the user's earlier constraints.
  • The pattern of incremental refinement — start broad, add constraints, ask for revisions, then summarise.

Primitives covered#

  • Agent
  • agent.ask() for the first turn
  • reply.ask() for follow-up turns (context-preserving)

Source#

"""03 · Travel planner — multi-turn conversation

Chained ``reply.ask()`` builds on the same conversation history. The planner
remembers constraints from earlier turns without the caller re-supplying
context each time — the stream stays alive across the whole dialogue.

Run::

    .venv-beta/bin/python 03_travel_planner.py
"""

import asyncio

from autogen.beta import Agent
from autogen.beta.config import GeminiConfig

def section(title: str) -> None:
    print(f"\n── {title} ───")

TURNS = [
    "I want to plan a 5-day trip to Japan in late April. Just cherry-blossom season.",
    "Budget is around $2500 per person, two travellers. Optimise for sightseeing, not luxury.",
    "We prefer trains to flights once we're in Japan. Draft a day-by-day itinerary.",
    "Looks great. For day 3, swap the shopping stop for something outdoorsy in or near Kyoto.",
    "Summarize the final itinerary in a single bullet list, one line per day.",
]

async def main() -> None:
    config = GeminiConfig(model="gemini-3-flash-preview", temperature=0)

    agent = Agent(
        "travel-planner",
        prompt=(
            "You are a detail-oriented travel planner. When the user adds "
            "constraints, update the plan rather than starting over. Be "
            "concrete and concise."
        ),
        config=config,
    )

    section("Turn 1 — kick off")
    reply = await agent.ask(TURNS[0])
    print(reply.body)

    for i, question in enumerate(TURNS[1:], start=2):
        section(f"Turn {i}{question}")
        reply = await reply.ask(question)
        print(reply.body)

if __name__ == "__main__":
    asyncio.run(main())