Why AI Applications Need Provider-Aware Scheduling
AI applications that help users access professional services — mental health, legal advice, healthcare, coaching — face a scheduling problem that standard calendar tools cannot solve. The problem is not finding an open time slot. The problem is finding the right professional given a customer need, then booking a slot with them, atomically, without double-booking. A calendar lookup API answers "when is this person free?" An AI application needs to answer "who should handle this, and when are they free?" That is a different question entirely.
What a Calendar API Cannot Do
When an AI assistant receives "I need a Spanish-speaking therapist for virtual sessions next week," it faces six distinct questions before a booking can happen:
- Which professionals are eligible for this request? (specialty, language, modality)
- Which ones are currently accepting new clients?
- Which ones are available during the requested window?
- How should options be ranked and scored?
- How do we explain the recommendation? ("Why this therapist and not the others?")
- How do we prevent double-bookings when multiple customers are being matched concurrently?
A calendar API answers none of these except question 3 — and only for a specific calendar you already have credentials for. You would need to query each provider's calendar individually, which does not scale across a network of 50–200 professionals.
The Naive Alternative: What It Looks Like in Practice
Without a resolution API, teams typically build something like this:
// ❌ The naive approach — don't do this
async function findTherapist(constraints: CustomerConstraints) {
const allProviders = await db.getProviders();
// Step 1: Manual eligibility filtering
const eligible = allProviders.filter((p) =>
p.languages.some((l) => constraints.languageCodes.includes(l)) &&
p.specialties.some((s) => constraints.specialtyCodes.includes(s)) &&
p.modalities.includes(constraints.modality) &&
p.acceptingNewClients
);
// Step 2: Query every eligible provider's calendar — sequentially
const results = [];
for (const provider of eligible) {
try {
const slots = await calendarApi.getSlots(provider.calendarId, constraints.dateRange);
results.push({ provider, slots });
} catch (e) {
// Calendar API down? Provider just marked unavailable? Skip silently.
}
}
// Step 3: Sort by... something? No scoring logic.
const sorted = results.filter((r) => r.slots.length > 0);
// Step 4: No hold mechanism. Hope two customers don't pick the same slot simultaneously.
return sorted[0];
}
This approach has several problems:
- Slow: Sequential calendar queries add up. 20 eligible providers Ă— 200ms each = 4 seconds minimum.
- Fragile: Each provider's calendar integration is a separate failure surface.
- No ranking logic: Returning the first result is not the same as returning the best result.
- No explanations: You cannot tell the user why this provider was selected or why others were excluded.
- Race conditions: No hold mechanism means two customers can book the same slot simultaneously.
- Compliance gaps: In regulated contexts, the eligibility decision is auditable — your manual filter loop is not.
The Provider-Aware Approach
Here is the same scenario using Orita's resolution API. The customer's request is translated directly into constraints:
import Orita from "orita-sdk";
const orita = new Orita({ platformKey: process.env.ORITA_PLATFORM_KEY });
// The AI assistant extracts these constraints from natural language
// "I need a Spanish-speaking therapist for virtual sessions next week"
const resolution = await orita.resolveScheduling({
constraints: {
languageCodes: { anyOf: ["es"] },
specialtyCodes: { anyOf: ["CBT", "DBT", "general-therapy"] },
modalityCodes: { anyOf: ["virtual"] },
acceptingNewClients: true,
},
dateRange: {
start: "2026-08-04T00:00:00Z",
end: "2026-08-08T23:59:59Z",
},
timezone: "America/New_York",
idempotencyKey: "chat-session-88abc",
});
The raw HTTP call:
POST /api/v1/resolutions
Authorization: Bearer <platform-key>
Idempotency-Key: chat-session-88abc
Content-Type: application/json
{
"constraints": {
"languageCodes": { "anyOf": ["es"] },
"specialtyCodes": { "anyOf": ["CBT", "DBT", "general-therapy"] },
"modalityCodes": { "anyOf": ["virtual"] },
"acceptingNewClients": true
},
"dateRange": {
"start": "2026-08-04T00:00:00Z",
"end": "2026-08-08T23:59:59Z"
},
"timezone": "America/New_York"
}
Walking Through the Response
{
"resolutionId": "res_01j2k3m4n5p6q7r8",
"status": "resolved",
"summary": {
"providersScanned": 143,
"eligibleProviders": 8,
"exclusionReasons": {
"languageNotMatched": 102,
"missingSpecialty": 27,
"notAcceptingClients": 6,
"noAvailability": 0
}
},
"options": [
{
"optionId": "opt_aabbcc112233",
"slotId": "slot_xxyyzz445566",
"provider": {
"providerId": "prov_88ff99ee00dd",
"name": "Dr. Marina Vidal",
"specialties": ["CBT", "trauma-focused"],
"languages": ["es", "en"],
"modalities": ["virtual"]
},
"slot": {
"start": "2026-08-05T14:00:00Z",
"end": "2026-08-05T15:00:00Z",
"timezone": "America/New_York"
},
"score": 0.94,
"reason": "Matches all constraints. CBT specialty confirmed. Spanish primary language. Virtual sessions available.",
"matchedConstraints": ["languageCodes", "specialtyCodes", "modalityCodes", "acceptingNewClients"]
}
]
}
The AI assistant can now give the user a direct, explainable answer:
"I found 8 therapists who speak Spanish and offer virtual CBT sessions next week. The top match is Dr. Marina Vidal — she specializes in CBT, her primary language is Spanish, and she has availability on Tuesday at 2 PM Eastern. Want me to hold that slot for you?"
The reason and matchedConstraints fields come directly from the API. No post-processing required.
Completing the Flow: Hold and Confirm
Once the user confirms, the assistant holds the slot and then completes the booking atomically:
// Hold for 5 minutes while the user decides
await orita.holdOption(
resolution.resolutionId,
resolution.options[0].optionId,
{ ttlSeconds: 300 }
);
// User said yes — confirm
const booking = await orita.confirmResolution(resolution.resolutionId, {
optionId: resolution.options[0].optionId,
customer: {
name: "Ana GarcĂa",
email: "ana@example.com",
timezone: "America/New_York",
},
});
The hold prevents another concurrent intake flow from booking the same slot between the user seeing the option and confirming it. This is not a theoretical race condition — it happens in production at any non-trivial scale.
The Resolution Engine You'd Otherwise Build Yourself
To build this from scratch, you would need to write and maintain:
| Component | What it does | |---|---| | Provider eligibility filter | Match customer constraints against provider attributes | | Parallel availability checks | Query multiple provider calendars concurrently | | Conflict detection | Prevent double-bookings across concurrent sessions | | Scoring model | Rank (provider, slot) pairs by relevance | | Explanation generation | Produce human-readable reasons for each option | | Exclusion audit log | Track why providers were excluded, for compliance | | Atomic confirmation | Convert a hold into a booking without race conditions | | Idempotency layer | Prevent duplicate resolutions on retry |
Each of these is a non-trivial engineering problem. Together, they represent several weeks of work — and ongoing maintenance as your provider network grows and eligibility rules change.
The resolution API encapsulates all of it behind a single endpoint.
When Orita Is Not the Right Solution
- Single provider: If your AI assistant always books with one specific professional, you do not need resolution — use
POST /api/v1/bookingsdirectly. - No professional network: If your AI handles scheduling for users' personal calendars (meetings, reminders), use a calendar API. Orita is for platforms that manage professional service providers.
- Provider is always pre-selected: If users choose their provider before talking to the AI (from a profile page, for example), resolution adds a step that is not needed.
- No eligibility complexity: If all providers in your network are interchangeable and the only variable is availability, any slot API is sufficient.
Next Steps
- What Is a Provider Resolution API? — foundational concepts
- How a Multi-Provider Scheduling API Works — the resolution pipeline in detail
- Known-Host Scheduling vs. Provider Resolution — choosing the right model
- See a live end-to-end resolution in the interactive demo
