Skip to content

Tutorial 4: Variables and Templates

Learn how to use template variables for dynamic prompts and conversation context.

  • Set and get template variables
  • Use variables in system prompts
  • Bulk variable operations
  • Environment variable integration

Variables make prompts dynamic and reusable:

Static Prompt:

You are a helpful assistant.

Dynamic Prompt:

You are a {{role}} assistant for {{company}}.
Speak in {{language}}.

Complete Tutorial 1 and understand basic SDK usage.

Create dynamic.pack.json:

{
"id": "dynamic-support",
"name": "Dynamic Support",
"version": "1.0.0",
"template_engine": {
"version": "v1",
"syntax": "{{variable}}"
},
"prompts": {
"support": {
"id": "support",
"name": "Support Agent",
"version": "1.0.0",
"system_template": "You are a {{role}} at {{company}}. Help customers in {{language}}. The customer's name is {{customer_name}}.",
"parameters": {
"temperature": 0.7
}
}
}
}

Use SetVar() to set individual variables:

package main
import (
"context"
"fmt"
"log"
"github.com/AltairaLabs/PromptKit/sdk"
)
func main() {
conv, err := sdk.Open("./dynamic.pack.json", "support")
if err != nil {
log.Fatal(err)
}
defer conv.Close()
// Set individual variables
conv.SetVar("role", "customer support specialist")
conv.SetVar("company", "TechCorp")
conv.SetVar("language", "English")
conv.SetVar("customer_name", "Alice")
ctx := context.Background()
resp, err := conv.Send(ctx, "I need help with my order")
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Text())
}

Use SetVars() for multiple variables at once:

conv.SetVars(map[string]any{
"role": "sales representative",
"company": "GlobalTech",
"language": "Spanish",
"customer_name": "Carlos",
})

Retrieve variables with GetVar():

// Set a variable
conv.SetVar("user_id", "12345")
// Get it back
userID, ok := conv.GetVar("user_id")
if ok {
fmt.Printf("User ID: %s\n", userID) // "12345"
}
// Non-existent variables return false
_, ok = conv.GetVar("nonexistent")
fmt.Printf("Found: %v\n", ok) // false

Load variables from environment:

// Set from environment
// Uses PROMPTKIT_ prefix by default
// e.g., PROMPTKIT_API_KEY becomes "api_key"
conv.SetVarsFromEnv("PROMPTKIT_")
// Or set individual env vars
import "os"
conv.SetVar("api_key", os.Getenv("MY_API_KEY"))

Update variables during conversation:

conv, _ := sdk.Open("./support.pack.json", "support")
conv.SetVar("customer_name", "Unknown")
// First interaction
resp1, _ := conv.Send(ctx, "Hi, my name is Bob")
// Update context based on conversation
conv.SetVar("customer_name", "Bob")
// Now system prompt includes "The customer's name is Bob"
resp2, _ := conv.Send(ctx, "What products do you have?")

Variables are strings:

conv.SetVar("name", "Alice")
conv.SetVar("user_id", "12345")
conv.SetVar("is_premium", "true")
conv.SetVar("region", "us-west")

Use SetVars() for bulk setting with map[string]any (values are converted to strings):

conv.SetVars(map[string]any{
"name": "Alice",
"user_id": 12345,
"is_premium": true,
})

Variables are thread-safe for concurrent access:

var wg sync.WaitGroup
// Safe to set from multiple goroutines
for i := 0; i < 10; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
conv.SetVar(fmt.Sprintf("var_%d", n), fmt.Sprintf("%d", n))
}(i)
}
wg.Wait()

Forked conversations get their own variable scope:

conv1, _ := sdk.Open("./pack.json", "chat")
conv1.SetVar("user", "Alice")
// Fork creates isolated copy
conv2 := conv1.Fork()
conv2.SetVar("user", "Bob")
// conv1 still has "Alice"
user1, _ := conv1.GetVar("user")
user2, _ := conv2.GetVar("user")
fmt.Println(user1) // "Alice"
fmt.Println(user2) // "Bob"

✅ Set variables with SetVar() and SetVars()
✅ Get variables with GetVar()
✅ Use variables in system prompts
✅ Load from environment
✅ Thread-safe concurrent access
✅ Variable isolation in forks

See the variable handling in sdk/examples/hello/.