***

title: InfoGatherer
description: Collect answers to a series of questions with confirmation support, dynamic question callbacks, and structured data output using the InfoGatherer prefab agent.
slug: /guides/info-gatherer
max-toc-depth: 3
---------------------

For a complete index of all SignalWire documentation pages, fetch https://signalwire.com/docs/llms.txt

InfoGatherer is a pre-built agent that collects answers to a series of questions. It handles the conversation flow automatically, including optional confirmation of critical answers and dynamic question selection.

### Basic Usage

<Tabs>
  <Tab title="Python">
    ```python
    from signalwire.prefabs import InfoGathererAgent

    agent = InfoGathererAgent(
        questions=[
            {"key_name": "full_name", "question_text": "What is your full name?"},
            {"key_name": "email", "question_text": "What is your email address?", "confirm": True},
            {"key_name": "reason", "question_text": "How can I help you today?"}
        ]
    )

    if __name__ == "__main__":
        agent.run()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript
    import { InfoGathererAgent } from 'signalwire-agents';

    const agent = new InfoGathererAgent({
      questions: [
        { keyName: 'full_name', questionText: 'What is your full name?' },
        { keyName: 'email', questionText: 'What is your email address?', confirm: true },
        { keyName: 'reason', questionText: 'How can I help you today?' },
      ],
    });

    agent.run();
    ```
  </Tab>
</Tabs>

### Question Format

| Field           | Type    | Required | Description                         |
| --------------- | ------- | -------- | ----------------------------------- |
| `key_name`      | string  | Yes      | Identifier for storing the answer   |
| `question_text` | string  | Yes      | The question to ask the user        |
| `confirm`       | boolean | No       | If true, confirm answer before next |

### Constructor Parameters

```python
InfoGathererAgent(
    questions=None,           # List of question dictionaries
    name="info_gatherer",     # Agent name
    route="/info_gatherer",   # HTTP route
    **kwargs                  # Additional AgentBase arguments
)
```

### Importing InfoGathererAgent

| Language   | Import                                                  |
| ---------- | ------------------------------------------------------- |
| Python     | `from signalwire.prefabs import InfoGathererAgent`      |
| TypeScript | `import { InfoGathererAgent } from 'signalwire-agents'` |

### Flow Diagram

<Frame caption="InfoGatherer conversation flow.">
  <img class="diagram" src="https://files.buildwithfern.com/signalwire.docs.buildwithfern.com/docs/28dcc8e214a40644b008d27283c7efc4c39223cb190c10b8d7f05ff74f6b56ea/assets/images/sdks/diagrams/09_01_info-gatherer_diagram1.webp" alt="Diagram showing the InfoGatherer flow from question presentation through answer collection and confirmation." />
</Frame>

### Built-in Functions

InfoGatherer provides these SWAIG functions automatically:

| Function          | Description                         |
| ----------------- | ----------------------------------- |
| `start_questions` | Begin the question sequence         |
| `submit_answer`   | Submit answer and get next question |

### Dynamic Questions

Instead of static questions, use a callback to determine questions at runtime:

```python
from signalwire.prefabs import InfoGathererAgent

def get_questions(query_params, body_params, headers):
    """Dynamically determine questions based on request"""
    question_set = query_params.get('type', 'default')

    if question_set == 'support':
        return [
            {"key_name": "name", "question_text": "What is your name?"},
            {"key_name": "issue", "question_text": "Describe your issue."},
            {"key_name": "urgency", "question_text": "How urgent is this?"}
        ]
    else:
        return [
            {"key_name": "name", "question_text": "What is your name?"},
            {"key_name": "message", "question_text": "How can I help?"}
        ]

# Create agent without static questions
agent = InfoGathererAgent()

# Set the callback for dynamic questions
agent.set_question_callback(get_questions)

if __name__ == "__main__":
    agent.run()
```

### Accessing Collected Data

The collected answers are stored in `global_data`:

```python
# In a SWAIG function or callback:
global_data = raw_data.get("global_data", {})
answers = global_data.get("answers", [])

# answers is a list like:
# [
#     {"key_name": "full_name", "answer": "John Doe"},
#     {"key_name": "email", "answer": "john@example.com"},
#     {"key_name": "reason", "answer": "Product inquiry"}
# ]
```

### Complete Example

```python
#!/usr/bin/env python3
# appointment_scheduler.py - Info gatherer for scheduling appointments
from signalwire.prefabs import InfoGathererAgent

agent = InfoGathererAgent(
    questions=[
        {"key_name": "name", "question_text": "What is your name?"},
        {"key_name": "phone", "question_text": "What is your phone number?", "confirm": True},
        {"key_name": "date", "question_text": "What date would you like to schedule?"},
        {"key_name": "time", "question_text": "What time works best for you?"},
        {"key_name": "notes", "question_text": "Any special notes or requests?"}
    ],
    name="appointment-scheduler"
)

# Add custom language
agent.add_language("English", "en-US", "rime.spore")

# Customize prompt
agent.prompt_add_section(
    "Brand",
    "You are scheduling appointments for Dr. Smith's office."
)

if __name__ == "__main__":
    agent.run()
```

### Implementation Notes

InfoGatherer uses `replace_in_history()` internally to keep the conversation history clean. Each question/answer exchange is replaced in the LLM history so that the conversation context stays focused and doesn't grow excessively with repetitive tool call entries. This is transparent to the user -- they experience a natural conversation flow.

### Best Practices

#### Questions

* Keep questions clear and specific
* Use confirm=true for critical data (email, phone)
* Limit to 5-7 questions max per session
* Order from simple to complex

#### key\_name Values

* Use descriptive, unique identifiers
* snake\_case convention recommended
* Match your backend/database field names

#### Dynamic Questions

* Use callbacks for multi-purpose agents
* Validate questions in callback
* Handle errors gracefully