Inspiration

I came into this hackathon planning to do the obvious thing: wire an LED, a buzzer, and a button to Caspian and call it "control your home from chat." A few days in, I realized that demo didn't actually need Caspian — three webhook calls could do the same job. If the SDK's whole point is one agent identity reaching a human across many channels, the interesting question wasn't "can I turn on a light from Telegram," it was "can an agent decide, on its own, how urgently and where to reach someone — and know when to stop."

That reframing is where Asha Iris came from. I'd already built ASHA, an agentic smart-home system for my final-year capstone (ESP32, MQTT, a WhatsApp-native MCP server, a Twi speech pipeline). Caspian was the missing multi-channel front door for it — but only if I built something Caspian itself doesn't ship yet.

What it does

Iris is an agent that sits in front of every connected channel at once — Telegram and Discord for this build — and:

  • Resolves one identity for a person no matter which channel they're on
  • Can be told to watch for something (a physical sensor event, or just a timer) and proactively notify the right contact when it happens
  • Escalates across channels if the first attempt goes unanswered, and stops the moment someone actually replies — on any channel, not just the one it messaged first Separately, Iris's messaging layer (CAAM — Caspian as an MCP) is exposed as its own MCP server, so any MCP-capable agent — Claude, Copilot, a custom agent — can send and receive through Caspian as tools, without hand-rolling channel adapters. Caspian's own roadmap lists an MCP server as something they haven't built yet; this fills that gap.

How I built it

I started by actually reading Caspian's source, not just the docs — the first real finding was that capabilities=["INITIATE"] isn't a free-text field, it's a fixed set the server validates, and Telegram/Discord/Slack don't get INITIATE at all (only SMS/iMessage can cold-start a conversation — a real platform constraint, not a Caspian gap, since bots generally can't DM someone who's never messaged them first). That single finding reshaped the whole product: "message anyone, cold, from a name" isn't possible on the free channels, so the real design became "remember everyone who's ever messaged you, and reach them there."

For the agent loop itself, I compared hand-rolling it (which I'd already done once, in TypeScript, for a WhatsApp-native version of ASHA) against adopting the OpenAI Agents SDK in Python. The SDK's tool-call loop and MCP client wiring were worth adopting; its session/memory layer wasn't a fit for what I needed, so I kept my own Redis-backed history and identity store instead of forcing everything into Sessions.

The escalation engine was the hardest design problem: an MQTT event and a task record needed to be correlated without inventing a UUID scheme, so the task ID doubles as both the Redis key and the MQTT topic suffix. A background retry loop notifies, waits, and re-checks task status — and a separate check on every real inbound message asks "does this reply resolve any open task, regardless of which channel it came in on" — which is what actually lets Iris notice you replied on Discord to an alert it sent on Telegram.

Challenges I ran into

  • Caspian's INITIATE capability isn't available on Telegram/Discord/Slack — confirmed by testing against the live API, not assumed from docs. This ruled out the simplest version of the pitch and forced the identity/memory-first redesign that's now the actual product.
  • Proactive email delivery reports success but doesn't reliably land — verified across multiple fresh conversations and identities to rule out a bug on my side before concluding it's likely a platform-side gap. Documented as a known limitation rather than hidden.
  • Cross-channel identity has no verification step yet — right now, telling Iris "my email is X" links it on say-so. Fine for a hackathon demo, not fine for anything real; it's the first thing on the roadmap. ## What I learned

The most useful thing I learned wasn't Caspian's API — it was to test assumptions against the real thing early. My first instinct was to design around what the docs implied Caspian could do; the actual product only became interesting once I'd hit the platform's real edges (capability limits, delivery reliability) and built around what was actually true, not what sounded true.

Built With

  • asha
  • caspian
  • event
  • featherless
  • fly
  • groq
  • iot
  • llm
  • mcp
  • python
  • sensor
Share this project:

Updates