Inspiration

There are four of us (Durham, Leicester, and London), and for most of the year we're in different parts of the country, with some of us away on placement. Whenever we try to meet up it turns into a group chat that goes round in circles for days, and right at the end someone finds out their last train home doesn't work.

We realised we were spending more time planning meetups than actually at them. The theme of OxHack was time, so we wanted to build something that cuts out that planning and gets us back to spending time together.

What it does

Day out is a video call that plans a day out while you talk.

Everyone joins with their postcode and gets their own AI agent. Your agent only listens to you, and it picks up what you want from the conversation (when you're free, how far you'd travel, budget, what you're in the mood for). There's no form or checklist to go through. A judge agent keeps an eye on the conversation and prompts the group if it stalls, but mostly you just chat to each other as normal.

Once the agents know enough, they do the planning. Each agent argues for its own person over a shortlist of real places, out loud in its own voice, and then the group votes. Everyone gets their own journey for the day. If nowhere works for everyone, it explains who can't make it and what would change that. "Durham is the blocker" came up a lot in testing.

How we built it

We started by sketching the whole thing out on a whiteboard, and a lot of the final design came straight from those drawings. We then split the work so we could build in parallel, with shared data formats between each part:

  • Isaac: places and travel data
  • Macie: the agents and the conversation
  • Charlie: the recommender (making sure the plan is fair)
  • Eila: the UI, which is all hand-drawn (watercolour paper, trees and birds, washi tape, handwritten text)

Agents

Each person has their own agent, plus a judge that runs the conversation and a moderator that sorts the options. The agents only see their own person's preferences, which means they genuinely argue for different things before it goes to a group vote. If people aren't happy, there's a second round where they can push back and the agents re-plan. We used GPT for the language, but it never makes up a time, price or distance. Every number comes from our data.

Voice

The call runs on LiveKit, self-hosted on one laptop. ElevenLabs Scribe transcribes each person's mic separately in real time (so your agent only hears you), and ElevenLabs voices let the agents talk back to the group.

Data

Most of our time went into the data, since every part of the plan depends on it. For each group we pull in:

  • OpenStreetMap: we downloaded the full UK extract (2 GB) and processed it into an offline table of ~215,000 places, including entrances for parks and forests
  • TravelTime: real public transport, driving and cycling times from every person to up to 2,000 candidate places, there and back
  • postcodes.io: postcodes to locations
  • Opening hours on the actual date, checked against gov.uk bank holidays
  • Open-Meteo: weather and sunset times
  • Ticketmaster and Skiddle: events happening that day

From this we work out the earliest each person can arrive and the latest they can leave for every place. Where those all overlap (and the place is open) is the time the group actually gets together. Around 300 places that work for everyone go to the recommender, which ranks them on fairness so one person isn't travelling three hours while everyone else travels twenty minutes.

Decision-making

All of that data only matters if it turns into a decision. For every person and place we predict when they can get there and when they need to leave, from real timetables rather than a straight-line guess, and those predictions are combined with opening hours (or daylight for outdoor places) to rank options by fairness and time together. Every number also records how much we trust it (a train found by our backup search is marked as a safe estimate, and opening hours we couldn't read are flagged), so the agents never present a guess as a fact. When nothing works, the same data shows who is blocking it and what would fix it, which is far more useful than "no results".

Challenges we ran into

  • Last trains: our first Durham to Oxford test found nothing at all. It turned out TravelTime counts waiting at home as part of the journey, so a 7pm last train looked like a five-hour trip. Adding a second search that looks for actual trains across a time window fixed it, and places like Sheffield and Lincoln started showing up.
  • Trains don't follow straight lines: on a map, Tring looks perfectly placed between Oxford, London and Reading, but by train it's around three hours from Reading. We ended up favouring bigger towns where rail lines meet.
  • Limited lookups: at first most of our travel lookups were spent on places too far away, and only 66 places worked. Changing how we pick candidates got this up to 300.
  • Live conversation: getting the agents to stop talking over people took a while, and the uni wifi stopped our laptops connecting to each other, so we ended up running everything through a phone hotspot.

What we learned

  • GPT is good at the conversation side but can't be trusted with facts like train times, so we kept it to the language and let the data handle the numbers.
  • Making a plan fair for everyone is much harder than finding the quickest option.
  • Real transport data is messy (one train fare came back as 5p, and lots of opening hours just say "varies").
  • Planning it properly on a whiteboard first saved us a lot of time later on.

What's next

We're going to use it to plan our own meetups. After that, we'd like to bring it into FaceTime or WhatsApp calls, so the agents can sit in the background of a normal catch-up.

Built With

  • cloudflare-tunnel;
  • elevenlabs;
  • geofabrik;
  • livekit;
  • llm-agents;
  • multi-agent;
  • next.js;
  • node.js;
  • open-meteo;
  • openai;
  • openstreetmap;
  • postcodes.io;
  • pyosmium;
  • python;
  • react;
  • shapely;
  • skiddle-api;
  • snowflake;
  • tailwindcss;
  • ticketmaster-api;
  • traveltime-api;
  • typescript;
  • vitest;
  • webrtc;
  • zod;
Share this project:

Updates

Submission history