Calendar Scheduling Agent
Your LLM can extract next Tuesday at 2pm from a message. But turning that into
2026-04-07T14:00:00-04:00 requires date math, timezone handling, and
ambiguity detection. That's what Biruni does.
User says
extract()Your LLM
→
resolve_time()Biruni API
→
create_event()Your calendar
→
reply()Your chat
The agent
calendar_agent.py
import httpx, os
from datetime import date
BIRUNI_URL = "https://biruni.dev/v1/resolve"
# ── Stubs: replace with your integrations ────────────────────
async def create_event(title: str, start: str, tz: str):
"""Create a calendar event. (Google Calendar, Outlook, CalDAV ...)"""
...
async def reply(text: str):
"""Send a response back to the user. (Slack, chat UI, email ...)"""
...
def extract(message: str) -> dict:
"""
Use your LLM to pull structured fields from the raw message.
Returns: { "title": str, "phrase": str, "tz": str }
"""
...
# ── Biruni integration ──────────────────────────────────────
async def resolve_time(phrase: str, tz: str) -> dict:
async with httpx.AsyncClient() as client:
r = await client.post(
BIRUNI_URL,
headers={"Authorization": f"Bearer {os.environ['BIRUNI_API_KEY']}"},
json={
"expression": phrase,
"reference_date": date.today().isoformat(),
"timezone": tz,
},
)
r.raise_for_status()
return r.json()
# ── Agent entry point ────────────────────────────────────────
async def handle(message: str):
fields = extract(message)
result = await resolve_time(fields["phrase"], fields["tz"])
match result["status"]:
case "resolved":
await create_event(fields["title"], result["resolved"], fields["tz"])
await reply(f"Done — {fields['title']} at {result['resolved']}.")
case "ambiguous":
opts = "\n".join(
f" {i+1}. {a['interpretation']}"
for i, a in enumerate(result["alternatives"])
)
await reply(f"That time is ambiguous:\n{opts}")
case _:
await reply("Couldn't parse that time — could you rephrase?")