Files
poimen-workflows/internal/memory/workflow_examples.go
T
Test 5ef14ad5ec feat(memory): add Temporal activities integration for memory service
- Implement 12 Temporal activities for memory operations
- Activities: create, update, search, context, diagnose, analyze, document
- Add activity registration and worker setup
- Full retry/timeout configuration with observability
- Include workflow patterns and examples
- All tests passing (23/23)

Documentation:
- MEMORY_INTEGRATION.md: High-level integration guide
- MEMORY_ACTIVITIES.md: Complete activities reference
- REGISTERED_ACTIVITIES.md: Registry and calling conventions
2026-08-29 21:49:24 -07:00

304 lines
7.7 KiB
Go

package memory
import (
"fmt"
"go.temporal.io/sdk/workflow"
)
// LearningWorkflow learns from task execution
// Pattern: Execute → Learn → Document
func LearningWorkflow(ctx workflow.Context, taskID string, executor string) (string, error) {
// Execute task (placeholder - replace with actual activity)
taskResult := fmt.Sprintf("Task %s executed by %s", taskID, executor)
// Learn from execution
knowledgeID, err := ExecuteLearnFromExecution(
ctx,
taskID,
taskResult,
[]string{"execution", "learning"},
DefaultActivityOptions(),
)
if err != nil {
return "", fmt.Errorf("learn from execution: %w", err)
}
return knowledgeID, nil
}
// DiagnosticWorkflow diagnoses issue using memory service
// Pattern: Get Context → Extract Recommendations → Apply
func DiagnosticWorkflow(ctx workflow.Context, tool, issue string) ([]string, error) {
// Get recommendations
recommendations, err := ExecuteDiagnoseIssue(
ctx,
tool,
issue,
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("diagnose: %w", err)
}
return recommendations, nil
}
// SearchAndApplyWorkflow searches knowledge and applies it
// Pattern: Search → Filter → Apply
func SearchAndApplyWorkflow(ctx workflow.Context, query string) ([]KnowledgeRecord, error) {
// Search knowledge
records, err := ExecuteSearchKnowledge(
ctx,
query,
&RetrievalOptions{
Limit: 10,
LevelFilter: []string{"L1", "L2"},
Floor: 0.7,
},
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("search: %w", err)
}
return records, nil
}
// ContextualDecisionWorkflow makes decisions with memory context
// Pattern: Get Context → Make Decision → Document Decision
func ContextualDecisionWorkflow(ctx workflow.Context, tool, task string, decision string) (string, error) {
// Get context
svcCtx, err := ExecuteGetContext(
ctx,
tool,
task,
8192,
DefaultActivityOptions(),
)
if err != nil {
return "", fmt.Errorf("get context: %w", err)
}
// Build reasoning from lessons
reasoning := fmt.Sprintf("Based on %d lessons from memory service (tier %d)", len(svcCtx.Lessons), svcCtx.Tier)
// Document decision
docID, err := ExecuteDocumentDecision(
ctx,
tool,
decision,
reasoning,
DefaultActivityOptions(),
)
if err != nil {
return "", fmt.Errorf("document decision: %w", err)
}
return docID, nil
}
// ErrorRecoveryWorkflow analyzes error and searches for recovery
// Pattern: Error → Analyze → Search → Recover
func ErrorRecoveryWorkflow(ctx workflow.Context, errorMsg string) ([]string, error) {
// Analyze error
records, err := ExecuteAnalyzeError(
ctx,
errorMsg,
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("analyze error: %w", err)
}
// Extract recovery recommendations
recommendations := make([]string, 0)
for _, record := range records {
if record.Level == "L1" { // High confidence
recommendations = append(recommendations, record.Content)
}
}
return recommendations, nil
}
// HealthAwareWorkflow checks health before proceeding
// Pattern: HealthCheck → Conditional Proceed
func HealthAwareWorkflow(ctx workflow.Context, taskID string) (bool, error) {
// Check health
healthy, err := ExecuteHealthCheck(ctx, DefaultActivityOptions())
if err != nil {
return false, fmt.Errorf("health check: %w", err)
}
if !healthy {
return false, fmt.Errorf("memory service unhealthy, skipping task %s", taskID)
}
return true, nil
}
// IterativeLearnWorkflow learns iteratively
// Pattern: Execute → Learn → Refine → Learn Again
func IterativeLearnWorkflow(ctx workflow.Context, topic string, iterations int) ([]string, error) {
knowledgeIDs := make([]string, 0)
for i := 0; i < iterations; i++ {
// Learn current iteration
id, err := ExecuteLearnFromExecution(
ctx,
fmt.Sprintf("%s-iteration-%d", topic, i+1),
fmt.Sprintf("Iteration %d: %s", i+1, topic),
[]string{"iteration", fmt.Sprintf("iteration-%d", i+1)},
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("learn iteration %d: %w", i+1, err)
}
knowledgeIDs = append(knowledgeIDs, id)
// Search for related knowledge
records, err := ExecuteSearchKnowledge(
ctx,
topic,
&RetrievalOptions{Limit: 5, Floor: 0.6},
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("search iteration %d: %w", i+1, err)
}
// Log found records
if len(records) > 0 {
workflow.GetLogger(ctx).Info("Iteration found related records", "iteration", i+1, "records", len(records))
}
}
return knowledgeIDs, nil
}
// ConditionalLearningWorkflow learns only on success
// Pattern: Execute → If Success → Learn
func ConditionalLearningWorkflow(ctx workflow.Context, taskID string, shouldSucceed bool) (string, error) {
if !shouldSucceed {
return "", fmt.Errorf("task failed, skipping learning")
}
// Only learn on success
result := fmt.Sprintf("Task %s succeeded", taskID)
id, err := ExecuteLearnFromExecution(
ctx,
taskID,
result,
[]string{"success"},
DefaultActivityOptions(),
)
if err != nil {
return "", fmt.Errorf("learn from success: %w", err)
}
return id, nil
}
// MultiStepWorkflow performs multiple memory operations
// Pattern: Create → Search → Context → Document
func MultiStepWorkflow(ctx workflow.Context, topic string) (map[string]interface{}, error) {
results := make(map[string]interface{})
// Step 1: Create knowledge
createID, err := ExecuteCreateKnowledge(
ctx,
&KnowledgeRecord{
Level: "L1",
Title: fmt.Sprintf("Initial: %s", topic),
Content: fmt.Sprintf("Starting workflow for %s", topic),
Source: "workflow://multi-step",
},
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("create knowledge: %w", err)
}
results["created"] = createID
// Step 2: Search knowledge
searchRecords, err := ExecuteSearchKnowledge(
ctx,
topic,
&RetrievalOptions{Limit: 5},
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("search knowledge: %w", err)
}
results["found"] = len(searchRecords)
// Step 3: Get context
svcCtx, err := ExecuteGetContext(
ctx,
"workflow",
topic,
8192,
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("get context: %w", err)
}
results["context_tier"] = svcCtx.Tier
results["lessons"] = len(svcCtx.Lessons)
results["skills"] = len(svcCtx.Skills)
// Step 4: Document completion
docID, err := ExecuteDocumentDecision(
ctx,
"workflow_completion",
fmt.Sprintf("Completed multi-step workflow for %s", topic),
fmt.Sprintf("Found %d records, tier %d context", len(searchRecords), svcCtx.Tier),
DefaultActivityOptions(),
)
if err != nil {
return nil, fmt.Errorf("document completion: %w", err)
}
results["documented"] = docID
return results, nil
}
// ParallelLearnWorkflow learns from multiple sources in parallel
// Pattern: Execute Multiple Tasks in Parallel → Learn from Each
func ParallelLearnWorkflow(ctx workflow.Context, taskIDs []string) ([]string, error) {
// Create parallel activities
futures := make([]workflow.Future, len(taskIDs))
for i, taskID := range taskIDs {
// Execute each task in parallel
future := workflow.ExecuteActivity(
workflow.WithActivityOptions(
ctx,
workflow.ActivityOptions{
ScheduleToCloseTimeout: DefaultActivityOptions().RetryBackoff * 60,
StartToCloseTimeout: DefaultActivityOptions().RetryBackoff * 30,
},
),
"LearnFromExecutionActivity",
taskID,
fmt.Sprintf("Result from %s", taskID),
[]string{"parallel", taskID},
)
futures[i] = future
}
// Collect results
results := make([]string, len(futures))
for i, future := range futures {
err := future.Get(ctx, &results[i])
if err != nil {
return nil, fmt.Errorf("parallel learn task %d: %w", i, err)
}
}
return results, nil
}