**TL;DR:** Include tentative events and manual holds in every availability check, and read each interviewer's calendar directly instead of relying on the ATS schedule view. The double booking happened because the agent checked a cache that never contained the recruiter's manually placed hold. Treat every tentative hold as a real commitment until a human says otherwise.

```text
interview scheduler double-booked the hiring manager  -  the agent didn't see the tentative hold the recruiter placed manually in Greenhouse
```

1. Query the hiring manager's calendar for the candidate's window with tentative status explicitly requested, not just confirmed events.
   Expected: the response lists the recruiter's manual hold with status tentative alongside confirmed meetings.
2. Re-run the candidate's booked slot against that full busy list.
   Expected: the overlap shows up, confirming the hold was bookable time the agent missed.
3. Change the scheduler to check free/busy across each interviewer's calendar directly before proposing or confirming any slot.
   Expected: a dry-run slot returns "busy" when a tentative hold overlaps.
4. Add a guardrail: the agent never books over a manual hold without flagging the recruiter for a decision.
   Expected: in a test with a hold present, the agent pauses and asks instead of booking.
5. After fixing, ask the recruiter whether the old hold is still needed and release or convert it.
   Expected: the manager's calendar shows one clean event for the real interview.

## Use this when
- The agent books interviews through calendar APIs while humans also place holds in Greenhouse or on calendars.
- Double bookings appear where the calendar "looked free" to the agent.
- The ATS schedule view and the calendar disagree about availability.
- Recruiters place tentative holds manually outside the agent's workflow.

## Not for this skill when
- The ATS is the sole system of record and all holds live inside it.
- The conflict is a race between two agent workers, not a missed manual hold (see the panel-slot race-condition skill).
- The calendar data itself is wrong or syncing late from the provider.

## Variant phrasings
- scheduling agent booked over a tentative event it could not see
- hiring manager got double booked by the interview scheduler
- agent ignored a soft hold the recruiter placed manually
- interview landed on a manually blocked calendar slot

## Why it happens
Calendar availability checks commonly default to confirmed events, and many scheduler implementations read an ATS-side schedule cache rather than each person's live calendar. A tentative hold placed manually in Greenhouse or on the calendar is a real event the agent's query filtered out. Two writers (the agent and the recruiter) with no shared lock will keep colliding until the agent sees what the human sees.

## Edge cases
- Holds that outlived their purpose: a tentative block from a cancelled loop still reads as busy. Sweep for stale holds weekly.
- Interviewers who never decline stale invites: the tentative event never clears. Treat untouched tentatives older than a few days as suspect and confirm with a human.
- All-day tentative blocks: a full-day hold reads as busy for every slot. Confirm whether it is a real out-of-office before treating the whole day as blocked.
- The recruiter deletes the hold after the agent already routed around it: re-check availability before finalizing, since the freed slot may be the best one.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_JZfhsl-lxoXYIh9m_I6M1A
