Serenity Star SDK for .NET
Official .NET SDK for Serenity Star API. The Serenity Star .NET SDK provides a comprehensive interface for interacting with Serenity's different types of agents, such as activities, assistants, proxies, and chat completions.
Table of Contents
- Installation
- Getting Started
- Assistants / Copilots
- Activities
- AI Proxy
- Chat Completions
- Volatile Knowledge
- Best Practices
Installation
Install the package via NuGet Package Manager:
dotnet add package SubgenAI.SerenityStar.SDK
Or via Package Manager Console:
Install-Package SubgenAI.SerenityStar.SDK
Getting Started
This section will guide you through the initial setup and usage of the Serenity Star SDK.
Direct Instantiation with Factory Method
To directly instantiate the SerenityClient, you can use the static Create method. This requires an API key which you can obtain from your Serenity Star account.
using SerenityStar.Client;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create and execute an activity agent
Activity activity = client.Agents.Activities.Create("marketing-campaign");
AgentResult response = await activity.ExecuteAsync();
Console.WriteLine(response.Content);
Direct Instantiation with Builder Pattern
For more control over the client configuration, use the builder pattern:
using SerenityStar.Client;
using SerenityStar.Agents.System;
SerenityClient client = new SerenityClientBuilder()
.WithApiKey("your-api-key")
.WithBaseUrl("https://api.serenitystar.ai") // Optional
.WithTimeout(30) // Optional
.Build();
// Create and execute an activity agent
Activity activity = client.Agents.Activities.Create("marketing-campaign");
AgentResult response = await activity.ExecuteAsync();
Console.WriteLine(response.Content);
Using a Custom HttpClient
If you need to use a custom HttpClient (for example, with specific handlers or configurations):
using SerenityStar.Client;
using SerenityStar.Agents.System;
HttpClient customHttpClient = new HttpClient();
// Configure your custom HttpClient as needed
SerenityClient client = new SerenityClientBuilder()
.WithApiKey("your-api-key")
.WithHttpClient(customHttpClient)
.Build();
// Create and execute an activity agent
Activity activity = client.Agents.Activities.Create("marketing-campaign");
AgentResult response = await activity.ExecuteAsync();
Console.WriteLine(response.Content);
Using Dependency Injection
For ASP.NET Core applications, you can register the client with dependency injection:
// In your startup/program.cs
using SerenityStar.Extensions;
services.AddSerenityStar("your-api-key");
// With custom base URL and timeout
services.AddSerenityStar(
apiKey: "your-api-key",
timeoutSeconds: 60,
baseUrl: "https://custom-api.serenitystar.ai"
);
Then inject and use the client in your services:
using SerenityStar.Agents.System;
public class YourService
{
private readonly ISerenityClient _client;
public YourService(ISerenityClient client)
{
_client = client;
}
public async Task DoSomething()
{
Activity activity = _client.Agents.Activities.Create("marketing-campaign");
AgentResult response = await activity.ExecuteAsync();
Console.WriteLine(response.Content);
}
}
Assistants / Copilots
Assistants and Copilots are conversational agents that maintain context across multiple messages. They're perfect for building chatbots, virtual assistants, and interactive applications. Both provide the same functionality - choose the terminology that best fits your use case.
Create a Conversation and Send Messages
using SerenityStar.Client;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Using Assistants
Conversation conversation = client.Agents.Assistants.CreateConversation("chef-assistant");
// Or using Copilots (same functionality)
Conversation copilotConversation = client.Agents.Copilots.CreateConversation("chef-assistant");
// First message - creates the conversation in Serenity Star automatically
AgentResult response = await conversation.SendMessageAsync("I would like to get a recipe for parmesan chicken");
Console.WriteLine(response.Content);
Console.WriteLine($"Conversation ID: {conversation.ConversationId}");
// Subsequent messages use the conversation ID automatically
AgentResult response2 = await conversation.SendMessageAsync("Can you suggest a side dish?");
Console.WriteLine(response2.Content);
Resume an Existing Conversation
Use this when you don't already have a Conversation instance in memory, for example, when you load a stored conversation ID from your database:
// Resume a conversation using an existing conversation ID with Assistants
Conversation existingConversation = client.Agents.Assistants.CreateConversation(
"chef-assistant",
conversationId: "existing-conversation-id"
);
// Or with Copilots
Conversation existingCopilot = client.Agents.Copilots.CreateConversation(
"chef-assistant",
conversationId: "existing-conversation-id"
);
AgentResult response = await existingConversation.SendMessageAsync("What was the recipe you suggested earlier?");
Console.WriteLine(response.Content);
Get Conversation Information
You can retrieve detailed information about an assistant/copilot agent, including its configuration, capabilities, and metadata. This is useful for understanding what parameters the agent accepts and how it's configured.
using SerenityStar.Models.Conversation;
using SerenityStar.Models.Execute;
// Get basic agent information by code (works with both Assistants and Copilots)
ConversationInfoResult agentInfo = await client.Agents.Assistants.GetInfoByCodeAsync("chef-assistant");
Console.WriteLine($"Initial Message: {agentInfo.Conversation.InitialMessage}");
Console.WriteLine($"Starters: {string.Join(", ", agentInfo.Conversation.Starters)}");
Console.WriteLine($"Version: {agentInfo.Agent.Version}");
Console.WriteLine($"Vision Enabled: {agentInfo.Agent.VisionEnabled}");
Console.WriteLine($"Is Realtime: {agentInfo.Agent.IsRealtime}");
if (agentInfo.Channel != null)
Console.WriteLine($"Channel: {agentInfo.Channel}");
Console.WriteLine($"Image ID: {agentInfo.Agent.ImageId}");
Advanced example with options:
ConversationInfoResult agentInfoAdvanced = await client.Agents.Assistants.GetInfoByCodeAsync(
"chef-assistant",
new AgentExecutionReq
{
AgentVersion = 2,
InputParameters = new Dictionary<string, object>
{
["dietaryRestrictions"] = "vegetarian",
["cuisinePreference"] = "italian",
["skillLevel"] = "beginner"
},
UserIdentifier = "user-123",
Channel = "web"
}
);
Console.WriteLine($"Initial Message: {agentInfoAdvanced.Conversation.InitialMessage}");
Console.WriteLine($"Starters: {string.Join(", ", agentInfoAdvanced.Conversation.Starters)}");
Console.WriteLine($"Version: {agentInfoAdvanced.Agent.Version}");
Get Conversation by ID
You can retrieve an existing conversation by its ID, including all messages and metadata:
using SerenityStar.Models.Conversation;
SerenityClient client = SerenityClient.Create("your-api-key");
// Get conversation by id (basic example)
ConversationRes conversation = await client.Agents.Assistants.GetConversationByIdAsync(
"chef-assistant",
"conversation-id-here"
);
Console.WriteLine($"Conversation ID: {conversation.Id}");
Console.WriteLine($"Is Open: {conversation.Open}");
Console.WriteLine($"Message Count: {conversation.Messages.Count}");
// Display all messages
foreach (ConversationMessage message in conversation.Messages)
Console.WriteLine($"{message.Role}: {message.Content}");
// Get conversation by id with executor task logs
ConversationRes conversationWithLogs = await client.Agents.Assistants.GetConversationByIdAsync(
"chef-assistant",
"conversation-id-here",
new GetConversationOptions
{
ShowExecutorTaskLogs = true
}
);
Console.WriteLine($"Executor Task Logs: {conversationWithLogs.ExecutorTaskLogs}");
Stream Message with SSE
You can stream responses from assistant agents using Server-Sent Events (SSE). This is useful for real-time response processing and providing a better user experience with progressive message display.
using SerenityStar.Client;
using SerenityStar.Models.Streaming;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create a conversation with an assistant
Conversation conversation = client.Agents.Assistants.CreateConversation("chef-assistant");
// Stream a message - get updates as they arrive
await foreach (StreamingAgentMessage message in conversation.StreamMessageAsync("Tell me a quick recipe"))
{
switch (message)
{
case StreamingAgentMessageStart start:
Console.WriteLine("Stream started");
break;
case StreamingAgentMessageContent content:
Console.Write(content.Text); // Display content as it arrives
break;
case StreamingAgentMessageTaskStart taskStart:
Console.WriteLine($"Task started: {taskStart.TaskKey}");
break;
case StreamingAgentMessageTaskStop taskStop:
Console.WriteLine($"Task completed: {taskStop.TaskKey} (Duration: {taskStop.Duration.TotalMilliseconds}ms)");
break;
case StreamingAgentMessageStop stop:
Console.WriteLine("\nStream completed");
Console.WriteLine($"Conversation ID: {stop.Result?.InstanceId}");
if (stop.Result?.CompletionUsage != null)
{
Console.WriteLine($"Tokens used - Input: {stop.Result.CompletionUsage.PromptTokens}, Output: {stop.Result.CompletionUsage.CompletionTokens}");
}
break;
case StreamingAgentMessageError error:
Console.WriteLine($"Error: {error.Message}");
break;
}
}
Stream Subsequent Messages
Once a conversation is created, you can stream additional messages using the same conversation instance:
// First message stream (creates the conversation)
await foreach (StreamingAgentMessage message in conversation.StreamMessageAsync("What's a healthy breakfast?"))
{
if (message is StreamingAgentMessageContent content)
Console.Write(content.Text);
}
// Subsequent message stream (uses existing conversation)
await foreach (StreamingAgentMessage message in conversation.StreamMessageAsync("Can you add protein options?"))
{
if (message is StreamingAgentMessageContent content)
Console.Write(content.Text);
}
Stream with Execution Options
You can customize the streaming behaviour with execution options:
// Create conversation with options
Conversation conversation = client.Agents.Assistants.CreateConversation(
"chef-assistant",
options: new AgentExecutionReq
{
InputParameters = new Dictionary<string, object>
{
["mealType"] = "dinner",
["servings"] = 4
},
UserIdentifier = "user-456",
Channel = "mobile-app",
AgentVersion = 2
}
);
// Stream message with the configured options
await foreach (StreamingAgentMessage message in conversation.StreamMessageAsync("I need a recipe"))
{
if (message is StreamingAgentMessageContent content)
Console.Write(content.Text);
}
Message Feedback
You can collect user feedback on agent responses to help improve the quality of your assistant.
Submit Feedback
using SerenityStar.Client;
using SerenityStar.Models.MessageFeedback;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create conversation with an assistant
Conversation conversation = client.Agents.Assistants.CreateConversation("chef-assistant");
// Send a message
AgentResult response = await conversation.SendMessageAsync("I would like to get a recipe for parmesan chicken");
// Submit positive feedback (thumbs up)
await conversation.SubmitFeedbackAsync(new SubmitFeedbackReq
{
AgentMessageId = response.AgentMessageId!.Value,
Feedback = true
});
// Or submit negative feedback (thumbs down)
await conversation.SubmitFeedbackAsync(new SubmitFeedbackReq
{
AgentMessageId = response.AgentMessageId!.Value,
Feedback = false
});
Remove Feedback
using SerenityStar.Client;
using SerenityStar.Models.MessageFeedback;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create conversation with an assistant
Conversation conversation = client.Agents.Assistants.CreateConversation("chef-assistant");
// Send a message
AgentResult response = await conversation.SendMessageAsync("I would like to get a recipe for parmesan chicken");
// Submit feedback first
await conversation.SubmitFeedbackAsync(new SubmitFeedbackReq
{
AgentMessageId = response.AgentMessageId!.Value,
Feedback = true
});
// Remove the feedback if the user changes their mind
await conversation.RemoveFeedbackAsync(new RemoveFeedbackReq
{
AgentMessageId = response.AgentMessageId!.Value
});
Connector Status
Check the connection status of an agent's connector:
using SerenityStar.Client;
using SerenityStar.Models.Connector;
using SerenityStar.Models.Execute;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create conversation with an assistant
Conversation conversation = client.Agents.Assistants.CreateConversation("chef-assistant");
// Send a message that might require a connector
AgentResult response = await conversation.SendMessageAsync("I need a summary of my latest meeting notes stored in google drive");
// Check if there are pending actions (e.g., authentication required)
if (response.PendingActions.Count > 0)
{
foreach (PendingAction action in response.PendingActions)
{
if (action is PendingAction.Connection connectionAction)
{
Console.WriteLine($"Authentication required for {connectionAction.ConnectorName}");
Console.WriteLine($"Please visit: {connectionAction.Url}");
// Here the user should complete the authentication process.
// Check connector status for this conversation (you can use a loop to check every 5 seconds)
ConnectorStatusRes status = await conversation.GetConnectorStatusAsync(connectionAction.ConnectorId);
Console.WriteLine($"Is Connected: {status.IsConnected}");
// You can use this to determine if a connector needs authentication
if (!status.IsConnected)
{
Console.WriteLine("Connector is not connected. Please authenticate.");
// Wait and check again...
}
}
}
}
// Once connected, send the message again
// The agent will now have access to Google Drive to retrieve the meeting notes
AgentResult newResponse = await conversation.SendMessageAsync("I need a summary of my latest meeting notes stored in google drive");
Console.WriteLine(newResponse.Content);
Activities
Activities are single-execution agents designed for one-time tasks like translations, data processing, or content generation. Unlike assistants, they don't maintain conversation history.
Execute an Activity Agent
using SerenityStar.Client;
using SerenityStar.Models.Execute;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create and execute activity (basic example)
Activity activity = client.Agents.Activities.Create("translator-activity");
AgentResult response = await activity.ExecuteAsync();
Console.WriteLine(response.Content);
Advanced example with parameters:
// Create and execute activity (advanced example)
Activity activityAdvanced = client.Agents.Activities.Create(
"translator-activity",
new AgentExecutionReq
{
InputParameters = new Dictionary<string, object>
{
["targetLanguage"] = "russian",
["textToTranslate"] = "hello world"
}
}
);
AgentResult responseAdvanced = await activityAdvanced.ExecuteAsync();
Console.WriteLine(responseAdvanced.Content); // Привет, мир!
Console.WriteLine($"Completion Usage: {responseAdvanced.CompletionUsage?.TotalTokens}");
if (responseAdvanced.ExecutorTaskLogs != null)
foreach (AgentResult.Task log in responseAdvanced.ExecutorTaskLogs)
Console.WriteLine($"Task: {log.Description}, Duration: {log.Duration}ms, Success: {log.Success}");
Stream Activity with SSE
Activities support streaming responses using Server-Sent Events (SSE). This allows you to process results as they're generated.
using SerenityStar.Client;
using SerenityStar.Models.Streaming;
using SerenityStar.Models.Execute;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create an activity with options
Activity activity = client.Agents.Activities.Create(
"translator-activity",
new AgentExecutionReq
{
InputParameters = new Dictionary<string, object>
{
["textToTranslate"] = "hello world",
["targetLanguage"] = "spanish"
}
}
);
// Stream the response
await foreach (StreamingAgentMessage message in activity.StreamAsync())
{
switch (message)
{
case StreamingAgentMessageStart:
Console.WriteLine("Translation started...");
break;
case StreamingAgentMessageContent content:
Console.Write(content.Text);
break;
case StreamingAgentMessageTaskStart taskStart:
Console.WriteLine($"Task: {taskStart.TaskKey}");
break;
case StreamingAgentMessageTaskStop taskStop:
Console.WriteLine($"Task completed in {taskStop.Duration.TotalMilliseconds}ms");
break;
case StreamingAgentMessageStop stop:
Console.WriteLine($"\nTranslation complete!");
if (stop.Result?.CompletionUsage != null)
Console.WriteLine($"Tokens used: {stop.Result.CompletionUsage.TotalTokens}");
break;
case StreamingAgentMessageError error:
Console.WriteLine($"Error: {error.Message}");
break;
}
}
AI Proxy
AI Proxy provides direct access to AI models with consistent interfaces across different providers. They're ideal when you need fine-grained control over model parameters.
Execute a Proxy Agent
using SerenityStar.Client;
using SerenityStar.Models.AIProxy;
using SerenityStar.Models.Execute;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create and execute a proxy agent
Proxy proxy = client.Agents.AIProxy.Create(
"proxy-agent",
new ProxyExecutionReq
{
Model = "gpt-4o-mini-2024-07-18",
Messages = new List<ProxyExecutionMessage>
{
new ProxyExecutionMessage
{
Role = "system",
Content = "You are a helpful AI assistant specialized in explaining complex topics."
},
new ProxyExecutionMessage
{
Role = "user",
Content = "What is artificial intelligence?"
}
},
Temperature = 0.7,
MaxTokens = 500
}
);
AgentResult response = await proxy.ExecuteAsync();
Console.WriteLine(response.Content);
Console.WriteLine(response.CompletionUsage);
Console.WriteLine(response.ExecutorTaskLogs);
Stream Proxy with SSE
AI Proxy supports streaming responses, perfect for real-time AI model interactions:
using SerenityStar.Client;
using SerenityStar.Models.AIProxy;
using SerenityStar.Models.Streaming;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create a proxy for streaming
ProxyExecutionReq options = new()
{
Model = "gpt-4o-mini-2024-07-18",
Messages = new List<ChatCompletionMessage>
{
new() { Role = "user", Content = "Write a short poem about programming" }
},
Temperature = 0.7f,
MaxTokens = 200
};
Proxy proxy = client.Agents.AIProxy.Create("openai-proxy", options);
// Stream the response
Console.WriteLine("Poem: ");
await foreach (StreamingAgentMessage message in proxy.StreamAsync())
{
switch (message)
{
case StreamingAgentMessageStart:
break; // Generation started
case StreamingAgentMessageContent content:
Console.Write(content.Text); // Print each chunk as it arrives
break;
case StreamingAgentMessageTaskStart taskStart:
Console.WriteLine($"\nStarting: {taskStart.Key}");
break;
case StreamingAgentMessageTaskStop taskStop:
Console.WriteLine($"Completed in {taskStop.Duration.TotalMilliseconds}ms");
break;
case StreamingAgentMessageStop stop:
Console.WriteLine("\n\nGeneration complete!");
if (stop.Result?.CompletionUsage != null)
{
Console.WriteLine($"Input tokens: {stop.Result.CompletionUsage.PromptTokens}");
Console.WriteLine($"Output tokens: {stop.Result.CompletionUsage.CompletionTokens}");
}
break;
case StreamingAgentMessageError error:
Console.WriteLine($"Error: {error.Message}");
break;
}
}
Proxy Execution Options
The following options can be passed when executing a proxy agent via ProxyExecutionReq:
using SerenityStar.Client;
using SerenityStar.Models.AIProxy;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
Proxy proxy = client.Agents.AIProxy.Create(
"proxy-agent",
new ProxyExecutionReq
{
// Specify the model to use
Model = "gpt-4-turbo",
// Define conversation messages
Messages = new List<ProxyExecutionMessage>
{
new ProxyExecutionMessage
{
Role = "system",
Content = "You are a knowledgeable AI assistant."
},
new ProxyExecutionMessage
{
Role = "user",
Content = "Can you explain the theory of relativity in simple terms?"
}
},
// Model parameters
Temperature = 0.7, // Controls randomness (0-1)
MaxTokens = 500, // Maximum length of response
TopP = 0.9, // Nucleus sampling parameter
TopK = 50, // Top-k sampling parameter
FrequencyPenalty = 0.5, // Reduces repetition (-2 to 2)
PresencePenalty = 0.2, // Encourages new topics (-2 to 2)
// Additional options
Vendor = "openai", // AI provider
UserIdentifier = "user_123", // Unique user ID
GroupIdentifier = "org_456", // Organization ID
UseVision = false // Enable/disable vision features
}
);
AgentResult response = await proxy.ExecuteAsync();
Chat Completions
Chat Completions provide a simplified interface for single-turn or multi-turn conversations without the overhead of managing conversation instances.
Execute a Chat Completion
using SerenityStar.Client;
using SerenityStar.Models.ChatCompletion;
using SerenityStar.Models.Execute;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create and execute chat completion (basic example)
ChatCompletion chatCompletion = client.Agents.ChatCompletions.Create("AgentCreator", new ChatCompletionReq
{
Message = "Hello!!!"
});
AgentResult response = await chatCompletion.ExecuteAsync();
Console.WriteLine(response.Content);
Console.WriteLine($"Completion Usage: {response.CompletionUsage?.TotalTokens}");
Advanced example:
// Create and execute chat completion (advanced example)
ChatCompletion chatCompletionAdvanced = client.Agents.ChatCompletions.Create("Health-Coach", new ChatCompletionReq
{
UserIdentifier = "user-123",
AgentVersion = 2,
Channel = "web",
VolatileKnowledgeIds = new List<string> { "knowledge-1", "knowledge-2" },
Message = "Hi! How can I eat healthier?",
Messages = new List<ChatCompletionMessage>
{
new ChatCompletionMessage
{
Role = "assistant",
Content = "Hi there! How can I assist you?"
}
}
});
AgentResult responseAdvanced = await chatCompletionAdvanced.ExecuteAsync();
Console.WriteLine(responseAdvanced.Content);
Console.WriteLine($"Completion Usage: {responseAdvanced.CompletionUsage?.TotalTokens}");
Stream Chat Completion with SSE
Chat completions support streaming for real-time chat interactions:
using SerenityStar.Client;
using SerenityStar.Models.ChatCompletion;
using SerenityStar.Models.Streaming;
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create a chat completion for streaming
ChatCompletion chatCompletion = client.Agents.ChatCompletions.Create(
"assistant-chat",
new ChatCompletionReq
{
Message = "Explain quantum computing in simple terms",
UserIdentifier = "user-123"
}
);
// Stream the response
Console.WriteLine("Answer: ");
await foreach (StreamingAgentMessage message in chatCompletion.StreamAsync())
{
switch (message)
{
case StreamingAgentMessageStart:
break; // Stream initialized
case StreamingAgentMessageContent content:
Console.Write(content.Text); // Print each chunk
break;
case StreamingAgentMessageTaskStart taskStart:
Console.WriteLine($"\n[Processing: {taskStart.TaskKey}]");
break;
case StreamingAgentMessageTaskStop taskStop:
Console.WriteLine($"[Task completed in {taskStop.Duration.TotalMilliseconds}ms]");
break;
case StreamingAgentMessageStop stop:
Console.WriteLine("\n\n[Response complete]");
if (stop.Result?.CompletionUsage != null)
{
Console.WriteLine($"Tokens - Input: {stop.Result.CompletionUsage.PromptTokens}, Output: {stop.Result.CompletionUsage.CompletionTokens}");
}
if (stop.Result?.TimeToFirstToken.HasValue == true)
{
Console.WriteLine($"Time to first token: {stop.Result.TimeToFirstToken}ms");
}
break;
case StreamingAgentMessageError error:
Console.WriteLine($"[Error: {error.Message}]");
break;
}
}
Volatile Knowledge
Volatile knowledge allows you to upload temporary documents that can be used in agent executions. These documents are processed and made available for a limited time based on your configuration. The volatile knowledge is scoped to the conversation or activity it's uploaded to and is automatically included in the next message.
Upload and Use Volatile Knowledge in a Conversation
using SerenityStar.Client;
using SerenityStar.Agents.Conversational;
using SerenityStar.Models.VolatileKnowledge;
SerenityClient client = SerenityClient.Create("your-api-key");
// Step 1: Create a conversation
Conversation conversation = client.Agents.Assistants.CreateConversation("chef-assistant");
// Step 2: Upload volatile knowledge to the conversation
using FileStream fileStream = File.OpenRead("document.pdf");
UploadVolatileKnowledgeReq uploadRequest = new()
{
FileStream = fileStream,
FileName = "document.pdf"
};
VolatileKnowledgeRes knowledge = await conversation.VolatileKnowledge.UploadAsync(uploadRequest);
Console.WriteLine($"Uploaded knowledge ID: {knowledge.Id}, Status: {knowledge.Status}");
// Step 3: Check status until ready
VolatileKnowledgeRes response = await conversation.VolatileKnowledge.GetStatusAsync(knowledge.Id);
// Wait until the knowledge is ready
while (response.Status != "success" && response.Status != "error")
{
await Task.Delay(1000);
response = await conversation.VolatileKnowledge.GetStatusAsync(knowledge.Id);
}
if (response.Status == "error")
Console.WriteLine($"Processing failed: {response.Error}");
else
{
// Step 4: Send a message - the volatile knowledge is automatically included
AgentResult result = await conversation.SendMessageAsync("What does the document say about cooking techniques?");
Console.WriteLine(result.Content);
// The volatile knowledge is automatically cleared after sending the message
// Subsequent messages won't include it unless you upload new knowledge
}
Upload Volatile Knowledge with Text Content
Conversation conversation = client.Agents.Assistants.CreateConversation("research-assistant");
UploadVolatileKnowledgeReq uploadRequest = new()
{
Content = "https://serenitystar.ai"
};
VolatileKnowledgeRes knowledge = await conversation.VolatileKnowledge.UploadAsync(uploadRequest);
Console.WriteLine($"Uploaded knowledge ID: {knowledge.Id}, Status: {knowledge.Status}");
Upload with Custom Parameters
Conversation conversation = client.Agents.Assistants.CreateConversation("data-analyst");
using FileStream fileStream = File.OpenRead("document.pdf");
UploadVolatileKnowledgeReq uploadRequest = new()
{
FileStream = fileStream,
FileName = "document.pdf",
CallbackUrl = "https://your-app.com/knowledge-callback"
};
VolatileKnowledgeRes knowledge = await conversation.VolatileKnowledge.UploadAsync(
uploadRequest,
processEmbeddings: true, // Process embeddings for semantic search
noExpiration: false, // Allow expiration
expirationDays: 7); // Expire in 7 days
Console.WriteLine($"Uploaded knowledge ID: {knowledge.Id}");
if (knowledge.ExpirationDate.HasValue)
Console.WriteLine($"Expires on: {knowledge.ExpirationDate.Value}");
Use Volatile Knowledge with Activities
using SerenityStar.Agents.System;
SerenityClient client = SerenityClient.Create("your-api-key");
// Create an activity
Activity activity = client.Agents.Activities.Create("document-analyzer");
// Upload volatile knowledge to the activity
using FileStream fileStream = File.OpenRead("report.pdf");
UploadVolatileKnowledgeReq uploadRequest = new()
{
FileStream = fileStream,
FileName = "report.pdf"
};
VolatileKnowledgeRes knowledge = await activity.VolatileKnowledge.UploadAsync(uploadRequest);
// Wait for processing
VolatileKnowledgeRes response = await activity.VolatileKnowledge.GetStatusAsync(knowledge.Id);
while (response.Status != "success" && response.Status != "error")
{
await Task.Delay(1000);
response = await activity.VolatileKnowledge.GetStatusAsync(knowledge.Id);
}
if (response.Status == "success")
{
// Execute the activity - volatile knowledge is automatically included
AgentResult result = await activity.ExecuteAsync();
Console.WriteLine(result.Content);
// Volatile knowledge is cleared after execution
}
Multiple Knowledge Documents
You can upload multiple documents to the same conversation or activity. All uploaded documents will be included in the next message and then automatically cleared.
Conversation conversation = client.Agents.Assistants.CreateConversation("multi-doc-assistant");
// Upload first document
using (FileStream file1 = File.OpenRead("doc1.pdf"))
{
VolatileKnowledgeRes knowledge1 = await conversation.VolatileKnowledge.UploadAsync(new()
{
FileStream = file1,
FileName = "doc1.pdf"
});
// Wait for processing
while ((await conversation.VolatileKnowledge.GetStatusAsync(knowledge1.Id)).Status == "analyzing")
await Task.Delay(1000);
}
// Upload second document
using (FileStream file2 = File.OpenRead("doc2.pdf"))
{
VolatileKnowledgeRes knowledge2 = await conversation.VolatileKnowledge.UploadAsync(new()
{
FileStream = file2,
FileName = "doc2.pdf"
});
// Wait for processing
while ((await conversation.VolatileKnowledge.GetStatusAsync(knowledge2.Id)).Status == "analyzing")
await Task.Delay(1000);
}
// Both documents are included in this message
AgentResult result = await conversation.SendMessageAsync("What can you say me about doc1 and doc2?");
Console.WriteLine(result.Content);
// Both documents are cleared after the message is sent
Best Practices
- Error Handling: Always handle exceptions such as
HttpRequestExceptionwhen making API calls to ensure your application can gracefully handle errors. - Cancellation Tokens: Use
CancellationTokento manage request cancellations, especially for long-running operations. - Dependency Injection: Integrate the
SerenityClientusing dependency injection for better testability and manageability of your application. - Streaming for UX: Use SSE streaming for real-time responses to provide a better user experience with progressive message display.
- Volatile Knowledge Lifecycle: Remember that volatile knowledge is automatically cleared after some time, so upload documents before each interaction that requires them.
This documentation provides a comprehensive overview of the Serenity Star .NET SDK, including installation, usage examples for all agent types, streaming capabilities, and best practices. For further information, please refer to the official repository.