***

title: Request Lifecycle
description: Trace the complete journey of a call through the SignalWire Agents SDK, from incoming call to conversation end.
slug: /guides/lifecycle
max-toc-depth: 3
---------------------

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

[security]: /docs/server-sdks/guides/security

### The Complete Call Flow

Understanding the request lifecycle helps you debug issues and optimize your agents. Here's the complete flow:

<Frame caption="Complete Call Lifecycle">
  <img class="diagram" src="https://files.buildwithfern.com/signalwire.docs.buildwithfern.com/docs/bbf3a20ebd6af2ba54fccbfb43ce018c6226ce527942de33d9184263e16394b1/assets/images/sdks/diagrams/02_04_lifecycle_diagram1.webp" alt="Complete call lifecycle." />
</Frame>

### Phase 1: Call Setup

When a call arrives at SignalWire:

<Frame caption="Call Setup">
  <img class="diagram" src="https://files.buildwithfern.com/signalwire.docs.buildwithfern.com/docs/40edd18624d3308db61c21d0a52a2674a7e8393372baf628fc057266d3842e44/assets/images/sdks/diagrams/02_04_lifecycle_diagram2.webp" alt="Call setup phase." />
</Frame>

**Key points:**

* SignalWire knows which agent to contact based on phone number configuration
* The request includes Basic Auth credentials
* POST is the default; GET requests are also supported for SWML retrieval

### Phase 2: SWML Generation

Your agent builds and returns the SWML document:

```python
## Inside AgentBase._render_swml()

def _render_swml(self, request_body=None):
    """Generate SWML document for this agent."""

    # 1. Build the prompt (POM or text)
    prompt = self._build_prompt()

    # 2. Collect all SWAIG functions
    functions = self._tool_registry.get_functions()

    # 3. Generate webhook URLs with security tokens
    webhook_url = self._build_webhook_url("/swaig")

    # 4. Assemble AI configuration
    ai_config = {
        "prompt": prompt,
        "post_prompt": self._post_prompt,
        "post_prompt_url": self._build_webhook_url("/post_prompt"),
        "SWAIG": {
            "defaults": {"web_hook_url": webhook_url},
            "functions": functions
        },
        "hints": self._hints,
        "languages": self._languages,
        "params": self._params
    }

    # 5. Build complete SWML document
    swml = {
        "version": "1.0.0",
        "sections": {
            "main": [
                {"answer": {}},
                {"ai": ai_config}
            ]
        }
    }

    return swml
```

### Phase 3: AI Conversation

Once SignalWire has the SWML, it executes the instructions:

<Frame caption="AI Conversation Loop">
  <img class="diagram" src="https://files.buildwithfern.com/signalwire.docs.buildwithfern.com/docs/db665277a117d0f7ed04c9cf86d27ce86b5233a2973822aef4ceb8d3233acef0/assets/images/sdks/diagrams/02_04_lifecycle_diagram3.webp" alt="AI conversation loop." />
</Frame>

**AI Parameters that control this loop:**

| Parameter               | Default | Purpose                             |
| ----------------------- | ------- | ----------------------------------- |
| `end_of_speech_timeout` | 500ms   | Wait time after user stops speaking |
| `attention_timeout`     | 15000ms | Max silence before AI prompts       |
| `inactivity_timeout`    | 30000ms | Max silence before ending call      |
| `barge_match_string`    | -       | Words that immediately interrupt AI |

### Phase 4: Function Calls

When the AI needs to call a function:

<Frame caption="SWAIG Function Call">
  <img class="diagram" src="https://files.buildwithfern.com/signalwire.docs.buildwithfern.com/docs/82227c86185ef93f23ed19e54f1fd169331da16c3e9b744513e0d7b9df20fb33/assets/images/sdks/diagrams/02_04_lifecycle_diagram4.webp" alt="SWAIG function call phase." />
</Frame>

### Phase 5: Call End

When the call ends, the post-prompt summary is sent:

<Frame caption="Call Ending">
  <img class="diagram" src="https://files.buildwithfern.com/signalwire.docs.buildwithfern.com/docs/68c13a82f7166605e56f1e4a8cd04be2782fc0dbfcdd0aa96e6ea0c3d9b0e196/assets/images/sdks/diagrams/02_04_lifecycle_diagram5.webp" alt="Call ending phase." />
</Frame>

### Handling Post-Prompt

Configure post-prompt handling in your agent:

| Language   | Set Post-Prompt                                   |
| ---------- | ------------------------------------------------- |
| Python     | `agent.set_post_prompt("Summarize this call...")` |
| TypeScript | `agent.setPostPrompt('Summarize this call...')`   |

<Tabs>
  <Tab title="Python">
    ```python
    from signalwire import AgentBase

    class MyAgent(AgentBase):
        def __init__(self):
            super().__init__(name="my-agent")

            self.set_post_prompt(
                "Summarize this call including: "
                "1) The caller's main question or issue "
                "2) How it was resolved "
                "3) Any follow-up actions needed"
            )

        def on_post_prompt(self, data):
            """Handle the call summary."""
            summary = data.get("post_prompt_data", {})
            call_id = data.get("call_id")
            self.log_call_summary(call_id, summary)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript
    agent.setPostPrompt(
      'Summarize this call including: 1) The caller\'s main question '
      + '2) How it was resolved 3) Any follow-up actions needed'
    );

    agent.onSummary((summary, rawData) => {
      console.log('Call summary:', summary);
    });
    ```
  </Tab>
</Tabs>

### Request/Response Headers

#### SWML Request (GET or POST /)

```http
GET / HTTP/1.1
Host: your-agent.com
Authorization: Basic c2lnbmFsd2lyZTpwYXNzd29yZA==
Accept: application/json
X-Forwarded-For: signalwire-ip
X-Forwarded-Proto: https
```

#### SWML Response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{"version": "1.0.0", "sections": {...}}
```

#### SWAIG Request (POST /swaig)

```http
POST /swaig HTTP/1.1
Host: your-agent.com
Authorization: Basic c2lnbmFsd2lyZTpwYXNzd29yZA==
Content-Type: application/json

{"action": "swaig_action", "function": "...", ...}
```

#### SWAIG Response

```http
HTTP/1.1 200 OK
Content-Type: application/json

{"response": "...", "action": [...]}
```

### Debugging the Lifecycle

#### View SWML Output

```bash
## See what your agent returns
curl -u signalwire:password http://localhost:3000/ | jq '.'

## Using swaig-test
swaig-test my_agent.py --dump-swml
```

#### Test Function Calls

```bash
## Call a function directly
swaig-test my_agent.py --exec get_balance --account_id 12345

## With verbose output
swaig-test my_agent.py --exec get_balance --account_id 12345 --verbose
```

#### Monitor Live Traffic

```python
from signalwire import AgentBase

class DebugAgent(AgentBase):
    def __init__(self):
        super().__init__(name="debug-agent")

    def on_swml_request(self, request_data=None, callback_path=None, request=None):
        """Called when SWML is requested."""
        if request:
            print(f"SWML requested from: {request.client.host}")
            print(f"Headers: {dict(request.headers)}")

    def on_swaig_request(self, function_name, args, raw_data):
        """Called before each SWAIG function."""
        print(f"Function called: {function_name}")
        print(f"Arguments: {args}")
        print(f"Call ID: {raw_data.get('call_id')}")
```

### Error Handling

#### SWML Errors

If your agent can't generate SWML:

```python
def _render_swml(self):
    try:
        return self._build_swml()
    except Exception as e:
        # Return minimal valid SWML
        return {
            "version": "1.0.0",
            "sections": {
                "main": [
                    {"answer": {}},
                    {"play": {"url": "https://example.com/error.mp3"}},
                    {"hangup": {}}
                ]
            }
        }
```

#### SWAIG Errors

If a function fails:

```python
def get_balance(self, args, raw_data):
    try:
        balance = self.lookup_balance(args.get("account_id"))
        return FunctionResult(f"Your balance is ${balance}")
    except DatabaseError:
        return FunctionResult(
            "I'm having trouble accessing account information right now. "
            "Please try again in a moment."
        )
    except Exception as e:
        # Log the error but return user-friendly message
        self.logger.error(f"Function error: {e}")
        return FunctionResult(
            "I encountered an unexpected error. "
            "Let me transfer you to a representative."
        )
```

### Next Steps

Now that you understand the complete lifecycle, let's look at how [security][security] works throughout this flow.