AI agents and group scheduling API design

    Group Scheduling API Concurrency: Stop Calendar Races Before the Event Write

    By Tevye Krynski16 min read

    The slot was free when the agent proposed it. That sentence is where duplicate bookings begin. A customer says yes at 10:04. A required engineer accepts another meeting at 10:05. The organizer approves at 10:06. The event write succeeds but the response times out. Then two workers retry. Calendar Tetris has become a distributed-systems problem with human inboxes attached.

    Build a compare-and-commit booking path in eight steps

    Use one sixty-minute cross-company kickoff with four required people, one optional observer, Google and Microsoft calendars, and one required participant who supplies availability without connecting a calendar. Generate a valid proposal, change a required calendar before approval, deliver approval twice, and time out the first event-write response.

    1. 1

      Freeze an authorized meeting-intent revision

      Store meeting_request_id, revision, authenticated organizer, purpose, duration, bounded date window, deadline, IANA time zone, required and optional people, approved substitutes, working-hour rules, preferences, outreach policy, approval mode, organizer calendar, and allowed event actions. Every availability read, reply, proposal, and booking command must point to this revision.
      • Required attendance, consent, and date boundaries cannot change through a slot approval.
      • Preferences are scored only after hard constraints pass.
      • Booking, rescheduling, and cancellation authority remain separate.
    2. 2

      Build a versioned availability evidence set

      Read approved Google and Microsoft free/busy for connected calendars. Store provider, account, retrieval time, requested interval, source cursor or change marker when available, response error, IANA zone, and a hash or internal version for the normalized busy set. Do not copy event titles, descriptions, or unrelated attendees into the scheduling record.
      • Missing access and provider errors are unknown, not free.
      • Every required participant has evidence with an explicit freshness rule.
      • The same normalized input produces the same evidence version.
    3. 3

      Join conversational availability without pretending it is live sync

      For an unconnected participant, send a consent-safe request with purpose, duration, bounded date range, local-time wording, response deadline, reminder cap, and opt-out path. Parse bounded windows, corrections, decline, and zone into typed evidence tied to sender, channel message ID, meeting revision, received time, and declared expiry.
      • A duplicate reply is suppressed by message and request identity.
      • Ambiguous dates or zones produce one narrow clarification instead of a guess.
      • A correction invalidates every proposal derived from the superseded windows.
    4. 4

      Issue proposals as expiring evidence leases

      Intersect all required people, then rank optional attendance and preferences. Create a proposal_id containing meeting revision, exact slot, attendee roles, evidence versions, generated time, expiry, approval requirement, and status. The proposal is a claim that the evidence supported the slot at generation time. It is not a calendar hold and not a booking.
      • The approval surface shows proposal expiry and the source meeting revision.
      • A later calendar change or participant correction can revoke the lease.
      • No-overlap returns the smallest duration, date, attendee, or preference decision.
    5. 5

      Re-read required availability at the commit boundary

      After approval and immediately before side effects, fetch current required free/busy and check reply evidence expiry. Compare the normalized evidence versions with those behind the proposal. If the proposed interval is still free and policy permits freshness-only changes elsewhere, continue. If the interval or any hard rule changed, invalidate the proposal and recompute.
      • An approval never overrides a new required conflict.
      • Optional changes follow declared policy and stay visible in the final attendee decision.
      • The preflight result and comparison reason are persisted with the booking attempt.
    6. 6

      Acquire one commit right and write idempotently

      Use a short meeting-level commit lease or transactional state transition so only one worker can move the approved proposal into booking_in_progress. Send one stable idempotency key derived from meeting request, revision, and proposal. Persist provider request correlation before the call and provider event identifiers as soon as they are known.
      • Repeated approval, queue delivery, or tool invocation returns the same operation.
      • A lock expiry cannot authorize a second write while the first outcome is unknown.
      • The event body is rebuilt from authorized durable state, not model memory.
    7. 7

      Reconcile uncertainty before retrying

      A timeout means unknown, not failed. Search by stored provider correlation, organizer calendar, idempotency marker, attendee set, and bounded time. If the event exists, attach it to the operation and continue verification. If absence is proven, retry under the same key. If provider state is conflicting, stop with a bounded recovery task instead of creating another event.
      • Transport errors and provider rejections have different reason codes.
      • Retries preserve meeting revision, actor, approval, and side-effect history.
      • An operator can resolve uncertain state without reading private event content.
    8. 8

      Verify invitations and emit the concurrency trace

      Read back the canonical event and verify final URL-independent provider identity, slot, IANA zone, organizer, every required participant, optional-attendee decision, and invitation state. Trace evidence reads, version comparison, proposal expiry, approval, lock owner, write attempt, timeout, reconciliation, duplicate suppression, and completion. Finish only with one verified booking or a bounded exception.
      • A successful HTTP response alone is not booking proof.
      • The final result explains whether a proposal changed because of freshness, policy, or provider state.
      • The calling agent receives one terminal outcome it can act on safely.

    Free at read time is not free at commit time

    Calendar providers can return current availability, changes, and event writes. They do not give your cross-company workflow one distributed transaction across every calendar and human reply. Time passes between proposal and approval. That gap is the race window.

    The practical answer is not to lock everyone’s calendar for every proposal. It is to make evidence versions and expiry explicit, keep the proposal cheap to invalidate, and run a fresh required-attendee check at the side-effect boundary.

    A tentative hold moves the race; it does not erase it

    A hold can reduce collisions when every calendar owner has authorized it. It also creates new work: disclosure, expiry, cleanup, decline handling, duplicate suppression, and the risk that a tentative event looks confirmed. External participants may not permit a hold at all.

    Use holds as one policy-controlled tool, not as your concurrency model. The durable model is still meeting revision, evidence set, proposal lease, commit right, idempotent write, reconciliation, and read-back proof.

    Links, polls, sync, and draft-only assistants stop before compare-and-commit

    A booking link can check configured host availability when an invitee selects. A poll records votes. A sync utility reports conflicts. An AI assistant can send ‘does Tuesday still work?’ A calendar API can read and write. None by itself owns the hard meeting from required people and missing availability through approval, fresh preflight, safe booking, invitations, and recovery.

    Scheduling execution carries the authorized intent across those boundaries. That is the layer WonderCal is moving toward: an agent should not return a stale slot or a drafted message. It should return a verified booking or a precise exception.

    Run the approval-race acceptance test

    Generate a proposal from current Google, Microsoft, and conversational evidence. Add a conflict to one required calendar, correct the unconnected participant’s window, approve the original proposal twice, let two workers race, and time out the provider response after it may have created the event.

    Pass when stale versions invalidate the old proposal, valid unchanged replies survive, only one worker owns commit, the uncertain event is reconciled, and one invitation is verified. Fail when approval is treated as proof of current availability or a timeout triggers a blind second write.

    Compare booking approaches at the race window

    The critical moment sits between ‘this slot works’ and ‘everyone is invited.’ Compare which method owns freshness, concurrency, uncertain writes, and final proof.

    Execution completion

    Read availability, then write an event

    Covers provider reads and writes while proposal state, approval, and recovery remain application work.

    Booking link, poll, or custom holds

    Can complete a configured selection or reduce collisions; wider participant coordination may remain human-owned.

    WonderCal execution direction

    Target path carries one authorized proposal through fresh preflight and verified invitations.

    Cross-company reach

    Read availability, then write an event

    Depends on calendar access the application has across providers and tenants.

    Booking link, poll, or custom holds

    Shared surfaces reach external people, with hold and response state joined separately.

    WonderCal execution direction

    Designed for required and optional people across Google, Microsoft, and unconnected calendars.

    Optional-sync fallback

    Read availability, then write an event

    A calendar read cannot supply availability for a participant who declines connection.

    Booking link, poll, or custom holds

    Poll or form responses can fill gaps, but expiry and correction handling still need state.

    WonderCal execution direction

    Target model versions bounded conversational windows beside connected free/busy.

    Recovery and observability

    Read availability, then write an event

    The team must add evidence versions, locks, idempotency, reconciliation, and read-back verification.

    Booking link, poll, or custom holds

    Depends on the selected product plus custom glue around holds, timeouts, and changed calendars.

    WonderCal execution direction

    Target release should expose proposal evidence, commit ownership, retries, provider state, and final proof.

    Time to ship

    Read availability, then write an event

    Fast for a demo and incomplete once approval latency and uncertain writes enter the path.

    Booking link, poll, or custom holds

    Useful for stable meeting shapes; hard-meeting edge cases still define the integration burden.

    WonderCal execution direction

    Worth adopting when the live contract removes race-handling code without hiding booking state.

    Frequently asked questions

    What is a calendar race condition in a group scheduling API?

    It occurs when availability changes after a slot is read or proposed but before the event is committed. The API must detect stale required-attendee evidence, invalidate the proposal, recompute, and avoid writing an event from an old snapshot.

    Should a scheduling API place tentative holds on every proposed slot?

    Not by default. Holds require authority, disclosure, expiry, cleanup, and participant-safe wording. They can reduce some collisions, but the API still needs versioned evidence, commit control, idempotency, reconciliation, and final verification.

    How do idempotency and concurrency control differ?

    Concurrency control decides which worker may commit the approved proposal. Idempotency makes repeated delivery of that same command return the original operation instead of another event. A production booking path needs both.

    How should an AI scheduling agent handle an event-write timeout?

    Treat the result as uncertain. Reconcile provider state using stored correlation and event markers before retrying. Reuse the same idempotency key, preserve the approval and meeting revision, and stop for a bounded recovery decision if absence cannot be proven.

    Where can developers review WonderCal’s group scheduling direction?

    Review WonderCal for AI agents. Confirm the live availability freshness, participant fallback, approval, idempotency, concurrency, reconciliation, observability, and invitation-verification contract before production use.

    Primary sources

    Related WonderCal reading

    Close the race window before booking

    Test WonderCal and your own integration with a stale proposal, duplicate approval, two workers, an uncertain provider write, and one required outcome: a single verified invitation.

    Review WonderCal for AI agents