Skip to content

Tutorial 6: Observability

Learn how to monitor and observe your SDK applications with the hooks package.

  • Subscribe to SDK events
  • Monitor tool calls and responses
  • Track conversation flow
  • Debug issues

Observability helps you:

  • Debug - Understand what’s happening in your application
  • Monitor - Track performance and usage
  • Audit - Log all actions for compliance
  • Optimize - Find bottlenecks and improve

Complete Tutorial 1 and understand basic SDK usage.

Use Subscribe() to listen for events:

package main
import (
"context"
"fmt"
"log"
"github.com/AltairaLabs/PromptKit/sdk"
"github.com/AltairaLabs/PromptKit/sdk/hooks"
)
func main() {
conv, err := sdk.Open("./hello.pack.json", "chat")
if err != nil {
log.Fatal(err)
}
defer conv.Close()
// Subscribe to send events
conv.Subscribe(hooks.EventSend, func(e hooks.Event) {
fmt.Printf("[SEND] Message: %v\n", e.Data["message"])
})
// Subscribe to response events
conv.Subscribe(hooks.EventResponse, func(e hooks.Event) {
fmt.Printf("[RESPONSE] Got reply\n")
})
ctx := context.Background()
resp, _ := conv.Send(ctx, "Hello!")
fmt.Println(resp.Text())
}

The hooks package provides these event types:

const (
EventSend = "send" // Message sent
EventResponse = "response" // Response received
EventToolCall = "tool_call" // Tool invoked
EventToolResult = "tool_result" // Tool returned
EventError = "error" // Error occurred
EventStream = "stream" // Stream chunk received
)

Track tool execution:

conv.Subscribe(hooks.EventToolCall, func(e hooks.Event) {
toolName := e.Data["tool"].(string)
args := e.Data["args"]
fmt.Printf("[TOOL] Calling %s with %v\n", toolName, args)
})
conv.Subscribe(hooks.EventToolResult, func(e hooks.Event) {
toolName := e.Data["tool"].(string)
result := e.Data["result"]
fmt.Printf("[TOOL] %s returned: %v\n", toolName, result)
})

Create a comprehensive logger:

func logAllEvents(conv *sdk.Conversation) {
events := []string{
hooks.EventSend,
hooks.EventResponse,
hooks.EventToolCall,
hooks.EventToolResult,
hooks.EventError,
hooks.EventStream,
}
for _, event := range events {
eventName := event // Capture for closure
conv.Subscribe(eventName, func(e hooks.Event) {
log.Printf("[%s] %s: %v",
e.Timestamp.Format("15:04:05"),
eventName,
e.Data,
)
})
}
}
// Usage
conv, _ := sdk.Open("./pack.json", "chat")
logAllEvents(conv)

Track and alert on errors:

conv.Subscribe(hooks.EventError, func(e hooks.Event) {
err := e.Data["error"]
// Log the error
log.Printf("[ERROR] %v", err)
// Alert if critical
if isCritical(err) {
alertTeam(err)
}
})

Track streaming progress:

var charCount int
conv.Subscribe(hooks.EventStream, func(e hooks.Event) {
chunk := e.Data["chunk"].(string)
charCount += len(chunk)
// Log progress every 100 characters
if charCount % 100 == 0 {
log.Printf("[STREAM] %d characters received", charCount)
}
})

Collect metrics for monitoring systems:

type Metrics struct {
MessageCount int64
ToolCalls int64
Errors int64
TotalTokens int64
mu sync.Mutex
}
func (m *Metrics) Attach(conv *sdk.Conversation) {
conv.Subscribe(hooks.EventSend, func(e hooks.Event) {
m.mu.Lock()
m.MessageCount++
m.mu.Unlock()
})
conv.Subscribe(hooks.EventToolCall, func(e hooks.Event) {
m.mu.Lock()
m.ToolCalls++
m.mu.Unlock()
})
conv.Subscribe(hooks.EventError, func(e hooks.Event) {
m.mu.Lock()
m.Errors++
m.mu.Unlock()
})
}

Enable verbose debugging:

func enableDebug(conv *sdk.Conversation) {
conv.Subscribe(hooks.EventSend, func(e hooks.Event) {
fmt.Printf("📤 SEND: %v\n", e.Data)
})
conv.Subscribe(hooks.EventResponse, func(e hooks.Event) {
fmt.Printf("📥 RESPONSE: %v\n", e.Data)
})
conv.Subscribe(hooks.EventToolCall, func(e hooks.Event) {
fmt.Printf("🔧 TOOL CALL: %s(%v)\n",
e.Data["tool"], e.Data["args"])
})
conv.Subscribe(hooks.EventToolResult, func(e hooks.Event) {
fmt.Printf("✅ TOOL RESULT: %v\n", e.Data["result"])
})
conv.Subscribe(hooks.EventError, func(e hooks.Event) {
fmt.Printf("❌ ERROR: %v\n", e.Data["error"])
})
}

✅ Subscribe to events with Subscribe()
✅ Monitor tool calls and responses
✅ Track errors and stream progress
✅ Build metrics collection
✅ Enable debug logging

See observability patterns in sdk/examples/.