Variables & Templates
Variables allow you to inject dynamic content into prompts, greetings, and responses, enabling personalized conversations.
Overview
┌──────────────────────────────────────────────────────────────┐
│ Variable System │
│ │
│ Call Context ───► Template Engine ───► Rendered Output │
│ {customer: "John"} "Hello {{customer}}!" "Hello John!"│
│ │
└──────────────────────────────────────────────────────────────┘
Configuration
Define Variables
{
"agent": {
"name": "Customer Support",
"variables": {
"companyName": "Acme Corp",
"supportHours": "9 AM to 6 PM",
"website": "acme.com"
},
"greetingMessage": "Hello! Welcome to {{companyName}}. How can I help?",
"prompt": "You are a support agent for {{companyName}}. Support hours are {{supportHours}}."
}
}
Variable Types
| Type | Example | Description |
|---|---|---|
| Static | companyName |
Configured in agent settings |
| Dynamic | customerName |
Passed at call time |
| System | currentTime |
Auto-populated by system |
| Computed | orderTotal |
Calculated from data |
Implementation
Template Engine
type TemplateEngine struct {
staticVars map[string]string
dynamicVars map[string]string
systemVars map[string]func() string
}
func NewTemplateEngine(staticVars map[string]string) *TemplateEngine {
return &TemplateEngine{
staticVars: staticVars,
dynamicVars: make(map[string]string),
systemVars: map[string]func() string{
"currentTime": getCurrentTime,
"currentDate": getCurrentDate,
"callDuration": func() string { return "calculating..." },
"agentName": func() string { return "Assistant" },
},
}
}
func (t *TemplateEngine) Render(template string) string {
result := template
// Replace static variables
for key, value := range t.staticVars {
placeholder := "{{" + key + "}}"
result = strings.ReplaceAll(result, placeholder, value)
}
// Replace dynamic variables
for key, value := range t.dynamicVars {
placeholder := "{{" + key + "}}"
result = strings.ReplaceAll(result, placeholder, value)
}
// Replace system variables
for key, fn := range t.systemVars {
placeholder := "{{" + key + "}}"
if strings.Contains(result, placeholder) {
result = strings.ReplaceAll(result, placeholder, fn())
}
}
return result
}
func (t *TemplateEngine) SetDynamicVar(key, value string) {
t.dynamicVars[key] = value
}
Passing Variables at Call Time
// When initiating a call
func (s *Session) StartCall(config CallConfig) error {
// Set dynamic variables from call config
for key, value := range config.Variables {
s.templateEngine.SetDynamicVar(key, value)
}
// Render greeting with variables
greeting := s.templateEngine.Render(s.agent.GreetingMessage)
s.tts.Speak(greeting)
// Render prompt with variables
prompt := s.templateEngine.Render(s.agent.Prompt)
s.llm.SetSystemPrompt(prompt)
return nil
}
API Example
# Initiate call with variables
curl -X POST https://api.edesy.in/v1/calls \
-H "Authorization: Bearer $API_KEY" \
-d '{
"agent_id": "agent_123",
"to": "+1234567890",
"variables": {
"customerName": "John Smith",
"orderId": "ORD-12345",
"orderStatus": "shipped",
"deliveryDate": "December 30th"
}
}'
System Variables
Built-in Variables
| Variable | Description | Example |
|---|---|---|
{{currentTime}} |
Current time | "2:30 PM" |
{{currentDate}} |
Current date | "December 28, 2024" |
{{callDuration}} |
Time in call | "2 minutes" |
{{callerNumber}} |
Caller's phone | "+1234567890" |
{{agentName}} |
Agent's name | "Customer Support" |
System Variable Implementation
func getCurrentTime() string {
return time.Now().Format("3:04 PM")
}
func getCurrentDate() string {
return time.Now().Format("January 2, 2006")
}
func (s *Session) getCallDuration() string {
duration := time.Since(s.startTime)
if duration < time.Minute {
return fmt.Sprintf("%d seconds", int(duration.Seconds()))
}
return fmt.Sprintf("%d minutes", int(duration.Minutes()))
}
func (s *Session) getCallerNumber() string {
return s.callerID
}
Use Cases
Personalized Greeting
{
"greetingMessage": "Hello {{customerName}}! This is {{agentName}} from {{companyName}}. I see you have an order {{orderId}}. How can I help you today?"
}
Dynamic Prompt
{
"prompt": "You are a support agent for {{companyName}}.\n\nCustomer Information:\n- Name: {{customerName}}\n- Account: {{accountId}}\n- Plan: {{subscriptionPlan}}\n\nPrevious interactions: {{lastInteractionSummary}}\n\nBe helpful and address them by name."
}
Order Status
// Lookup order and set variables
func (s *Session) prepareOrderVariables(orderID string) error {
order, err := s.orderService.GetOrder(orderID)
if err != nil {
return err
}
s.templateEngine.SetDynamicVar("orderId", order.ID)
s.templateEngine.SetDynamicVar("orderStatus", order.Status)
s.templateEngine.SetDynamicVar("orderTotal", formatCurrency(order.Total))
s.templateEngine.SetDynamicVar("shippingAddress", order.ShippingAddress)
s.templateEngine.SetDynamicVar("estimatedDelivery", formatDate(order.EstimatedDelivery))
return nil
}
// Template
prompt := `Customer is calling about order {{orderId}}.
Current status: {{orderStatus}}
Order total: {{orderTotal}}
Shipping to: {{shippingAddress}}
Estimated delivery: {{estimatedDelivery}}`
Appointment Confirmation
variables := map[string]string{
"patientName": "John Smith",
"appointmentDate": "December 30th",
"appointmentTime": "2:30 PM",
"doctorName": "Dr. Johnson",
"clinicName": "Main Street Clinic",
"clinicPhone": "555-123-4567",
}
greeting := "Hello {{patientName}}! This is {{clinicName}} calling to confirm your appointment with {{doctorName}} on {{appointmentDate}} at {{appointmentTime}}. Press 1 to confirm or 2 to reschedule."
Conditional Content
If-Else Templates
type ConditionalTemplate struct {
conditions map[string]string
}
func (t *TemplateEngine) RenderConditional(template string) string {
// Pattern: {{#if variable}}content{{else}}alternative{{/if}}
re := regexp.MustCompile(`\{\{#if (\w+)\}\}(.*?)\{\{else\}\}(.*?)\{\{/if\}\}`)
result := re.ReplaceAllStringFunc(template, func(match string) string {
parts := re.FindStringSubmatch(match)
varName := parts[1]
ifContent := parts[2]
elseContent := parts[3]
if t.hasVar(varName) && t.getVar(varName) != "" {
return t.Render(ifContent)
}
return t.Render(elseContent)
})
return result
}
// Usage
template := `Hello {{customerName}}!
{{#if hasActiveOrder}}Your order {{orderId}} is {{orderStatus}}.{{else}}I don't see any active orders.{{/if}}`
Switch Templates
func (t *TemplateEngine) RenderSwitch(template string) string {
// Pattern: {{#switch variable}}{{#case value}}content{{/case}}{{/switch}}
// Implementation...
return template
}
// Usage
template := `{{#switch orderStatus}}
{{#case "processing"}}Your order is being processed.{{/case}}
{{#case "shipped"}}Your order has shipped!{{/case}}
{{#case "delivered"}}Your order was delivered.{{/case}}
{{/switch}}`
Formatting Helpers
Built-in Formatters
type Formatter struct{}
func (f *Formatter) Currency(amount float64, currency string) string {
switch currency {
case "USD":
return fmt.Sprintf("$%.2f", amount)
case "INR":
return fmt.Sprintf("₹%.2f", amount)
case "EUR":
return fmt.Sprintf("€%.2f", amount)
default:
return fmt.Sprintf("%.2f %s", amount, currency)
}
}
func (f *Formatter) Date(t time.Time, format string) string {
formats := map[string]string{
"short": "Jan 2",
"medium": "January 2, 2006",
"long": "Monday, January 2, 2006",
"relative": "", // "yesterday", "2 days ago"
}
if fmt, ok := formats[format]; ok {
if format == "relative" {
return f.relativeDate(t)
}
return t.Format(fmt)
}
return t.Format(format)
}
func (f *Formatter) Phone(number string) string {
// Format: (555) 123-4567
if len(number) == 10 {
return fmt.Sprintf("(%s) %s-%s", number[:3], number[3:6], number[6:])
}
return number
}
func (f *Formatter) SpeakableNumber(number string) string {
// "1234" -> "1 2 3 4"
return strings.Join(strings.Split(number, ""), " ")
}
Template with Formatters
// {{amount|currency:"USD"}} -> "$25.99"
// {{date|format:"medium"}} -> "December 28, 2024"
// {{phone|format}} -> "(555) 123-4567"
func (t *TemplateEngine) RenderWithFormatters(template string) string {
re := regexp.MustCompile(`\{\{(\w+)\|(\w+)(?::"([^"]+)")?\}\}`)
result := re.ReplaceAllStringFunc(template, func(match string) string {
parts := re.FindStringSubmatch(match)
varName := parts[1]
formatter := parts[2]
arg := parts[3]
value := t.getVar(varName)
switch formatter {
case "currency":
amount, _ := strconv.ParseFloat(value, 64)
return t.formatter.Currency(amount, arg)
case "format":
// Parse as date and format
date, _ := time.Parse(time.RFC3339, value)
return t.formatter.Date(date, arg)
case "phone":
return t.formatter.Phone(value)
case "speakable":
return t.formatter.SpeakableNumber(value)
}
return value
})
return result
}
Variable Scopes
Session Variables
Persist for the entire call:
func (s *Session) SetSessionVar(key, value string) {
s.sessionVars[key] = value
}
func (s *Session) GetSessionVar(key string) string {
return s.sessionVars[key]
}
Turn Variables
Reset each conversation turn:
func (s *Session) SetTurnVar(key, value string) {
s.turnVars[key] = value
}
func (s *Session) ClearTurnVars() {
s.turnVars = make(map[string]string)
}
Global Variables
Shared across all calls:
var globalVars = map[string]string{
"companyName": "Acme Corp",
"supportEmail": "[email protected]",
"supportPhone": "1-800-ACME",
}
Webhook Integration
Receiving Variables via Webhook
type WebhookPayload struct {
Event string `json:"event"`
CallID string `json:"call_id"`
Variables map[string]string `json:"variables"`
}
func (s *Session) HandleWebhook(payload WebhookPayload) {
// Update session variables from webhook
for key, value := range payload.Variables {
s.templateEngine.SetDynamicVar(key, value)
}
}
Example: CRM Integration
{
"event": "call.started",
"call_id": "call_123",
"variables": {
"customerName": "John Smith",
"accountTier": "Premium",
"lastPurchase": "Widget Pro",
"lifetimeValue": "$5,432"
}
}
Best Practices
1. Validate Variables
func (t *TemplateEngine) ValidateTemplate(template string) []string {
var missing []string
re := regexp.MustCompile(`\{\{(\w+)\}\}`)
matches := re.FindAllStringSubmatch(template, -1)
for _, match := range matches {
varName := match[1]
if !t.hasVar(varName) {
missing = append(missing, varName)
}
}
return missing
}
2. Provide Defaults
func (t *TemplateEngine) RenderWithDefaults(template string) string {
// {{variable|default:"fallback"}}
re := regexp.MustCompile(`\{\{(\w+)\|default:"([^"]+)"\}\}`)
result := re.ReplaceAllStringFunc(template, func(match string) string {
parts := re.FindStringSubmatch(match)
varName := parts[1]
defaultVal := parts[2]
if value := t.getVar(varName); value != "" {
return value
}
return defaultVal
})
return result
}
// Usage
template := "Hello {{customerName|default:\"valued customer\"}}!"
3. Escape User Input
func (t *TemplateEngine) EscapeForSpeech(value string) string {
// Remove or escape characters that might affect TTS
value = strings.ReplaceAll(value, "<", "less than")
value = strings.ReplaceAll(value, ">", "greater than")
value = strings.ReplaceAll(value, "&", "and")
return value
}
Next Steps
- Function Calling - Dynamic data lookup
- Webhooks - Receive variable updates
- Configuration - Agent settings