By Sagar Shankaran, Founder of CallSphere
Build an AI agent that helps community members discover local events, register with capacity management, receive reminders, and get real-time updates for community organizations.
Key takeaways
Community organizations — neighborhood associations, cultural centers, recreation departments, and civic groups — host dozens of events each month. Yet most still rely on flyers, Facebook posts, and word of mouth. People miss events they would have loved because they did not hear about them in time, or they show up to events that are already at capacity.
An AI event agent solves this by maintaining a searchable event catalog, handling registrations with capacity limits, sending timely reminders, and providing real-time updates when events change.
Define the structures that represent events and registrations.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
flowchart LR
CALLER(["Donor or Volunteer"])
subgraph TEL["Telephony"]
SIP["Twilio SIP and PSTN"]
end
subgraph BRAIN["Nonprofit AI Agent"]
STT["Streaming STT<br/>Deepgram or Whisper"]
NLU{"Intent and<br/>Entity Extraction"}
TOOLS["Tool Calls"]
TTS["Streaming TTS<br/>ElevenLabs or Rime"]
end
subgraph DATA["Live Data Plane"]
CRM[("CRM and Notes")]
CAL[("Calendar and<br/>Schedule")]
KB[("Knowledge Base<br/>and Policies")]
end
subgraph OUT["Outcomes"]
O1(["Donation pledge captured"])
O2(["Volunteer slot booked"])
O3(["Program lead handoff"])
end
CALLER --> SIP --> STT --> NLU
NLU -->|Lookup| TOOLS
TOOLS <--> CRM
TOOLS <--> CAL
TOOLS <--> KB
NLU --> TTS --> SIP --> CALLER
NLU -->|Resolved| O1
NLU -->|Schedule| O2
NLU -->|Escalate| O3
style CALLER fill:#f1f5f9,stroke:#64748b,color:#0f172a
style NLU fill:#4f46e5,stroke:#4338ca,color:#fff
style O1 fill:#059669,stroke:#047857,color:#fff
style O2 fill:#0ea5e9,stroke:#0369a1,color:#fff
style O3 fill:#f59e0b,stroke:#d97706,color:#1f2937
from dataclasses import dataclass, field
from datetime import datetime, date, time
from typing import Optional
from enum import Enum
from uuid import uuid4
class EventCategory(Enum):
WORKSHOP = "workshop"
FESTIVAL = "festival"
MEETING = "meeting"
FUNDRAISER = "fundraiser"
SPORTS = "sports"
ARTS = "arts"
FAMILY = "family"
HEALTH = "health"
EDUCATION = "education"
class RegistrationStatus(Enum):
CONFIRMED = "confirmed"
WAITLISTED = "waitlisted"
CANCELLED = "cancelled"
@dataclass
class CommunityEvent:
event_id: str = field(default_factory=lambda: str(uuid4()))
title: str = ""
description: str = ""
category: EventCategory = EventCategory.MEETING
event_date: date = field(default_factory=date.today)
start_time: time = field(default_factory=lambda: time(10, 0))
end_time: time = field(default_factory=lambda: time(12, 0))
location: str = ""
organizer: str = ""
capacity: int = 50
registered_count: int = 0
waitlist_count: int = 0
is_free: bool = True
cost: float = 0.0
requires_registration: bool = True
age_group: str = "All ages"
is_cancelled: bool = False
@dataclass
class EventRegistration:
registration_id: str = field(default_factory=lambda: str(uuid4()))
event_id: str = ""
attendee_name: str = ""
attendee_email: str = ""
attendee_phone: str = ""
party_size: int = 1
status: RegistrationStatus = RegistrationStatus.CONFIRMED
registered_at: datetime = field(default_factory=datetime.utcnow)
reminder_sent: bool = False
Let community members search events by category, date range, or keywords.
from agents import function_tool
events_db: list[CommunityEvent] = []
registrations_db: list[EventRegistration] = []
@function_tool
async def search_events(
category: str = "all",
date_from: str = "",
date_to: str = "",
keyword: str = "",
age_group: str = "",
) -> dict:
"""Search for upcoming community events by category,
date, keyword, or age group."""
results = []
today = date.today()
for event in events_db:
if event.is_cancelled:
continue
if event.event_date < today:
continue
if category != "all" and event.category.value != category:
continue
if date_from and event.event_date < date.fromisoformat(date_from):
continue
if date_to and event.event_date > date.fromisoformat(date_to):
continue
if keyword and keyword.lower() not in event.title.lower():
continue
results.append({
"event_id": event.event_id,
"title": event.title,
"date": str(event.event_date),
"time": f"{event.start_time.strftime('%I:%M %p')} - "
f"{event.end_time.strftime('%I:%M %p')}",
"location": event.location,
"spots_remaining": max(event.capacity - event.registered_count, 0),
"is_free": event.is_free,
})
results.sort(key=lambda x: x["date"])
return {"events": results, "total_found": len(results)}
The registration tool enforces capacity limits and manages a waitlist for popular events.
@function_tool
async def register_for_event(
event_id: str,
attendee_name: str,
attendee_email: str,
attendee_phone: str = "",
party_size: int = 1,
) -> dict:
"""Register an attendee for a community event with
capacity enforcement and waitlist support."""
event = None
for e in events_db:
if e.event_id == event_id:
event = e
break
if not event:
return {"error": "Event not found"}
if event.is_cancelled:
return {"error": "This event has been cancelled"}
# Check for duplicate registration
for reg in registrations_db:
if (reg.event_id == event_id and
reg.attendee_email == attendee_email and
reg.status != RegistrationStatus.CANCELLED):
return {
"error": "Already registered for this event",
"registration_id": reg.registration_id,
}
spots_available = event.capacity - event.registered_count
if spots_available >= party_size:
status = RegistrationStatus.CONFIRMED
event.registered_count += party_size
else:
status = RegistrationStatus.WAITLISTED
event.waitlist_count += party_size
reg = EventRegistration(
event_id=event_id,
attendee_name=attendee_name,
attendee_email=attendee_email,
attendee_phone=attendee_phone,
party_size=party_size,
status=status,
)
registrations_db.append(reg)
return {
"status": status.value,
"registration_id": reg.registration_id,
"event": event.title,
"date": str(event.event_date),
"party_size": party_size,
"message": "Confirmed! You are registered."
if status == RegistrationStatus.CONFIRMED
else f"Event is full. You are #{event.waitlist_count} "
f"on the waitlist.",
}
@function_tool
async def send_event_reminder(event_id: str) -> dict:
"""Send reminders to all confirmed attendees for an event."""
event = next((e for e in events_db if e.event_id == event_id), None)
if not event:
return {"error": "Event not found"}
sent = 0
for reg in registrations_db:
if (reg.event_id == event_id and
reg.status == RegistrationStatus.CONFIRMED and
not reg.reminder_sent):
reg.reminder_sent = True
sent += 1
return {"event": event.title, "reminders_sent": sent}
from agents import Agent, Runner
event_agent = Agent(
name="Community Event Agent",
instructions="""You are a community event agent for the
Riverside Community Center. Your responsibilities:
1. Help people discover events by category, date, or interest
2. Register attendees with capacity enforcement
3. Manage waitlists when events are full
4. Send reminders before events
5. Provide event details including location and accessibility
6. For paid events, provide cost details before registration
7. If an event is cancelled, notify registered attendees
8. Suggest similar events when a requested one is full
9. Always confirm registration details before finalizing""",
tools=[
search_events,
register_for_event,
send_event_reminder,
],
)
result = Runner.run_sync(
event_agent,
"I am looking for family-friendly events this weekend. "
"Ideally something outdoors or arts-related.",
)
print(result.final_output)
When a confirmed attendee cancels, the agent should automatically promote the first person on the waitlist to confirmed status. Implement a cancel_registration tool that decrements the event's registered count, finds the earliest waitlisted registration, updates its status to confirmed, and sends a notification to the promoted attendee.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
Yes. Add a recurrence_rule field to the event model (such as "weekly" or "first_saturday"). A scheduled job generates individual event instances from the rule. The agent then treats each instance as a separate event with its own capacity and registration list, while displaying the series name for context.
Add an accessibility field to the event model that captures details like wheelchair access, sign language interpretation, and sensory-friendly accommodations. The search tool can filter by accessibility features, and the agent proactively mentions accessibility information when providing event details.
#CommunityEvents #EventManagement #NonprofitAI #AgenticAI #Python #LearnAI #AIEngineering

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
The 2026 desktop AI agent landscape — ServiceNow Project Arc, Anthropic Claude offerings, OpenAI agents, and Google Mariner. A buyer's map.
Step-by-step build of a working agent with the OpenAI Agents SDK — Agent class, tools, handoffs, tracing — plus an eval pipeline that catches regressions before merge.
An agentic-AI perspective on Anthropic Skills system, covering orchestration patterns, tool use, and how agent tooling fits production agent stacks.
Enterprise CIO Guide perspective on Comet's general-availability launch put an agentic browser in front of millions of consumers, and it works better than the demos suggested.
Enterprise CIO Guide perspective on Harvey AI's enterprise rollout numbers show legal agents have moved past the pilot stage at AmLaw 100 firms.
Enterprise CIO Guide perspective on Hippocratic AI's deployment numbers show healthcare voice agents are moving from pilot to production across major US health systems.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco