State Management¶
State management is the foundation of data flow in SemanticKernel.Graph. This guide explains how to work with GraphState
, KernelArguments
, execution history, metadata, validation, and serialization to build robust and maintainable workflows.
What You'll Learn¶
- How
GraphState
wrapsKernelArguments
for enhanced functionality - Managing execution history and metadata
- State validation and versioning
- Serialization and deserialization capabilities
- Best practices for state design and management
Concepts and Techniques¶
GraphState: An enhanced wrapper around KernelArguments
that provides execution tracking, metadata management, validation, and serialization capabilities.
KernelArguments: The core Semantic Kernel container for key-value pairs that represents the execution state and context.
Execution History: A chronological record of all execution steps, including timing, results, and metadata for each node execution.
State Validation: Built-in integrity checks that ensure state consistency, serializability, and version compatibility.
Serialization: The ability to save and restore graph state with compression, version migration, and integrity validation.
Prerequisites¶
- First Graph Tutorial completed
- Basic understanding of SemanticKernel.Graph concepts
- Familiarity with
KernelArguments
from Semantic Kernel
Core State Components¶
GraphState: Enhanced State Wrapper¶
GraphState
is the primary state container that wraps KernelArguments
with additional graph-specific functionality:
using SemanticKernel.Graph.State;
using Microsoft.SemanticKernel;
// Create state with existing KernelArguments
var arguments = new KernelArguments
{
["input"] = "Hello World",
["timestamp"] = DateTimeOffset.UtcNow
};
var graphState = new GraphState(arguments);
// Access the underlying KernelArguments
var kernelArgs = graphState.KernelArguments;
// Access enhanced properties
var stateId = graphState.StateId;
var version = graphState.Version;
var createdAt = graphState.CreatedAt;
var lastModified = graphState.LastModified;
State Properties and Metadata¶
Every GraphState
instance includes built-in metadata:
// State identification
var stateId = graphState.StateId; // Unique identifier
var version = graphState.Version; // State version (e.g., "1.1.0")
var createdAt = graphState.CreatedAt; // Creation timestamp
var lastModified = graphState.LastModified; // Last modification timestamp
var isModified = graphState.IsModified; // Whether state has been modified
// Execution tracking
var executionStepCount = graphState.ExecutionStepCount;
var executionHistory = graphState.ExecutionHistory;
State Access and Manipulation¶
Reading State Values¶
Use type-safe methods to read values from state:
// Type-safe reading with defaults
var name = graphState.GetValue<string>("userName");
var age = graphState.GetValue<int>("userAge");
var isActive = graphState.GetValue<bool>("isActive");
// Safe reading with fallback values
var department = graphState.GetValueOrDefault("department", "Unknown");
var score = graphState.GetValueOrDefault("score", 0.0);
// Try-pattern for conditional reading
if (graphState.TryGetValue<string>("email", out var email))
{
// Process email
}
Writing to State¶
Update state values and track modifications:
// Set values (automatically updates LastModified)
graphState.SetValue("processed", true);
graphState.SetValue("result", "Success");
graphState.SetValue("score", 95.5);
// Remove values
var wasRemoved = graphState.RemoveValue("temporaryData");
// Check modification status
if (graphState.IsModified)
{
Console.WriteLine($"State modified at: {graphState.LastModified}");
}
Complex Object Management¶
Store and retrieve complex objects in state:
// Store complex objects
var userProfile = new
{
Name = "Alice",
Department = "Engineering",
Skills = new[] { "C#", ".NET", "AI" },
Experience = 5
};
graphState.SetValue("userProfile", userProfile);
// Retrieve and work with complex objects
var profile = graphState.GetValue<object>("userProfile");
var metadata = graphState.GetValue<Dictionary<string, object>>("metadata");
// Store collections
var tags = new List<string> { "AI", "Machine Learning", "Graphs" };
graphState.SetValue("tags", tags);
Execution History and Tracking¶
Execution Steps¶
GraphState
automatically tracks execution history through ExecutionStep
objects:
// Each execution step includes:
var steps = graphState.ExecutionHistory;
foreach (var step in steps)
{
Console.WriteLine($"Step: {step.StepId}");
Console.WriteLine($"Node: {step.NodeId}");
Console.WriteLine($"Function: {step.FunctionName}");
Console.WriteLine($"Status: {step.Status}");
Console.WriteLine($"Duration: {step.Duration}");
Console.WriteLine($"Result: {step.Result}");
}
Execution Status Types¶
Execution steps can have different statuses:
public enum ExecutionStatus
{
Running, // Currently executing
Completed, // Successfully completed
Failed, // Execution failed
Cancelled // Execution was cancelled
}
Adding Execution Metadata¶
Nodes can add custom metadata to execution steps:
// In your node execution
var step = new ExecutionStep("nodeId", "functionName", DateTimeOffset.UtcNow);
// Add custom metadata
step.AddMetadata("inputSize", input.Length);
step.AddMetadata("processingTime", stopwatch.ElapsedMilliseconds);
step.AddMetadata("confidence", 0.95);
// Mark completion
step.MarkCompleted(result);
State Validation and Integrity¶
Built-in Validation¶
GraphState
implements ISerializableState
with comprehensive validation:
// Validate state integrity
var validationResult = graphState.ValidateIntegrity();
if (validationResult.IsValid)
{
Console.WriteLine("State is valid");
}
else
{
Console.WriteLine($"Validation failed: {validationResult.ErrorCount} errors");
foreach (var error in validationResult.Errors)
{
Console.WriteLine($"Error: {error.Message}");
}
}
Validation Result Details¶
Validation results provide detailed information:
var result = graphState.ValidateIntegrity();
Console.WriteLine($"Valid: {result.IsValid}");
Console.WriteLine($"Errors: {result.ErrorCount}");
Console.WriteLine($"Warnings: {result.WarningCount}");
Console.WriteLine($"Total Issues: {result.TotalIssues}");
// Get detailed summary
var summary = result.CreateSummary(includeDetails: true);
Console.WriteLine(summary);
Custom Validation¶
Extend validation with custom rules:
public static ValidationResult ValidateCustomRules(GraphState state)
{
var result = new ValidationResult();
// Check required fields
if (!state.TryGetValue<string>("userId", out _))
{
result.AddError("Required field 'userId' is missing");
}
// Validate data types
if (state.TryGetValue<int>("age", out var age) && age < 0)
{
result.AddWarning("Age should be non-negative", "data_validation");
}
// Check business rules
if (state.TryGetValue<string>("email", out var email) && !email.Contains("@"))
{
result.AddError("Invalid email format");
}
return result;
}
State Versioning and Compatibility¶
Version Management¶
GraphState
includes semantic versioning for compatibility control:
// Current version information
var currentVersion = StateVersion.Current; // "1.1.0"
var minSupported = StateVersion.MinimumSupported; // "1.0.0"
// Check version compatibility
var stateVersion = graphState.Version;
var isCompatible = stateVersion.IsCompatible; // Compatible with current version
var requiresMigration = stateVersion.RequiresMigration; // Needs migration
// Version comparison
if (stateVersion < StateVersion.Current)
{
Console.WriteLine("State version is older than current");
}
Version Parsing¶
Create version objects from strings:
// Parse version strings
var version = StateVersion.Parse("1.2.3");
Console.WriteLine($"Major: {version.Major}"); // 1
Console.WriteLine($"Minor: {version.Minor}"); // 2
Console.WriteLine($"Patch: {version.Patch}"); // 3
// Try-parse for safe version handling
if (StateVersion.TryParse("invalid", out var parsedVersion))
{
// Use parsed version
}
else
{
Console.WriteLine("Invalid version format");
}
Serialization and Persistence¶
Basic Serialization¶
Serialize state to string representation:
// Serialize with default options
var serialized = graphState.Serialize();
// Serialize with custom options
var options = new SerializationOptions
{
Indented = true,
EnableCompression = true,
IncludeMetadata = true,
IncludeExecutionHistory = true
};
var verboseSerialized = graphState.Serialize(options);
Serialization Options¶
Control what gets serialized:
var options = new SerializationOptions
{
Indented = false, // Compact JSON
EnableCompression = true, // Enable compression for large states
IncludeMetadata = true, // Include state metadata
IncludeExecutionHistory = false, // Exclude execution history
ValidateIntegrity = true // Validate before serialization
};
Deserialization¶
Restore state from serialized data:
using SemanticKernel.Graph.State;
// Deserialize with factory method
var deserializedResult = SerializableStateFactory.Deserialize<GraphState>(
serializedData,
json => JsonSerializer.Deserialize<GraphState>(json)
);
if (deserializedResult.IsSuccessful)
{
var restoredState = deserializedResult.State;
Console.WriteLine("State restored successfully");
// Check if migration was applied
if (deserializedResult.WasMigrated)
{
Console.WriteLine($"Migrated from version {deserializedResult.OriginalVersion}");
}
}
else
{
Console.WriteLine("Deserialization failed");
var summary = deserializedResult.CreateSummary();
Console.WriteLine(summary);
}
Integrity Checks¶
Validate serialized data integrity:
// Create checksum for integrity verification
var checksum = graphState.CreateChecksum();
// Validate integrity
var validationResult = graphState.ValidateIntegrity();
if (!validationResult.IsValid)
{
throw new InvalidOperationException("State integrity validation failed");
}
State Extensions and Utilities¶
KernelArguments Extensions¶
Use extension methods to work with state:
using SemanticKernel.Graph.Extensions;
var arguments = new KernelArguments
{
["input"] = "Hello World"
};
// Convert to GraphState
var graphState = arguments.ToGraphState();
// Check if already has GraphState
if (arguments.HasGraphState())
{
var existingState = arguments.GetOrCreateGraphState();
}
// Set GraphState explicitly
arguments.SetGraphState(graphState);
State Cloning and Merging¶
Create copies and merge states:
using SemanticKernel.Graph.Extensions;
// Clone state (deep copy)
var clonedState = graphState.Clone();
// Merge states (other state takes priority)
var mergedState = graphState.MergeFrom(otherState);
// Check if states are equal
var areEqual = graphState.Equals(otherState);
State Helpers¶
Use utility methods for common operations:
using SemanticKernel.Graph.State;
// Estimate serialized size
var estimatedSize = StateHelpers.EstimateSerializedSize(graphState);
// Validate serializability
var serializationValidation = StateValidator.ValidateSerializability(graphState);
// Get parameter names
var parameterNames = graphState.GetParameterNames();
Advanced State Patterns¶
State Composition¶
Build complex state structures:
// Create hierarchical state
var state = new GraphState(new KernelArguments
{
["user"] = new Dictionary<string, object>
{
["profile"] = new
{
Name = "Alice",
Email = "alice@example.com"
},
["preferences"] = new Dictionary<string, object>
{
["theme"] = "dark",
["language"] = "en"
}
},
["session"] = new Dictionary<string, object>
{
["startTime"] = DateTimeOffset.UtcNow,
["activeTab"] = "dashboard"
}
});
State Lifecycle Management¶
Manage state throughout execution:
public class StateAwareNode : IGraphNode
{
public async Task<FunctionResult> ExecuteAsync(GraphState state)
{
// Read input state
var input = state.GetValue<string>("input");
// Process and update state
var result = await ProcessInput(input);
state.SetValue("processedResult", result);
state.SetValue("processingTimestamp", DateTimeOffset.UtcNow);
// Add execution metadata
state.AddExecutionStep("StateAwareNode", "ProcessInput", DateTimeOffset.UtcNow);
return new FunctionResult(result);
}
}
State Validation Patterns¶
Implement comprehensive validation:
public static class StateValidationRules
{
public static ValidationResult ValidateUserProfile(GraphState state)
{
var result = new ValidationResult();
// Required fields validation
var requiredFields = new[] { "userId", "userName", "email" };
foreach (var field in requiredFields)
{
if (!state.TryGetValue<string>(field, out var value) || string.IsNullOrEmpty(value))
{
result.AddError($"Required field '{field}' is missing or empty");
}
}
// Data type validation
if (state.TryGetValue<int>("age", out var age))
{
if (age < 0 || age > 150)
{
result.AddWarning("Age value seems unrealistic", "data_validation");
}
}
// Business rule validation
if (state.TryGetValue<string>("email", out var email))
{
if (!email.Contains("@") || !email.Contains("."))
{
result.AddError("Invalid email format");
}
}
return result;
}
}
Best Practices¶
State Design Principles¶
- Keep State Simple: Use clear, descriptive key names
- Type Safety: Use
GetValue<T>()
for type-safe access - Validation: Validate state at key points in your workflow
- Metadata: Add meaningful metadata for debugging and monitoring
- Serialization: Consider what needs to be persisted vs. transient
Performance Considerations¶
- Large Objects: Be mindful of serialization costs for large objects
- Execution History: Limit history size for long-running workflows
- Compression: Enable compression for large states
- Validation: Use validation selectively to avoid performance impact
Error Handling¶
- Graceful Degradation: Handle missing state gracefully
- Validation: Validate state before critical operations
- Logging: Log state changes for debugging
- Recovery: Implement state recovery mechanisms
Troubleshooting¶
Common Issues¶
State Key Not Found
Solution: UseGetValueOrDefault()
or check with ContainsKey()
before reading.
Serialization Errors
Solution: Ensure all objects in state are JSON-serializable.Version Compatibility Issues
Solution: Use state migration or update your workflow to handle version differences.Large State Performance Issues
Solution: Enable compression, exclude unnecessary data, or split large states.See Also¶
- State Quickstart - Quick introduction to state management
- State Tutorial - Comprehensive state management tutorial
- Execution Model - How state flows through execution
- Checkpointing - Saving and restoring state
- Graph Concepts - Core graph concepts and patterns