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

# Serverless Deployment

> Deploy agents to AWS Lambda, Google Cloud Functions, or Azure Functions with automatic environment detection.

[ref-agentserver]: /docs/server-sdks/reference/python/agents/agent-server

## Serverless overview

| Platform               | Runtime     | Entry Point      | Max Timeout          | Free Tier         |
| ---------------------- | ----------- | ---------------- | -------------------- | ----------------- |
| AWS Lambda             | Python 3.11 | `lambda_handler` | 15 min               | 1M requests/mo    |
| Google Cloud Functions | Python 3.11 | `main`           | 60 min (Gen 2)       | 2M invocations/mo |
| Azure Functions        | Python 3.11 | `main`           | 10 min (Consumption) | 1M executions/mo  |

**Language support for serverless:**

| Language   | AWS Lambda            | Google Cloud Functions | Azure Functions       |
| ---------- | --------------------- | ---------------------- | --------------------- |
| Python     | Yes                   | Yes                    | Yes                   |
| TypeScript | Yes (Node.js runtime) | Yes (Node.js runtime)  | Yes (Node.js runtime) |

**Benefits:**

* Auto-scaling
* Pay per invocation
* No server management
* High availability

## AWS Lambda

### Lambda handler

#### Python

`handler.py`:

```python
from signalwire import AgentBase, FunctionResult

class MyAgent(AgentBase):
    def __init__(self):
        super().__init__(name="my-agent")
        self.add_language("English", "en-US", "rime.spore")
        self.prompt_add_section("Role", "You are a helpful assistant.")
        self._setup_functions()

    def _setup_functions(self):
        @self.tool(
            description="Say hello to a user",
            parameters={
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Name of the person to greet"
                    }
                },
                "required": ["name"]
            }
        )
        def say_hello(args, raw_data):
            name = args.get("name", "World")
            return FunctionResult(f"Hello {name}!")

# Create agent instance outside handler for warm starts
agent = MyAgent()

def lambda_handler(event, context):
    """AWS Lambda entry point."""
    return agent.handle_serverless_request(event, context)
```

#### TypeScript

`handler.ts` (deploy as `handler.mjs` or ensure `package.json` has `"type": "module"` — `@signalwire/sdk` is ESM-only):

```typescript
import { AgentBase, FunctionResult } from '@signalwire/sdk';

const agent = new AgentBase({ name: "my-agent" });
agent.addLanguage({ name: "English", code: "en-US", voice: "rime.spore" });
agent.promptAddSection("Role", { body: "You are a helpful assistant." });

agent.defineTool({
  name: "say_hello",
  description: "Say hello to a user",
  parameters: {
    type: "object",
    properties: {
      name: { type: "string", description: "Name of the person to greet" }
    },
    required: ["name"]
  },
  handler: (args: Record<string, unknown>) => {
    const name = (args['name'] as string) || "World";
    return new FunctionResult(`Hello ${name}!`);
  }
});

export const handler = async (event: unknown, context: unknown) => {
  return agent.runServerless(event, context);
};
```

### Lambda requirements.txt (Python)

```text
signalwire-sdk>=1.0.15
```

### Lambda with API Gateway (Serverless Framework)

```yaml
## serverless.yml
service: signalwire-agent

provider:
  name: aws
  runtime: python3.11
  region: us-east-1
  environment:
    SWML_BASIC_AUTH_USER: ${env:SWML_BASIC_AUTH_USER}
    SWML_BASIC_AUTH_PASSWORD: ${env:SWML_BASIC_AUTH_PASSWORD}

functions:
  agent:
    handler: handler.lambda_handler
    events:
      - http:
          path: /
          method: any
      - http:
          path: /{proxy+}
          method: any
```

### Lambda request flow

<img class="diagram" src="https://fdr-prod-docs-files-public.s3.us-east-1.amazonaws.com/signalwire.docs.buildwithfern.com/d5008c379f7b25d6f746f1a71fec231d5e7b9419a3fc29491445e860dc027fdd/assets/images/sdks/diagrams/07_03_serverless_diagram1.webp?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIA6KXJSKKNFOCF7G4B%2F20260817%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260817T022717Z&X-Amz-Expires=604800&X-Amz-Signature=9806c9ea0f592722444a44d2ff9a97d23501670b031e30b0c1a40ec4fe075582&X-Amz-SignedHeaders=host&x-amz-checksum-mode=ENABLED&x-id=GetObject" alt="Lambda request flow diagram showing API Gateway, Lambda function, and SignalWire Cloud." />

## Google Cloud Functions

### Cloud Functions handler

#### Python

`main.py`:

```python
from signalwire import AgentBase, FunctionResult

class MyAgent(AgentBase):
    def __init__(self):
        super().__init__(name="my-agent")
        self.add_language("English", "en-US", "rime.spore")
        self.prompt_add_section("Role", "You are a helpful assistant.")
        self._setup_functions()

    def _setup_functions(self):
        @self.tool(
            description="Say hello to a user",
            parameters={
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Name of the person to greet"
                    }
                },
                "required": ["name"]
            }
        )
        def say_hello(args, raw_data):
            name = args.get("name", "World")
            return FunctionResult(f"Hello {name}!")

# Create agent instance outside handler for warm starts
agent = MyAgent()

def main(request):
    """Google Cloud Functions entry point."""
    return agent.handle_serverless_request(request)
```

#### TypeScript

`index.ts` (deploy as `.mjs` or ensure `package.json` has `"type": "module"` — `@signalwire/sdk` is ESM-only):

```typescript
import { AgentBase, FunctionResult, ServerlessAdapter } from '@signalwire/sdk';
import type { HttpFunction } from '@google-cloud/functions-framework';

const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
agent.promptAddSection('Role', { body: 'You are a helpful assistant.' });

agent.defineTool({
  name: 'say_hello',
  description: 'Say hello to a user',
  parameters: {
    type: 'object',
    properties: {
      name: { type: 'string', description: 'Name of the person to greet' },
    },
    required: ['name'],
  },
  handler: (args: Record<string, unknown>) => {
    return new FunctionResult(`Hello ${(args['name'] as string) || 'World'}!`);
  },
});

export const main: HttpFunction = ServerlessAdapter.createGcfHandler(agent.getApp());
```

### Cloud Functions requirements.txt (Python)

```text
signalwire-sdk>=1.0.15
functions-framework>=3.0.0
```

### Deploying to Cloud Functions (Gen 2)

```bash
gcloud functions deploy signalwire-agent \
  --gen2 \
  --runtime python311 \
  --trigger-http \
  --allow-unauthenticated \
  --entry-point main \
  --region us-central1 \
  --set-env-vars SWML_BASIC_AUTH_USER=user,SWML_BASIC_AUTH_PASSWORD=pass
```

## Azure Functions

### Azure Functions handler

#### Python

`function_app/__init__.py`:

```python
import azure.functions as func
from signalwire import AgentBase, FunctionResult

class MyAgent(AgentBase):
    def __init__(self):
        super().__init__(name="my-agent")
        self.add_language("English", "en-US", "rime.spore")
        self.prompt_add_section("Role", "You are a helpful assistant.")
        self._setup_functions()

    def _setup_functions(self):
        @self.tool(
            description="Say hello to a user",
            parameters={
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Name of the person to greet"
                    }
                },
                "required": ["name"]
            }
        )
        def say_hello(args, raw_data):
            name = args.get("name", "World")
            return FunctionResult(f"Hello {name}!")

# Create agent instance outside handler for warm starts
agent = MyAgent()

def main(req: func.HttpRequest) -> func.HttpResponse:
    """Azure Functions entry point."""
    return agent.handle_serverless_request(req)
```

#### TypeScript

`src/functions/agent.ts` (deploy as `.mjs` or set `"type": "module"` in `package.json` — `@signalwire/sdk` is ESM-only). This example uses the Azure Functions v3 programming model with `function.json` (shown below). The SDK's Azure helper follows that shape.

```typescript
import { AgentBase, FunctionResult, ServerlessAdapter } from '@signalwire/sdk';

const agent = new AgentBase({ name: 'my-agent' });
agent.addLanguage({ name: 'English', code: 'en-US', voice: 'rime.spore' });
agent.promptAddSection('Role', { body: 'You are a helpful assistant.' });

agent.defineTool({
  name: 'say_hello',
  description: 'Say hello to a user',
  parameters: {
    type: 'object',
    properties: {
      name: { type: 'string', description: 'Name of the person to greet' },
    },
    required: ['name'],
  },
  handler: (args: Record<string, unknown>) => {
    return new FunctionResult(`Hello ${(args['name'] as string) || 'World'}!`);
  },
});

// Azure Functions v3 entry point — `context.res` is populated by the adapter.
export default ServerlessAdapter.createAzureHandler(agent.getApp());
```

### Azure Functions requirements.txt (Python)

```text
azure-functions>=1.17.0
signalwire-sdk>=1.0.15
```

### function.json

```json
{
    "scriptFile": "__init__.py",
    "bindings": [
        {
            "authLevel": "anonymous",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req",
            "methods": ["get", "post"],
            "route": "{*path}"
        },
        {
            "type": "http",
            "direction": "out",
            "name": "$return"
        }
    ]
}
```

### host.json

```json
{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[4.*, 5.0.0)"
    }
}
```

## Testing serverless

### Local testing with swaig-test

```bash
## Simulate AWS Lambda
swaig-test handler.py --simulate-serverless lambda --dump-swml

## Simulate Google Cloud Functions
swaig-test main.py --simulate-serverless cloud_function --dump-swml

## Simulate Azure Functions
swaig-test function_app/__init__.py --simulate-serverless azure_function --dump-swml
```

### Testing deployed endpoints

```bash
## Test SWML output (replace with your endpoint and credentials)
curl -u username:password https://your-endpoint/

## Test SWAIG function
curl -u username:password -X POST https://your-endpoint/swaig \
    -H 'Content-Type: application/json' \
    -d '{"function": "say_hello", "argument": {"parsed": [{"name": "Alice"}]}}'
```

## Authentication

The SDK automatically enables HTTP Basic Authentication. You can:

1. **Let the SDK generate credentials** - Secure random credentials are created automatically
2. **Set your own credentials** - Via environment variables:

```bash
export SWML_BASIC_AUTH_USER=myuser
export SWML_BASIC_AUTH_PASSWORD=mypassword
```

## Force mode override

For testing, you can force a specific execution mode:

```python
## Force Lambda mode
agent.run(event={}, context=None, force_mode='lambda')

## Force Cloud Functions mode
agent.run(request, force_mode='google_cloud_function')

## Force Azure mode
agent.run(req, force_mode='azure_function')
```

## Serverless best practices

### Cold starts

* Keep dependencies minimal
* Initialize agent outside handler function
* Use provisioned concurrency for low latency

### Timeouts

* Set appropriate timeout (Lambda: up to 15 min)
* Account for external API calls
* Monitor and optimize slow functions

### Memory

* Allocate sufficient memory
* More memory = more CPU in Lambda
* Monitor memory usage

### State

* Design for statelessness
* Use external storage for persistent data
* Don't rely on local filesystem

## Multi-agent serverless

Deploy multiple agents with [AgentServer][ref-agentserver]:

```python
from signalwire import AgentBase, AgentServer

class SalesAgent(AgentBase):
    def __init__(self):
        super().__init__(name="sales-agent")
        self.add_language("English", "en-US", "rime.spore")

class SupportAgent(AgentBase):
    def __init__(self):
        super().__init__(name="support-agent")
        self.add_language("English", "en-US", "rime.spore")

server = AgentServer()
server.register(SalesAgent(), "/sales")
server.register(SupportAgent(), "/support")

def lambda_handler(event, context):
    """Lambda handler for multi-agent server"""
    return server.run(event, context)
```

## Environment detection

The SDK detects serverless environments automatically:

| Environment Variable          | Platform               |
| ----------------------------- | ---------------------- |
| `AWS_LAMBDA_FUNCTION_NAME`    | AWS Lambda             |
| `LAMBDA_TASK_ROOT`            | AWS Lambda             |
| `FUNCTION_TARGET`             | Google Cloud Functions |
| `K_SERVICE`                   | Google Cloud Functions |
| `GOOGLE_CLOUD_PROJECT`        | Google Cloud Functions |
| `AZURE_FUNCTIONS_ENVIRONMENT` | Azure Functions        |
| `FUNCTIONS_WORKER_RUNTIME`    | Azure Functions        |