import { CodeTabs } from '../views/docs/CodeTabs';
import { Callout, NextLink } from '../views/docs/prose';

export const SIG_PY = `call.set_variable(key: str, value: Any) -> None
call.get_variable(key: str) -> Any`;

export const SIG_TS = `await call.setVariable(key: string, value: any): Promise<void>
await call.getVariable(key: string): Promise<any>`;

export const SET_GET_VARIABLE_EX_PY = `@agent.on_call_start
def on_call_start(call: guava.Call):
    # Variables seeded via call_phone(variables={...}) are readable immediately
    patient_name = call.get_variable("patient_name")
    call.reach_person(contact_full_name=patient_name)


@agent.on_reach_person
def on_reach_person(call: guava.Call, outcome: str):
    if outcome == "available":
        call.set_task(
            objective="Confirm the appointment and answer any questions.",
            on_complete=on_confirmed,
        )


@agent.on_task_complete("confirmed")
def on_confirmed(call: guava.Call):
    call.hangup()`;

export const SET_GET_VARIABLE_EX_TS = `agent.onCallStart(async (call: guava.Call) => {
  // Variables seeded via callPhone({ variables: {...} }) are readable immediately
  const patientName = await call.getVariable("patientName");
  await call.reachPerson(patientName);
});

agent.onReachPerson(async (call: guava.Call, outcome: string) => {
  if (outcome === "available") {
    await call.setTask({
      objective: "Confirm the appointment and answer any questions.",
    });
  }
});

agent.onTaskComplete("confirmed", async (call: guava.Call) => {
  await call.hangup();
});`;

## set\_variable() / get\_variable()

Call variables are provided as a convenient way to pass per-call data (patient name, account ID, etc.) between agent handlers.
Variables can be seeded when the call starts and read or updated at any point during the call.

<CodeTabs
  python={{ code: SIG_PY, filename: "signature" }}
  typescript={{ code: SIG_TS, filename: "signature" }}
/>

### Valid variable values

Variable values must be JSON-serializable: strings, numbers, booleans, `None`, and dicts/lists composed of those types.

### Seeding variables at call start

For the following types of calls, variables can be seeded at the start.

- **Outbound calls** — pass a `variables` dict to `call_phone()` / `callPhone()`
- **Campaigns** — each contact's `data` dict becomes that contact's variables

### Other ways to store call state

As an alternative to call variables, you can keep per-call state in an in-process dictionary keyed by `call.id`.

That said, we only recommend this for simple use cases. If your process restarts, any in-memory state will be lost.
For durable per-call state, use Redis or another session store keyed by `call.id`.

```python
r = redis.Redis()
call_state: dict[str, dict] = {}

@agent.on_call_start
def on_call_start(call: guava.Call):
    # In-memory — lost on process restart
    call_state[call.id] = {"stage": "intro"}

    # Redis — survives restarts
    r.set(f"call_state:{call.id}", json.dumps({"stage": "intro"}), ex=3600)
```


### Example

<CodeTabs
  python={{ code: SET_GET_VARIABLE_EX_PY, filename: "example.py" }}
  typescript={{ code: SET_GET_VARIABLE_EX_TS, filename: "example.ts" }}
/>


<NextLink section="add-info" label="add_info()" />
