Inspiration
Walking around San Francisco means juggling four browser tabs: Google Maps for directions, Citizen for crime, Twitter for what locals are saying right now, and Wikipedia for "wait, what is that building?" We wanted one companion that could plan a walk, narrate the neighborhood, and warn you about an incident that hit the news ten minutes ago — by voice, while your phone stays in your pocket.
What it does
SF Companion is a voice-first walking agent for San Francisco. You say where you want to go; it plans the walking route on a live map, fetches segment-by-segment weather, pulls real SFPD incidents along the path, scrapes fresh crime reporting from local outlets, and surfaces attractions worth a detour. The Claude-powered agent drives the map directly — when it mentions Coit Tower, the pin pulses; when it warns about a hotspot, the segment highlights. Text or voice, your choice.
How we built it
A federated GraphQL stack glued to a multi-tool Claude agent:
A TypeScript graphql-yoga BFF serving the full GraphQL contract with streaming subscriptions over an in-process bus. InsForge Postgres (PostGIS 3.6.1 enabled) for users and sessions; Redis for route and weather caching keyed by (lat, lng, hour). Mapbox Search Box and Directions handle geocoding and walking routes with an SF bbox check; Open-Meteo fills in per-segment weather. On top, an Anthropic Claude tool-use loop streams deltas, tool calls, and results through four wired tools — plan_route, get_route_context, get_user_location, show_on_map — each gated by a swappable authorize + logToolCall governance facade. Vapi voice, Nexla ingestion, TinyFish, Senso, Cosmo federation, and the frontend are scoped but not yet built.
Challenges we ran into
- Verifying PostGIS on InsForge — the architecture leaned on
ST_DWithinovergeography, so before we built anything we had to confirm the extension was actually available. It took a CLI deep-dive (db query "SELECT extname FROM pg_extension") and a tracked migration to lock it in as 3.6.1. - Picking the right BFF primitive — InsForge ships two hosting options and only one of them (
compute, Fly.io under the hood) supports the long-lived WebSockets and SSE that streaming subscriptions and Claude responses need. Working that out from docs marked "in progress" took longer than the decision deserved. - Streaming a heterogeneous event union — the agent emits text deltas, tool calls, tool results, and a final
ChatDoneover a single GraphQL subscription. Wiring that tographql-yogameant writing a small async-iterator bridge over an in-process channel that filters byturnIdand ends cleanly when the turn does.
Accomplishments that we're proud of
- Canonical GraphQL schema wired end-to-end on the dev server, with real resolvers for routing, weather, and the agent loop.
- Real Mapbox walking routes with SF bbox enforcement and per-segment splits.
- Open-Meteo per-segment weather, Redis-cached by
(lat, lng, hour). - PostGIS 3.6.1 enabled on InsForge, ready for along-route spatial queries.
- Streaming Claude agent with a four-tool loop (
plan_route,get_route_context,get_user_location,show_on_map) over a single GraphQL subscription.
What we learned
- Federated GraphQL pays off the moment you have more than one subgraph that benefits from independent deploy cadence.
- "Long-lived" vs. "request/response" is the question to ask when picking a serverless host — most edge platforms quietly fail the first one.
- Pre-built vendor agents (TinyFish for scraping, Nexla for ingestion, Senso for RAG)
What's next for SF Companion
- Proper auth via InsForge OAuth (today we're anonymous-session only)
- Historical crime joining DataSF
wg3w-h783for >48h lookback and trend analysis - Ambient voice narration — "tell me when I'm near something interesting" without prompting
- Safer-alternate-route suggestions when a segment crosses a recent incident cluster
- Generalize beyond SF: LA and NYC are the obvious next two cities given Socrata coverage
- Real Guild.ai integration for tool-call governance, replacing our file-based audit stub
Built With
- anthropic-claude
- insforge
- mapbox
- nexla
- postgis
- senso.ai
- tinyfish
- typescript
- vapi
- wundergraph-cosmo
Log in or sign up for Devpost to join the conversation.