Agents API
Agents API
Section titled “Agents API”The Strategos.Agents package provides integration with Microsoft.Extensions.AI for LLM-powered workflow steps.
IAgentStep<TState>
Section titled “IAgentStep<TState>”Base interface for LLM-powered workflow steps. Extends IWorkflowStep<TState> with agent-specific context.
Methods
Section titled “Methods”| Method | Parameters | Returns | Description |
|---|---|---|---|
ExecuteAsync | TState state, AgentStepContext context, CancellationToken ct | Task<StepResult<TState>> | Executes the agent step |
Example
Section titled “Example”public class AnalyzeDocumentStep : IAgentStep<DocumentState>{ private readonly IChatClient _chatClient;
public AnalyzeDocumentStep(IChatClient chatClient) { _chatClient = chatClient; }
public async Task<StepResult<DocumentState>> ExecuteAsync( DocumentState state, AgentStepContext context, CancellationToken ct) { var response = await _chatClient.GetResponseAsync( $"Analyze this document: {state.Content}", ct);
return state .With(s => s.Analysis, response) .AsResult(); }}AgentStepContext
Section titled “AgentStepContext”Extended execution context for agent steps. Inherits all properties from StepContext.
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
WorkflowId | Guid | Workflow instance identifier |
CorrelationId | string | Correlation ID for tracing |
Timestamp | DateTimeOffset | When the step execution started |
Phase | string | Current workflow phase name |
StepName | string | Current step name |
Metadata | IReadOnlyDictionary<string, object> | Additional context data |
ConversationThread | IConversationThread? | Conversation history access |
StreamingCallback | IStreamingCallback? | Real-time token streaming |
BudgetStatus | BudgetStatus | Current resource budget |
Example
Section titled “Example”public async Task<StepResult<ChatState>> ExecuteAsync( ChatState state, AgentStepContext context, CancellationToken ct){ // Access conversation history var history = context.ConversationThread?.GetMessages();
// Check budget before expensive operation if (context.BudgetStatus.Level == ScarcityLevel.Critical) { return state.With(s => s.Response, "Budget exhausted").AsResult(); }
// Stream response tokens await foreach (var chunk in _chatClient.GetStreamingResponseAsync(...)) { context.StreamingCallback?.OnToken(chunk.Text); }
// ...}IConversationalState
Section titled “IConversationalState”Interface for workflow state that includes conversation history.
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
Messages | IReadOnlyList<ChatMessage> | Conversation history |
Example
Section titled “Example”[WorkflowState]public record ChatState : IConversationalState{ public string Query { get; init; } public string Response { get; init; }
[Append] public List<ChatMessage> Messages { get; init; } = new();
IReadOnlyList<ChatMessage> IConversationalState.Messages => Messages;}IConversationThread
Section titled “IConversationThread”Interface for accessing and managing conversation history.
Methods
Section titled “Methods”| Method | Parameters | Returns | Description |
|---|---|---|---|
GetMessages | - | IReadOnlyList<ChatMessage> | Gets full conversation history |
GetRecentMessages | int count | IReadOnlyList<ChatMessage> | Gets N most recent messages |
AddMessage | ChatMessage message | void | Appends message to history |
IStreamingCallback
Section titled “IStreamingCallback”Callback interface for real-time token streaming.
Methods
Section titled “Methods”| Method | Parameters | Returns | Description |
|---|---|---|---|
OnToken | string token | void | Called for each streamed token |
OnComplete | - | void | Called when streaming completes |
OnError | Exception error | void | Called on streaming error |
Example
Section titled “Example”public class StreamingStep : IAgentStep<ChatState>{ private readonly IChatClient _chatClient;
public async Task<StepResult<ChatState>> ExecuteAsync( ChatState state, AgentStepContext context, CancellationToken ct) { var fullResponse = new StringBuilder();
await foreach (var chunk in _chatClient.GetStreamingResponseAsync( state.Query, ct)) { fullResponse.Append(chunk.Text); context.StreamingCallback?.OnToken(chunk.Text); }
context.StreamingCallback?.OnComplete();
return state .With(s => s.Response, fullResponse.ToString()) .AsResult(); }}ChatMessage
Section titled “ChatMessage”Represents a single message in a conversation.
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
Role | ChatRole | Message role (User, Assistant, System) |
Content | string | Message content |
Timestamp | DateTimeOffset | When message was created |
Metadata | Dictionary<string, object> | Additional message data |
ChatRole
Section titled “ChatRole”Enumeration of message roles.
| Value | Description |
|---|---|
System | System/instruction message |
User | User input message |
Assistant | LLM response message |
Tool | Tool/function result message |
IChatClient Integration
Section titled “IChatClient Integration”The package integrates with Microsoft.Extensions.AI.IChatClient.
Supported Providers
Section titled “Supported Providers”| Provider | Package | Registration |
|---|---|---|
| OpenAI | Microsoft.Extensions.AI.OpenAI | new OpenAIChatClient(model, apiKey) |
| Azure OpenAI | Microsoft.Extensions.AI.AzureOpenAI | new AzureOpenAIChatClient(endpoint, key) |
| Ollama | OllamaChatClient | new OllamaChatClient(model) |
Example Registration
Section titled “Example Registration”// OpenAIservices.AddSingleton<IChatClient>( new OpenAIChatClient("gpt-4o", apiKey));
// Azure OpenAIservices.AddSingleton<IChatClient>( new AzureOpenAIChatClient( new Uri("https://your-resource.openai.azure.com"), new AzureKeyCredential(apiKey), "gpt-4o"));
// Ollama (local)services.AddSingleton<IChatClient>( new OllamaChatClient("llama2"));Agent Step Patterns
Section titled “Agent Step Patterns”Simple Chat Step
Section titled “Simple Chat Step”public class SimpleChatStep : IAgentStep<ChatState>{ private readonly IChatClient _chatClient;
public async Task<StepResult<ChatState>> ExecuteAsync( ChatState state, AgentStepContext context, CancellationToken ct) { var response = await _chatClient.GetResponseAsync(state.Query, ct); return state.With(s => s.Response, response).AsResult(); }}Step with History
Section titled “Step with History”public class ConversationalStep : IAgentStep<ChatState>{ private readonly IChatClient _chatClient;
public async Task<StepResult<ChatState>> ExecuteAsync( ChatState state, AgentStepContext context, CancellationToken ct) { var messages = state.Messages .Select(m => new ChatMessage(m.Role, m.Content)) .Append(new ChatMessage(ChatRole.User, state.Query)) .ToList();
var response = await _chatClient.GetResponseAsync(messages, ct);
return state .With(s => s.Response, response) .With(s => s.Messages, state.Messages .Append(new ChatMessage { Role = ChatRole.User, Content = state.Query }) .Append(new ChatMessage { Role = ChatRole.Assistant, Content = response }) .ToList()) .AsResult(); }}Step with Streaming
Section titled “Step with Streaming”public class StreamingChatStep : IAgentStep<ChatState>{ private readonly IChatClient _chatClient;
public async Task<StepResult<ChatState>> ExecuteAsync( ChatState state, AgentStepContext context, CancellationToken ct) { var response = new StringBuilder();
await foreach (var chunk in _chatClient.GetStreamingResponseAsync( state.Query, ct)) { response.Append(chunk.Text); context.StreamingCallback?.OnToken(chunk.Text); }
context.StreamingCallback?.OnComplete();
return state.With(s => s.Response, response.ToString()).AsResult(); }}