π Examples
Common use cases and integration examples
ROBO CODED β This documentation was made with AI and may not be 100% sane. But the code does work! π
π Examples
Real-world examples and integration patterns for the SIP AI Assistant.
π
Morning Weather Briefing
Schedule a daily weather call at 7am:
curl -X POST http://sip-agent:8080/schedule \
-H "Content-Type: application/json" \
-d '{
"extension": "5551234567",
"tool": "WEATHER",
"at_time": "07:00",
"timezone": "America/Los_Angeles",
"recurring": "daily",
"prefix": "Good morning! Here is your weather update for today.",
"suffix": "Have a great day!"
}' | jqResponse:
{
"schedule_id": "a1b2c3d4",
"status": "scheduled",
"extension": "5551234567",
"scheduled_for": "2025-12-01T07:00:00-08:00",
"delay_seconds": 28800,
"message": "Call scheduled for 2025-12-01T07:00:00-08:00",
"recurring": "daily"
}What happens at 7am:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β° 07:00 AM - Scheduled call triggered β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β π Dialing 5551234567... β
β π Ring... ring... β
β π± Call answered β
β π "Good morning! Here is your weather update for today." β
β π "At Storm Lake, as of 7:00 am, it's 38 degrees..." β
β π "Have a great day!" β
β π΄ Call ended β
β π Rescheduled for tomorrow at 07:00 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π
Appointment Reminders
Send appointment reminders with confirmation:
curl -X POST http://sip-agent:8080/call \
-H "Content-Type: application/json" \
-d '{
"extension": "5551234567",
"message": "Hello! This is a reminder that you have an appointment with Dr. Smith tomorrow at 2pm.",
"callback_url": "https://your-app.com/webhook/appointment",
"choice": {
"prompt": "Would you like to confirm or cancel this appointment?",
"options": [
{"value": "confirmed", "synonyms": ["yes", "yeah", "confirm", "keep"]},
{"value": "cancelled", "synonyms": ["no", "nope", "cancel", "reschedule"]}
],
"timeout_seconds": 20,
"repeat_count": 2
}
}' | jqWebhook payload received:
{
"call_id": "out-1732945860-1",
"status": "completed",
"extension": "5551234567",
"duration_seconds": 45.2,
"message_played": true,
"choice_response": "confirmed",
"choice_raw_text": "yes that works for me",
"error": null
}Handle the webhook (Python):
from fastapi import FastAPI
app = FastAPI()
@app.post("/webhook/appointment")
async def handle_appointment_webhook(payload: dict):
call_id = payload["call_id"]
choice = payload.get("choice_response")
if choice == "confirmed":
# β
Mark appointment confirmed
await confirm_appointment(call_id)
print(f"π
Appointment confirmed: {call_id}")
elif choice == "cancelled":
# β Open slot for rebooking
await cancel_appointment(call_id)
print(f"π
Appointment cancelled: {call_id}")
else:
# β οΈ No response - follow up later
await schedule_followup(call_id)
print(f"π
No response, scheduling followup: {call_id}")
return {"status": "ok"}π Home Assistant Integration
Trigger a weather call when leaving home:
automations.yaml
automation:
- id: weather_announcement_leaving
alias: "π€οΈ Weather announcement when leaving"
trigger:
- platform: state
entity_id: person.john
from: "home"
to: "not_home"
condition:
- condition: time
after: "06:00:00"
before: "10:00:00"
action:
- service: rest_command.weather_callconfiguration.yaml
rest_command:
weather_call:
url: "http://sip-agent:8080/tools/WEATHER/call"
method: POST
content_type: "application/json"
payload: >
{
"extension": "5551234567",
"prefix": "Good morning! Before you head out, here's the weather."
}What happens:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π Home Assistant Event β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β π John left home at 7:30 AM β
β π Trigger: person.john state changed to "not_home" β
β β
Condition: Time is between 6:00 AM and 10:00 AM β
β β‘ Action: Call rest_command.weather_call β
β π SIP Agent receives webhook β
β π€οΈ Weather tool executed β
β π Outbound call to 5551234567 β
β π "Good morning! Before you head out..." β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π¨ Monitoring Alerts
Alert on-call engineer when system goes down:
curl -X POST http://sip-agent:8080/call \
-H "Content-Type: application/json" \
-d '{
"extension": "5551234567",
"message": "Alert! The production database server is not responding. CPU usage was at 98% before it went offline. Please investigate immediately.",
"callback_url": "https://monitoring.example.com/alert-acknowledged",
"choice": {
"prompt": "Say acknowledge to confirm you received this alert.",
"options": [
{"value": "acknowledged", "synonyms": ["acknowledge", "ack", "got it", "on it"]}
],
"timeout_seconds": 30
}
}' | jqAlertmanager Integration
alertmanager.yml:
receivers:
- name: 'phone-alert'
webhook_configs:
- url: 'http://alert-bridge:8000/alert'
send_resolved: trueAlert bridge service (Python):
from fastapi import FastAPI
import httpx
app = FastAPI()
# π On-call rotation
ONCALL_NUMBERS = {
"primary": "5551234567",
"secondary": "5559876543"
}
@app.post("/alert")
async def handle_alert(alert: dict):
# π Build alert message
alert_name = alert['labels']['alertname']
severity = alert['labels'].get('severity', 'warning')
description = alert['annotations'].get('description', 'No description')
message = f"Alert: {alert_name}. Severity: {severity}. {description}"
# π Call on-call engineer
async with httpx.AsyncClient() as client:
response = await client.post(
"http://sip-agent:8080/call",
json={
"extension": ONCALL_NUMBERS["primary"],
"message": message,
"callback_url": "http://alert-bridge:8000/ack",
"choice": {
"prompt": "Say acknowledge to confirm.",
"options": [{"value": "ack", "synonyms": ["acknowledge", "ack", "got it"]}],
"timeout_seconds": 30
}
}
)
return {"status": "calling", "call_id": response.json()["call_id"]}
@app.post("/ack")
async def handle_ack(payload: dict):
if payload.get("choice_response") == "ack":
print(f"β
Alert acknowledged by on-call")
# Update incident management system
else:
print(f"β οΈ No acknowledgment, escalating to secondary")
# Call secondary on-callπ Medication Reminders
Set up recurring medication reminders:
# π
Morning medication (8 AM)
curl -X POST http://sip-agent:8080/schedule \
-H "Content-Type: application/json" \
-d '{
"extension": "5551234567",
"message": "Good morning! This is your reminder to take your morning medication.",
"at_time": "08:00",
"timezone": "America/New_York",
"recurring": "daily"
}' | jq
# π Evening medication (8 PM)
curl -X POST http://sip-agent:8080/schedule \
-H "Content-Type: application/json" \
-d '{
"extension": "5551234567",
"message": "Good evening! This is your reminder to take your evening medication.",
"at_time": "20:00",
"timezone": "America/New_York",
"recurring": "daily"
}' | jqList scheduled reminders:
curl http://sip-agent:8080/schedule | jqOutput:
[
{
"schedule_id": "med-morning",
"extension": "5551234567",
"scheduled_for": "2025-12-01T08:00:00-05:00",
"remaining_seconds": 14400,
"message": "Good morning! This is your reminder...",
"tool": null,
"recurring": "daily",
"status": "pending"
},
{
"schedule_id": "med-evening",
"extension": "5551234567",
"scheduled_for": "2025-12-01T20:00:00-05:00",
"remaining_seconds": 57600,
"message": "Good evening! This is your reminder...",
"tool": null,
"recurring": "daily",
"status": "pending"
}
]β° Cron-based Scheduling
Use system cron for flexible scheduling:
/etc/cron.d/weather-calls:
# ββββββββββββββ minute (0-59)
# β ββββββββββββββ hour (0-23)
# β β ββββββββββββββ day of month (1-31)
# β β β ββββββββββββββ month (1-12)
# β β β β ββββββββββββββ day of week (0-6, Sun=0)
# β β β β β
# β β β β β
# π
Weekday mornings at 6:30am
30 6 * * 1-5 root curl -s -X POST http://sip-agent:8080/tools/WEATHER/call \
-H "Content-Type: application/json" \
-d '{"extension":"1001","prefix":"Good morning! Time to wake up."}' > /dev/null
# π
Weekend mornings at 8am
0 8 * * 0,6 root curl -s -X POST http://sip-agent:8080/tools/WEATHER/call \
-H "Content-Type: application/json" \
-d '{"extension":"1001","prefix":"Good morning!"}' > /dev/null
# π Nightly summary at 9pm
0 21 * * * root curl -s -X POST http://sip-agent:8080/tools/WEATHER/call \
-H "Content-Type: application/json" \
-d '{"extension":"1001","prefix":"Here is your evening weather."}' > /dev/nullπ n8n Workflow Integration
Create a workflow that calls when a form is submitted:
Workflow JSON:
{
"name": "Contact Form β Phone Call",
"nodes": [
{
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [250, 300],
"parameters": {
"path": "contact-form",
"httpMethod": "POST"
}
},
{
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"position": [450, 300],
"parameters": {
"method": "POST",
"url": "http://sip-agent:8080/call",
"jsonParameters": true,
"options": {},
"bodyParametersJson": "={ \"message\": \"You have a new contact form submission from {{ $json.name }}. They said: {{ $json.message }}\", \"extension\": \"1001\" }"
}
}
],
"connections": {
"Webhook": {
"main": [[{"node": "HTTP Request", "type": "main", "index": 0}]]
}
}
}Trigger the workflow:
curl -X POST http://n8n:5678/webhook/contact-form \
-H "Content-Type: application/json" \
-d '{
"name": "John Smith",
"email": "[email protected]",
"message": "I am interested in your services"
}'π Python SDK
import httpx
from typing import Optional
class SIPAssistant:
"""Python client for the SIP AI Assistant API."""
def __init__(self, base_url: str = "http://sip-agent:8080"):
self.base_url = base_url
async def call(
self,
extension: str,
message: str,
callback_url: Optional[str] = None
) -> dict:
"""π Make an outbound call."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{self.base_url}/call",
json={
"extension": extension,
"message": message,
"callback_url": callback_url
}
)
return response.json()
async def weather_call(
self,
extension: str,
prefix: Optional[str] = None
) -> dict:
"""π€οΈ Call with weather update."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{self.base_url}/tools/WEATHER/call",
json={
"extension": extension,
"prefix": prefix
}
)
return response.json()
async def schedule_daily_weather(
self,
extension: str,
time: str,
timezone: str = "America/Los_Angeles"
) -> dict:
"""β° Schedule daily weather calls."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{self.base_url}/schedule",
json={
"extension": extension,
"tool": "WEATHER",
"at_time": time,
"timezone": timezone,
"recurring": "daily",
"prefix": "Good morning! Here's your weather."
}
)
return response.json()
async def get_weather(self) -> dict:
"""π‘οΈ Get weather data without calling."""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{self.base_url}/tools/WEATHER/execute",
json={}
)
return response.json()
# π Usage example
async def main():
assistant = SIPAssistant()
# π€οΈ Get weather
weather = await assistant.get_weather()
print(f"Weather: {weather['message']}")
# β° Schedule daily briefing
result = await assistant.schedule_daily_weather(
extension="5551234567",
time="07:00"
)
print(f"Scheduled: {result['schedule_id']}")
# π Make a call
call = await assistant.call(
extension="5551234567",
message="Hello! This is a test call."
)
print(f"Call ID: {call['call_id']}")
if __name__ == "__main__":
import asyncio
asyncio.run(main())π Grafana Alert Integration
Configure Grafana to call via webhook:
Contact Point (YAML):
apiVersion: 1
contactPoints:
- name: phone-alert
receivers:
- uid: phone
type: webhook
settings:
url: http://sip-agent:8080/call
httpMethod: POST
secureSettings: {}Notification Template:
{{ define "phone.message" }}
Alert: {{ .CommonLabels.alertname }}
Status: {{ .Status }}
{{ range .Alerts }}
{{ .Annotations.summary }}
{{ end }}
{{ end }}π³ Docker Health Check
Monitor the assistant and restart if unhealthy:
services:
sip-agent:
image: sip-agent:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
restart: unless-stoppedCheck health manually:
docker inspect --format='{{.State.Health.Status}}' sip-agentExpected output:
healthyUpdated about 1 month ago
