## reach\_person()

For outbound calls, `reach_person()` handles the critical first step: confirming you have the right person on the line before proceeding. It automatically handles answering machines, gatekeepers, wrong numbers, and refusals.

```python
def reach_person(
    contact_full_name: str,
    *,
    greeting: str | None = None,
    voicemail_message: str | None = None,
    voicemail_hangup: bool = False,
    outcomes: list[ReachPersonOutcome] | None = None,
)
```

```typescript
reachPerson(
  contactFullName: string,
  options?: {
    greeting?: string;
    voicemailMessage?: string;
    voicemailHangup?: boolean;
    outcomes?: ReachPersonOutcome[];
  },
): Promise<void>
```

### What happens on the call

When `reach_person()` is invoked, the agent automatically:

1. **Greets** whoever answers and introduces itself (organization + purpose).
2. **Asks for the contact** by name. If someone else answered, asks to speak with or be transferred to the contact.
3. **Determines availability** and records the contact's availability in a `contact_availability` field.
4. **Fires `agent.on_reach_person`** with the outcome key. The five default outcomes are:
   - `"available"` — the intended contact is on the line.
   - `"unavailable"` — someone else or an IVR answered and the contact could not be reached.
   - `"voicemail"` — an answering machine or voicemail system was reached.
   - `"wrong_number"` — the number does not belong to the contact.
   - `"do_not_contact"` — the contact asked not to be called again.

If you provided custom `outcomes`, those are used instead.

### Voicemail handling

> **Warning:** `reach_person()` and `set_voicemail_action()` both handle voicemail and **cannot be used together**. If you set `voicemail_message` or `voicemail_hangup` on `reach_person()`, do not call `set_voicemail_action()` — and vice versa. Using both raises an error.

### Common mistake: redundant introductions

> **Warning:** By the time `on_reach_person` fires, the agent has already introduced itself and stated the purpose of the call. Do **not** re-introduce in the first task after `reach_person`.

```python
# WRONG — redundant introduction
@agent.on_reach_person
def on_reach_person(call: guava.Call, outcome: str):
    if outcome == "available":
        call.set_task("survey", checklist=[
            guava.Say("Hi, this is Grace from Acme Corp, I'm calling about..."),  # Already said this
            ...
        ])

# RIGHT — go straight to content
@agent.on_reach_person
def on_reach_person(call: guava.Call, outcome: str):
    if outcome == "available":
        call.set_task("survey", checklist=[
            guava.Say("I just have a few quick questions for you today."),
            ...
        ])
```
