> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usebrainbase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# State Management and Persistence

# State Management and Persistence

Based automatically persists variables across conversation turns, allowing you to maintain context throughout a multi-turn conversation. Understanding how state works is essential for building stateful agents.

## The `state` Dictionary

The `state` dictionary is the primary way to store and retrieve data that should persist across conversation turns. It's automatically saved and restored between interactions.

**Usage:**

```python theme={null}
# Initialize state at the start of your flow
state = {}

# Store user information as you collect it
state["user_name"] = "John"
state["preferences"] = {"language": "en", "notifications": True}
state["order_items"] = []

# Add items to state throughout the conversation
state["order_items"].append({"item": "Taco", "quantity": 2})

# Access state later in the flow
total_items = len(state["order_items"])
say(f"You have {total_items} items in your cart.", exact=True)
```

## Variable Persistence Example

Here's a complete example showing how variables persist across conversation turns:

```python theme={null}
# First turn: Initialize and collect data
state = {}
say("Welcome! Let me help you place an order.")

loop:
    response = talk("What would you like to order?", True)
until "user provides their order":
    order = response.ask(
        question="Extract the items the user wants to order",
        example={"items": [{"name": "burger", "quantity": 1}]}
    )
    state["order"] = order
    state["order_step"] = "collecting_details"
    print(f"Order saved to state: {state['order']}")

# On subsequent turns, the state is automatically restored
# You can access state["order"] and continue from where you left off
```

<Note>
  Variables defined at the top level of your Based code (like `state = {}`) are automatically persisted across conversation turns. The session maintains the complete execution state, so your agent can pick up right where it left off.
</Note>

## Pre-populated State for Voice Calls

When your Based agent is deployed for voice, the `state` dictionary is automatically pre-populated with call metadata. This gives you immediate access to caller information without needing to ask for it.

### Inbound Voice Calls

For inbound calls, `state` is pre-populated with Twilio call data:

```python theme={null}
# Example state for an inbound voice call
state = {
    # Caller information
    'From': '+14154650216',
    'Caller': '+14154650216',
    'CallerCity': 'SAN FRANCISCO',
    'CallerState': 'CA',
    'CallerZip': '94904',
    'CallerCountry': 'US',
    
    # Called number information
    'To': '+14158738252',
    'Called': '+14158738252',
    'ToCity': 'POINT REYES STATION',
    'ToState': 'CA',
    'ToZip': '94956',
    'ToCountry': 'US',
    'CalledCity': 'POINT REYES STATION',
    'CalledState': 'CA',
    'CalledZip': '94956',
    'CalledCountry': 'US',
    
    # Call metadata
    'Direction': 'inbound',
    'CallStatus': 'ringing',
    'CallSid': 'CAe64d540d7f8d465128c3e128d4cfb6d8',
    'AccountSid': 'AC607f40827a8fce6eb9b4d9d67adbf425',
    'ApiVersion': '2010-04-01',
    'StirVerstat': 'TN-Validation-Passed-A',
    
    # Brainbase metadata
    'version': 'v2',
    'deploymentId': 'deploy_a05e0b20-87ed-440b-9cd4-0427cc812c41',
    'flowId': 'flow_86414fd8-f0b9-42d8-8fdf-e6d13daeec48',
    'workerId': 'worker_5e864909-61c0-4785-8622-3af76cc58783',
    'teamId': '581fdb69-309b-4e95-aa78-315d6a0ad0db',
    'phoneNumber': '+14158738252'
}
```

You can use this data to personalize the conversation:

```python theme={null}
# Access caller information directly from state
caller_city = state.get('CallerCity', 'your area')
caller_number = state.get('From', '')

say(f"Thanks for calling from {caller_city}!", exact=True)

# Use caller ID for lookups
customer = lookup_customer_by_phone(caller_number)
if customer:
    say(f"Welcome back, {customer['name']}!", exact=True)
```

### Outbound Voice Calls

For outbound calls, `state` includes all the same call metadata plus an `outbound_data` field containing the data that triggered the call:

```python theme={null}
# Example state for an outbound voice call
state = {
    # Standard call metadata (same as inbound)
    'Direction': 'outbound',
    'From': '+14158738252',
    'To': '+14154650216',
    'CallStatus': 'in-progress',
    # ... other Twilio fields ...
    
    # Custom data that triggered the call
    'outbound_data': {
        'first_name': 'John',
        'last_name': 'Smith',
        'appointment_date': '2024-03-15',
        'appointment_time': '2:30 PM',
        'doctor_name': 'Dr. Johnson'
        # ... any other data you included when initiating the call
    }
}
```

Use `outbound_data` to personalize outbound calls:

```python theme={null}
# Access the data that triggered this outbound call
data = state.get('outbound_data', {})
first_name = data.get('first_name', 'there')
appointment_date = data.get('appointment_date', '')
appointment_time = data.get('appointment_time', '')

say(f"Hi {first_name}, this is a reminder about your appointment on {appointment_date} at {appointment_time}.", exact=True)
```

<Note>
  The `outbound_data` field contains whatever data you pass when initiating the outbound call through the API or trigger. This allows you to include any context needed for the conversation, such as customer details, appointment information, order numbers, etc.
</Note>
