Build a conference concierge with Agent Context and Anthropic
Written by Knut Melvær
You're at a conference. You want to see the AI talks, but the schedule is a 47-row spreadsheet organized by time slot, not by topic. You open the conference app and scroll. And scroll. You find one that looks right, but it's in "Room C" and you have no idea where Room C is. You check the venue map (a PDF, naturally). By the time you've figured it out, the talk has started.
Conference attendees have questions that don't fit neatly into a search box. "What talks about AI are on Thursday afternoon?" requires joining sessions, tracks, schedule slots, and rooms. "Is there anything for people new to design systems?" requires understanding topic relationships across the content model. A schedule page can list sessions. It can't understand intent.
For the fictive ContentOps Conf, I built a Telegram bot that attendees can message with exactly these kinds of questions. "What's happening in Room B right now?" "Tell me about the keynote speaker." "Are there any workshops I can still sign up for?" The bot has read access to the full conference content model and answers in natural language. Telegram because that's where conference attendees already are (the group chat, the hallway conversations, the "where are we meeting for dinner?" threads).
The whole thing is about 60 lines of application code across two files. And you can repurpose it to surface the agent on the website, or any other channel supported by Chat SDK. Agent Context also ships with a skill to make it even more effortless to add it to your code base.
This is the attendee side of a two-bot setup. The same Telegram app also has an ops bot for organizers that can read and write content using Sanity's Content Agent API. That bot is covered in a separate post. The two bots share a codebase but use different integration patterns, and the routing between them is a single if statement.
Two patterns, one decision
Before getting into the code, it's worth explaining why the attendee bot uses a different pattern than the organizer bot.
The organizer bot uses Content Agent API. That's a language model provider that bundles content access directly into the model. You call it like any Vercel AI SDK model, but it queries your Content Lake (Sanity's hosted content API) as part of inference. You don't choose the underlying model. You don't manage tools. It's opaque by design, and that's fine for an internal tool where you want simplicity and write access.
The attendee bot uses Agent Context. Agent Context is a different approach: it exposes your Sanity content as MCP (Model Context Protocol, a standard for connecting AI models to external tools) tools, and you bring your own LLM. You create an Agent Context document in Studio, get an MCP endpoint URL, and connect any model to those tools via @ai-sdk/mcp. The model can query your content through the tools but cannot write anything. The access boundary is structural, not prompt-based.
I chose Agent Context for the attendee bot for three reasons:
- Attendees only need read access. There's no reason to use a pattern that supports writes.
- I wanted to use Claude Sonnet 4.6 specifically. Content Agent API doesn't give you model choice.
- I wanted explicit control over the conversation flow, history management, and streaming behavior.
The routing in bot.ts makes the split visible: