Serverless Deployment

View as MarkdownOpen in Claude

Serverless overview

PlatformRuntimeEntry PointMax TimeoutFree Tier
AWS LambdaPython 3.11lambda_handler15 min1M requests/mo
Google Cloud FunctionsPython 3.11main60 min (Gen 2)2M invocations/mo
Azure FunctionsPython 3.11main10 min (Consumption)1M executions/mo

Language support for serverless:

LanguageAWS LambdaGoogle Cloud FunctionsAzure Functions
PythonYesYesYes

| 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

handler.py:

1from signalwire import AgentBase, FunctionResult
2
3class MyAgent(AgentBase):
4 def __init__(self):
5 super().__init__(name="my-agent")
6 self.add_language("English", "en-US", "rime.spore")
7 self.prompt_add_section("Role", "You are a helpful assistant.")
8 self._setup_functions()
9
10 def _setup_functions(self):
11 @self.tool(
12 description="Say hello to a user",
13 parameters={
14 "type": "object",
15 "properties": {
16 "name": {
17 "type": "string",
18 "description": "Name of the person to greet"
19 }
20 },
21 "required": ["name"]
22 }
23 )
24 def say_hello(args, raw_data):
25 name = args.get("name", "World")
26 return FunctionResult(f"Hello {name}!")
27
28# Create agent instance outside handler for warm starts
29agent = MyAgent()
30
31def lambda_handler(event, context):
32 """AWS Lambda entry point."""
33 return agent.handle_serverless_request(event, context)

Lambda requirements.txt (Python)

signalwire>=1.0.15

Lambda with API Gateway (Serverless Framework)

1## serverless.yml
2service: signalwire-agent
3
4provider:
5 name: aws
6 runtime: python3.11
7 region: us-east-1
8 environment:
9 SWML_BASIC_AUTH_USER: ${env:SWML_BASIC_AUTH_USER}
10 SWML_BASIC_AUTH_PASSWORD: ${env:SWML_BASIC_AUTH_PASSWORD}
11
12functions:
13 agent:
14 handler: handler.lambda_handler
15 events:
16 - http:
17 path: /
18 method: any
19 - http:
20 path: /{proxy+}
21 method: any

Lambda request flow

Lambda request flow diagram showing API Gateway, Lambda function, and SignalWire Cloud.
Lambda Request Flow

Google Cloud Functions

Cloud Functions handler

main.py:

1from signalwire import AgentBase, FunctionResult
2
3class MyAgent(AgentBase):
4 def __init__(self):
5 super().__init__(name="my-agent")
6 self.add_language("English", "en-US", "rime.spore")
7 self.prompt_add_section("Role", "You are a helpful assistant.")
8 self._setup_functions()
9
10 def _setup_functions(self):
11 @self.tool(
12 description="Say hello to a user",
13 parameters={
14 "type": "object",
15 "properties": {
16 "name": {
17 "type": "string",
18 "description": "Name of the person to greet"
19 }
20 },
21 "required": ["name"]
22 }
23 )
24 def say_hello(args, raw_data):
25 name = args.get("name", "World")
26 return FunctionResult(f"Hello {name}!")
27
28# Create agent instance outside handler for warm starts
29agent = MyAgent()
30
31def main(request):
32 """Google Cloud Functions entry point."""
33 return agent.handle_serverless_request(request)

Cloud Functions requirements.txt (Python)

signalwire>=1.0.15
functions-framework>=3.0.0

Deploying to Cloud Functions (Gen 2)

$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

function_app/__init__.py:

1import azure.functions as func
2from signalwire import AgentBase, FunctionResult
3
4class MyAgent(AgentBase):
5 def __init__(self):
6 super().__init__(name="my-agent")
7 self.add_language("English", "en-US", "rime.spore")
8 self.prompt_add_section("Role", "You are a helpful assistant.")
9 self._setup_functions()
10
11 def _setup_functions(self):
12 @self.tool(
13 description="Say hello to a user",
14 parameters={
15 "type": "object",
16 "properties": {
17 "name": {
18 "type": "string",
19 "description": "Name of the person to greet"
20 }
21 },
22 "required": ["name"]
23 }
24 )
25 def say_hello(args, raw_data):
26 name = args.get("name", "World")
27 return FunctionResult(f"Hello {name}!")
28
29# Create agent instance outside handler for warm starts
30agent = MyAgent()
31
32def main(req: func.HttpRequest) -> func.HttpResponse:
33 """Azure Functions entry point."""
34 return agent.handle_serverless_request(req)

Azure Functions requirements.txt (Python)

azure-functions>=1.17.0
signalwire>=1.0.15

function.json

1{
2 "scriptFile": "__init__.py",
3 "bindings": [
4 {
5 "authLevel": "anonymous",
6 "type": "httpTrigger",
7 "direction": "in",
8 "name": "req",
9 "methods": ["get", "post"],
10 "route": "{*path}"
11 },
12 {
13 "type": "http",
14 "direction": "out",
15 "name": "$return"
16 }
17 ]
18}

host.json

1{
2 "version": "2.0",
3 "extensionBundle": {
4 "id": "Microsoft.Azure.Functions.ExtensionBundle",
5 "version": "[4.*, 5.0.0)"
6 }
7}

Testing serverless

Local testing with swaig-test

$## 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

$## 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:
$export SWML_BASIC_AUTH_USER=myuser
$export SWML_BASIC_AUTH_PASSWORD=mypassword

Force mode override

For testing, you can force a specific execution mode:

1## Force Lambda mode
2agent.run(event={}, context=None, force_mode='lambda')
3
4## Force Cloud Functions mode
5agent.run(request, force_mode='google_cloud_function')
6
7## Force Azure mode
8agent.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:

1from signalwire import AgentBase, AgentServer
2
3class SalesAgent(AgentBase):
4 def __init__(self):
5 super().__init__(name="sales-agent")
6 self.add_language("English", "en-US", "rime.spore")
7
8class SupportAgent(AgentBase):
9 def __init__(self):
10 super().__init__(name="support-agent")
11 self.add_language("English", "en-US", "rime.spore")
12
13server = AgentServer()
14server.register(SalesAgent(), "/sales")
15server.register(SupportAgent(), "/support")
16
17def lambda_handler(event, context):
18 """Lambda handler for multi-agent server"""
19 return server.run(event, context)

Environment detection

The SDK detects serverless environments automatically:

Environment VariablePlatform
AWS_LAMBDA_FUNCTION_NAMEAWS Lambda
LAMBDA_TASK_ROOTAWS Lambda
FUNCTION_TARGETGoogle Cloud Functions
K_SERVICEGoogle Cloud Functions
GOOGLE_CLOUD_PROJECTGoogle Cloud Functions
AZURE_FUNCTIONS_ENVIRONMENTAzure Functions
FUNCTIONS_WORKER_RUNTIMEAzure Functions