Inspiration

Airbnb takes 30% per booking and cities are losing the fight to enforce short-term-rental
tax and permit rules. Hosts spend hours answering identical guest questions; travelers pay more than they should because no platform shows availability across Airbnb, VRBO, HomeAway, and direct-booked listings in one place; and city auditors have no way to query a platform's data programmatically. We wanted to see how far we could go in a single hackathon day
toward an end-to-end agentic platform that handles all three sides — host, guest, and city oversight — with voice as the primary interface and AI agents doing the work humans currently do by hand.

What it does

BnBMesh is an agentic short-term rental platform with three live surfaces:

  • Host onboarding by voice. Click "Become a Host" on bnbmesh.ai, talk to an AI agent for ~3 minutes about your place, and watch a structured listing form fill itself in real time as the agent invokes a update_listing tool on every captured field. You can type to override
    anything — manual edits win.
  • Live customer support, mesh-style. Any call gets a 32-character public URL at /#call-. A support agent can open the link, see the live transcript, and inject context (typed or
    spoken) that gets pushed into the running call as a system message — the AI agent weaves it into its next reply.
  • Meta-search across platforms. A natural-language search hits a Lambda which uses TinyFish's agentic browser to scrape Airbnb (with VRBO and HomeAway as next targets),
    normalizes per-platform pricing, and caches in Redis Cloud. The same backend exposes a Model Context Protocol server so anyone can install BnBMesh into ChatGPT, Claude, or Cursor and
    search by chat. The premium "split-stay" tool (stitching multiple bookings when one listing can't cover the whole trip) sits behind an x402 payment wall.

The legacy operations stack — call routing, reservations, Guesty/Properly integrations —
keeps running on the existing PHP+MySQL app, fronted by bland.ai for inbound calls, while bnbmesh.ai is a clean serverless rebuild on the public side.

How I built it

  • Frontend: Vite + React landing page, Vapi Web SDK for browser-side voice, Web Speech API
    for the text-input mic, plain CSS (no framework). Hash-based routing for the public call viewer.
  • Backend: Node 22 AWS Lambda behind API Gateway HTTP API. Single handler dispatching /api/{search, mcp, calls/{id}/{start,end,turn,context}, vapi-webhook, split-stay, health}.
    The MCP server speaks JSON-RPC 2.0 over streamable HTTP.
  • Voice: Vapi for both the support assistant (Elliot voice) and host onboarding (Savannah). The host assistant has a strict tool definition for update_listing so every field captured
    triggers a structured tool call back to the browser.
  • Data layer: Redis Cloud over TCP from Lambda (using the redis npm package). Two roles —
    TinyFish search-result cache (bnbmesh:search:, 10-min TTL), and an agent memory layer (bnbmesh:mem:) backing remember_preference/recall_preferences MCP tools. Calls + transcript history under bnbmesh:call::meta and :turns (LIST).
  • Search: TinyFish's /v1/automation/run-sse API for live agentic browser scraping, with SSE stream parsing inside the Lambda and a 22-second timeout that falls back to deterministic
    mock data so the UX never hangs.
  • Skill publishing: A SKILL.md + shipables.json published to shipables.dev as
    oceanseth/bnbmesh; installable in Claude Code, Cursor, and 30+ other agents via npx
    @senso-ai/shipables install.
  • Payments: x402 (HTTP 402) on the plan_split_stay tool — clients without an x-payment
    header get back the payment descriptor and can pay-and-retry per the protocol.
  • Infra: All of it Terraformed in a single terraform/ directory — Route 53 zones, ACM cert with four SANs (bnbmesh.ai, .bnbmesh.ai, bnbmesh.com, *.bnbmesh.com), CloudFront with two
    origins (S3 for static, API Gateway for /api/
    ), Lambda + IAM + API Gateway + permissions. terraform apply boots the entire environment from scratch in about 15 minutes.

Challenges I ran into

  • Lambda Function URLs returned 403 despite authorization_type = NONE and a valid
    public-invoke policy — almost certainly an org-level SCP. Swapped to API Gateway HTTP API, lost ~30 minutes but ended up with a cleaner CORS story.
  • TinyFish's API shape didn't match my first guess. I'd coded against a JSON-response /v1/agent/run endpoint; the real API is /v1/automation/run-sse with a Server-Sent Events
    stream and an X-API-Key header. Had to add a streaming parser that bails on the first COMPLETE event so we don't wait for the SSE connection to close.
  • Airbnb's anti-scrape is real. Even TinyFish's stealth profile times out beyond 30 seconds against airbnb.com, so the demo path falls back to mock with a clear source: mock,
    fallback_reason: tinyfish timeout label and the live result gets cached on success.
  • Vapi assistantOverrides schema is stricter than the docs suggest. Trying to pass
    model.tools as an override returned a 400. Fixed by PATCH /assistant/{id} to bake the tool
    definition into the assistant itself; the browser only sends metadata.
  • CJS-default-export interop bit twice. @vapi-ai/web ships with exports.default = Vapi, and Vite's dev (esbuild) and prod (Rollup) bundlers landed the constructor in different places. Settled on typeof VapiSDK === 'function' ? VapiSDK : VapiSDK.default and added
    optimizeDeps.include so dev and prod agree.
  • Redis confusion early on. I started building against Upstash's HTTP-REST shape; the actual database we got was Redis Cloud over TCP. Swapped to the redis npm package, bundled into
    the Lambda zip, single connection reused across warm invocations.
  • Race between the existing PHP app and the new serverless one. Resisted the urge to rewrite api.php (50+ cases, 1900 lines) in Lambda. Kept the legacy stack on bland.ai for the
    existing inbound number; new public surface is Vapi-only on bnbmesh.ai. Prevented a
    half-finished migration from breaking the demo.

Accomplishments that I'm proud of

  • Voice fills a form in real time. The agent calls a structured tool every turn and the
    React form animates the field that just got set — it's the moment the demo earns its keep, and it works.
  • Public call URLs with human-in-the-loop injection. Copy the share URL, open it on another device, type a context note, and the live AI call uses it. End-to-end working, with 128-bit IDs and CloudFront in front for guess-protection.
  • Five sponsor integrations from a standing start in one day: Vapi, TinyFish, Redis Cloud,
    shipables.dev, x402.
  • Fully Terraformed. A fresh AWS account could run terraform apply and have the whole stack live in 15 minutes — DNS, certs, CloudFront, Lambda, API Gateway, all of it.
  • Coexistence with the legacy stack. The existing PHP/MySQL ops platform keeps serving real reservation data and bland.ai inbound calls — bnbmesh.ai is purely additive, no migration
    risk.
  • Live skill on shipables.dev. Anyone can npx @senso-ai/shipables install oceanseth/bnbmesh and have the skill in Claude Code or Cursor in seconds.

What I learned

  • Vapi tool calling is the right primitive for voice-driven UIs. Trying to parse transcript text on the client is fragile; structured tool calls give you reliable JSON to drive React state.
  • The MCP ecosystem and the Agent Skills ecosystem solve different problems. MCP is a runtime protocol agents speak to remote servers; Agent Skills (shipables.dev) are static
    instructions and code agents bundle locally. A modern product wants both — same backend, two distribution channels.
  • AWS Lambda has subtle gotchas at the edge. Function URLs aren't really public unless your org allows them, API Gateway HTTP API caps at 29 seconds whether you like it or not, and
    CloudFront's AllViewerExceptHostHeader origin policy is the only sane choice when CloudFront fronts a Function URL or API Gateway.
  • CJS/ESM interop is still the most under-budgeted task in any 2026 frontend project. Pre-bundling via optimizeDeps.include avoids a class of dev-vs-prod inconsistencies that
    would otherwise eat a debugging hour at the worst possible moment.
  • Anti-bot scraping is the real bottleneck for "live" meta-search. Caching aggressively
    (Redis with 10-min TTL) and labeling fallbacks honestly is more useful than pretending every search is fresh.
  • Preserving an existing system while building a new front face is almost always the right
    hackathon call. Two cleanly-separated stacks beat one half-finished rewrite, every time.

======= DEMO SCRIPT ======= 0:00–0:15 — Hook + problem (camera or screen with title card "BnBMesh")

▎ "Airbnb keeps thirty percent of every booking, hosts spend hours answering the same ▎ questions, and cities can't enforce tax or permit rules at scale.
▎ BnBMesh is the agentic short-term-rental platform that runs hosting, guest support, and ▎ meta-search end-to-end with voice agents."


0:15–1:20 — Demo 1: "Become a Host" (the autonomy showcase) (Tab A, click Become a Host)

▎ "Watch what listing your place looks like on BnBMesh." ▎ click "Become a Host" — mic permission — start call

When the agent speaks, respond naturally to a few questions. Aim for ~45 seconds:

▎ Agent: "What's the address?"
▎ You: "Twelve thirty Anacapa Street, Santa Barbara" — point at the form: "Watch the form ▎ fill itself."
▎ Agent: "Property type?"
▎ You: "Whole house, three bedrooms, two baths, sleeps six." — narrate over: "All three
▎ filled in one tool call."
▎ Agent: "Nightly price?"
▎ You: "Two-fifty a night with a hundred-dollar cleaning fee."

Click into one field and type to override, narrating: "The host can also type — manual
overrides win, the agent moves on."

End the call with: "Wifi, parking, hot tub. Done."

▎ "That voice agent is Vapi, calling a structured tool every turn. The form's a single React ▎ state."


1:20–2:00 — Demo 2: Public call URL + human-in-the-loop

Copy the share URL from the modal. Paste it into Tab B's URL bar (or scan from phone).

▎ "Every call has a 32-character ID. Anyone with the link can join as a support agent —
▎ CloudFront protects against guessing."

On the public viewer, type into the add-context bar:

▎ "Guest is bringing a service dog — confirm pets are allowed."

Then back to the call modal:

▎ "The agent gets that as a system message mid-call and weaves it in."

(If the call already ended, narrate: "During a live call, the agent gets that injection in
real time.")


2:00–2:30 — Demo 3: ChatGPT Skill + Meta-search

Scroll to the search bar. Voice it: click mic, say "three bedroom in Austin Memorial Day weekend".

▎ "Search hits a Lambda, which calls TinyFish to scrape Airbnb live, then caches in Redis
▎ Cloud. Per-platform pricing in one search."

Scroll to MCP section, click Copy on the URL.

▎ "Same backend speaks Model Context Protocol — paste this URL into ChatGPT and BnBMesh
▎ becomes a chat skill."

Cut to Tab B terminal:
npx @senso-ai/shipables install oceanseth/bnbmesh

▎ "Or install the shipables.dev skill straight into Claude Code or Cursor."


2:30–3:00 — Close

Cut to Tab C (GitHub).

▎ "Everything's open source — IaC in Terraform, MCP server in a Lambda, voice frontend in
▎ Vite, and a five-tool MCP server with x402 payments gating the premium 'split-stay' tool. ▎
▎ Sponsors used: Vapi, TinyFish, Redis Cloud, shipables.dev, x402 — five.

▎ BnBMesh: agentic short-term rental, end to end."

End on the bnbmesh.ai homepage.

What's next for BnbMesh

Built With

  • redis
  • senso-ai
  • terraform
  • tinyfish
  • vapi
  • x402
Share this project:

Updates