By Sagar Shankaran, Founder of CallSphere
Build an AI agent that manages fundraising campaigns with real-time progress tracking, segmented donor communication, milestone notifications, and automated impact reporting for nonprofits.
Key takeaways
Fundraising campaigns depend on three things: knowing where you stand against your goal, communicating the right message to the right donors, and demonstrating impact after the campaign ends. An AI fundraising agent automates all three: real-time dashboards, segmented donor outreach, milestone notifications, and impact reports that connect donations to outcomes.
from dataclasses import dataclass, field
from datetime import datetime, date, timedelta
from typing import Optional
from enum import Enum
from uuid import uuid4
class DonorSegment(Enum):
MAJOR_DONOR = "major_donor"
MID_LEVEL = "mid_level"
GRASSROOTS = "grassroots"
FIRST_TIME = "first_time"
LAPSED = "lapsed"
@dataclass
class Campaign:
campaign_id: str = field(default_factory=lambda: str(uuid4()))
name: str = ""
goal_amount: float = 0.0
raised_amount: float = 0.0
donor_count: int = 0
start_date: date = field(default_factory=date.today)
end_date: date = field(
default_factory=lambda: date.today() + timedelta(days=30))
milestones: list[float] = field(
default_factory=lambda: [25.0, 50.0, 75.0, 100.0])
milestones_reached: list[float] = field(default_factory=list)
impact_metrics: dict = field(default_factory=dict)
@dataclass
class CampaignDonor:
donor_id: str = field(default_factory=lambda: str(uuid4()))
name: str = ""
email: str = ""
segment: DonorSegment = DonorSegment.GRASSROOTS
total_given_campaign: float = 0.0
has_been_thanked: bool = False
@dataclass
class CampaignGift:
gift_id: str = field(default_factory=lambda: str(uuid4()))
campaign_id: str = ""
amount: float = 0.0
gift_date: date = field(default_factory=date.today)
is_matching: bool = False
The agent monitors campaign progress in real time and detects when milestones are reached.
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 agents import function_tool
campaigns_db: dict[str, Campaign] = {}
campaign_donors: dict[str, list[CampaignDonor]] = {}
campaign_gifts: list[CampaignGift] = []
@function_tool
async def get_campaign_dashboard(campaign_id: str) -> dict:
"""Get real-time campaign progress dashboard."""
campaign = campaigns_db.get(campaign_id)
if not campaign:
return {"error": "Campaign not found"}
pct = (campaign.raised_amount / campaign.goal_amount * 100
if campaign.goal_amount > 0 else 0)
days_left = (campaign.end_date - date.today()).days
elapsed = max((date.today() - campaign.start_date).days, 1)
daily_rate = campaign.raised_amount / elapsed
projected = daily_rate * (campaign.end_date - campaign.start_date).days
new_milestones = [m for m in campaign.milestones
if pct >= m and m not in campaign.milestones_reached]
campaign.milestones_reached.extend(new_milestones)
return {
"campaign": campaign.name,
"raised": campaign.raised_amount,
"goal": campaign.goal_amount,
"percent": round(pct, 1),
"days_remaining": max(days_left, 0),
"on_track": projected >= campaign.goal_amount,
"new_milestones": new_milestones,
}
Segment donors so the agent can tailor messaging to each group.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
@function_tool
async def segment_campaign_donors(campaign_id: str) -> dict:
"""Segment donors for targeted campaign communication."""
donors = campaign_donors.get(campaign_id, [])
if not donors:
return {"error": "No donors found for this campaign"}
segments = {}
for donor in donors:
seg = donor.segment.value
if seg not in segments:
segments[seg] = {"count": 0, "total_raised": 0.0}
segments[seg]["count"] += 1
segments[seg]["total_raised"] += donor.total_given_campaign
unthanked = [d for d in donors
if d.total_given_campaign > 0 and not d.has_been_thanked]
return {
"segments": segments,
"unthanked_count": len(unthanked),
"total_donors": len(donors),
}
@function_tool
async def record_campaign_gift(
campaign_id: str,
donor_name: str,
donor_email: str,
amount: float,
is_matching: bool = False,
dedication: str = "",
) -> dict:
"""Record a new gift to a campaign and update progress."""
campaign = campaigns_db.get(campaign_id)
if not campaign:
return {"error": "Campaign not found"}
gift = CampaignGift(
campaign_id=campaign_id,
amount=amount,
is_matching=is_matching,
dedication=dedication,
)
campaign_gifts.append(gift)
campaign.raised_amount += amount
campaign.donor_count += 1
pct = campaign.raised_amount / campaign.goal_amount * 100
return {
"status": "recorded",
"gift_id": gift.gift_id,
"donor": donor_name,
"amount": amount,
"campaign_total": campaign.raised_amount,
"percent_of_goal": round(pct, 1),
"is_matching": is_matching,
}
After a campaign ends, the agent generates impact reports that connect donations to outcomes.
@function_tool
async def generate_impact_report(campaign_id: str) -> dict:
"""Generate an impact report for a completed campaign."""
campaign = campaigns_db.get(campaign_id)
if not campaign:
return {"error": "Campaign not found"}
gifts = [g for g in campaign_gifts if g.campaign_id == campaign_id]
gift_amounts = [g.amount for g in gifts]
avg_gift = sum(gift_amounts) / len(gift_amounts) if gift_amounts else 0
matching_total = sum(g.amount for g in gifts if g.is_matching)
return {
"campaign": campaign.name,
"goal": campaign.goal_amount,
"total_raised": campaign.raised_amount,
"total_donors": campaign.donor_count,
"total_gifts": len(gifts),
"average_gift": round(avg_gift, 2),
"matching_funds": matching_total,
"impact_metrics": campaign.impact_metrics,
"milestones_reached": campaign.milestones_reached,
}
from agents import Agent, Runner
fundraising_agent = Agent(
name="Fundraising Campaign Agent",
instructions="""You are a fundraising campaign manager agent.
1. Track campaign progress in real time against goals
2. Record gifts and update totals with milestone detection
3. Segment donors for targeted communication
4. Identify unthanked donors for follow-up
5. Generate impact reports after campaigns close
6. Flag campaigns behind pace with recovery ideas
7. Major donors get personal outreach, grassroots get
community-focused messaging
8. Always express gratitude — every gift matters""",
tools=[
get_campaign_dashboard,
segment_campaign_donors,
record_campaign_gift,
generate_impact_report,
],
)
result = Runner.run_sync(
fundraising_agent,
"Give me a dashboard update on our Spring campaign (ID: spring-2026). "
"We need to know if we are on track and which donor segments "
"need outreach. Also identify anyone who has not been thanked yet.",
)
print(result.final_output)
The agent calculates a daily giving rate by dividing total raised by the number of days elapsed. It then projects the total by multiplying the daily rate by the full campaign duration. If the projected total meets or exceeds the goal, the campaign is marked as on track. This simple linear projection works well for most campaigns, though giving-day events may need different models that account for last-day surges.
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.
When recording a gift, the agent accepts an is_matching flag. Matching gifts are tracked separately in the impact report so the organization can show donors how their individual gifts were amplified. The agent can also proactively inform donors about active matching opportunities by checking if a matching gift program is associated with the campaign.
A good impact report connects dollars to outcomes. Instead of just saying "$50,000 raised," it should say "$50,000 raised, providing 10,000 meals to families in our community." The impact_metrics field in the campaign model stores these conversion ratios (for example, $5 per meal), and the report multiplies total raised by the ratio to produce concrete outcome numbers that donors can connect with emotionally.
#Fundraising #NonprofitAI #CampaignManagement #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
Watch how CallSphere handles real customer calls, schedules appointments, and processes payments — live.