How to create an agent to your cluster
Note
This page is about the in-app chatbot agent you configure in Neos Studio for the end users of a cluster. For the AI coding assistant that helps developers build Neos clusters from Claude Code or GitHub Copilot, see Neos Copilot.
Configure AI Models
You must configure AI models in Neos Studio.
A model must have an unique name, the model ID and the provider.
Model identifier
When using a model hosted on Microsoft Foundry, the model ID must be the deployment ID. By default, the deployment ID is the same as the model ID, but the same model can be deployed multiple times with different deployment IDs.
Providers
We support the following providers : OpenAI, Anthropic, Google, Mistral, Hugging Face, Ollama.
You can use models hosted on Microsoft Foundry, AWS Bedrock, OpenRouter, ...
Optional properties
The organization ID is deprecated and is specific to the official OpenAI provider: Previously, the API key generated on the developer portal was not linked to an organization. Now that it is, there is no longer any need to provide it.
In the model capabilities, you must add :
TextGenerationto be able to use it in the chatbot or invoke it by code.Embeddingsto be able to generate embeddings.
Configure secrets
There are 2 secrets to set to be able to use AI models:
- The API key which is always required except when using Ollama since the model will be hosted locally.
- The endpoint which is optional when using the provider's official endpoint, but required when using an alternative endpoint such as Microsoft Foundry.
Development
This is the recommended way in development mode.
To set user secrets, you must execute the following commands:
dotnet user-secrets set "AI:[Provider]:ApiKey" "[ApiKey]" --id "[ClusterRootNamespace].AspNetCore"
dotnet user-secrets set "AI:[Provider]:ApiEndpoint" "[ApiEndpoint]" --id "[ClusterRootNamespace].AspNetCore"
The cluster root namespace can be found in the cluster configuration file.
For example, to use OpenAI models hosted on Microsoft Foundry on TechnicalDemos, you will need to execute:
dotnet user-secrets set "AI:OpenAI:ApiKey" "..." --id "TechnicalDemos.AspNetCore"
dotnet user-secrets set "AI:OpenAI:ApiEndpoint" "https://neosazopenaisweden.openai.azure.com/openai/v1" --id "TechnicalDemos.AspNetCore"
You can override the secrets for a specific model by adding the model name instead of the provider name:
dotnet user-secrets set "AI:AzureGpt56Terra:ApiKey" "..." --id "TechnicalDemos.AspNetCore"
dotnet user-secrets set "AI:AzureGpt56Terra:ApiEndpoint" "https://neosazopenaisweden.openai.azure.com/openai/v1" --id "TechnicalDemos.AspNetCore"
Production
In Kubernetes, the recommended way is to set the secrets in a store.
| Key | Value |
|---|---|
| AI:[Provider]:ApiKey | The API key (requires) |
| AI:[Provider]:ApiEndpoint | The endpoint (optional) |
For example, with a OpenAI model hosted on Microsoft Foundry:
| Key | Value |
|---|---|
| AI:OpenAI:ApiKey | ... |
| AI:OpenAI:ApiEndpoint | https://neosazopenaisweden.openai.azure.com/openai/v1 |
You can override the secrets for a specific model by adding the model name instead of the provider name:
| Key | Value |
|---|---|
| AI:AzureGpt56Terra:ApiKey | ... |
| AI:AzureGpt56Terra:ApiEndpoint | https://neosazopenaisweden.openai.azure.com/openai/v1 |
Create an Agent
Then, you must configure an agent in Neos Studio.
| Property | Description | Example |
|---|---|---|
| Identifier | A unique name | OrderCreator |
| Name | The displayed name in the chatbot | Bob |
| ModelName | The model name configured in the previous step | AzureGpt56Terra |
| IconName | The name of the icon displayed in the chatbot | OrderIcon |
| Temperature | What sampling temperature to use. Higher values mean the model will take more risks. Try 0.9 for more creative applications and 0 (argmax sampling) for ones with a well-defined answer. | 0.9 |
| TopP | An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with the top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered | 1 |
| MaxTokens | The maximum number of tokens to generate in the completion. | |
| ReasoningEffort | The reasoning effort to use for the agent. The higher the reasoning effort, the more the agent will try to find a solution to the user's request. Available only for OpenAI models that support reasoning. | Medium |
| IncludeSkillInstructions | If true, the instructions of the skills used by the agent will be included in the prompt sent to the model. If false you can include them by using handlebars in the agent prompt | True |
| Description | A localized string to describe the agent | en: Order creator, fr: Créateur de commande |
| Instructions | A system-level instruction to guide your model's behavior throughout the conversation. The assistant refers to himself in the first person singular. | I'm an assistant that helps the user to create orders |
| Skills | The skills of your agent. You should select one or more skills provided by Neos or your own skills | OrderCreation |
Note
When you create an agent, you need to generate the cluster to apply the changes. When you edit an agent except its name, you do not need to generate the cluster, the changes are applied immediately after saving.
Warning
The agent is not visible in the chatbot if the API Key or API endpoint are not configured.
Skills provided by Neos
Neos provides several skills that you can use to extend the capabilities of your agent. You don't need to reference the functions of these skills in the instructions of the agent, they are automatically available for the assistant.
EntitiesExplorer Skill
Provides functionalities to explore entities.
You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IEntitiesExplorerSkill interface.
You must include this skill if the agent needs to explore entities to find an entity needed to perform an action asked by the user. Only entities with read permission will be provided.
Functions provided by this skill:
| Function name | C# Method name | Description |
|---|---|---|
| GetAllEntities | Task |
Provides a markdown list of all entities with their description. Only entities with read permission will be provided. |
| GetEntityProperties | Task |
Provides a markdown list of all entity properties with their caption and description for the specified entity. Navigation properties to unauthorized entities will not be provided. Properties without caption and AI description will not be provided, so you can hide a property to an agent. |
| GetEnumValues | string GetEnum(string enumName) | Provides a markdown list of all enum members with their caption for the specified enum. |
EntitiesQuerierSkill
Provides functionalities to query entities. You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IEntitiesQuerierSkill interface.
You must include this skill if the agent needs to query entities with EF Linq queries.
Functions provided by this skill:
| Function name | C# Method name | Description |
|---|---|---|
| QueryExpressionEvaluator | Task | Parse the C# code and return the result of its execution. |
Note
The QueryExpressionEvaluator can only access on entities repositories with read permission, otherwise an exception will be thrown.
The expression query created by the agent is checked by the QueryExpressionEvaluator to avoid used of unauthorized entities.
So you must check if the entity is authorized if your cluster used the user permissions module.
Note
Security considerations
This skill executes C# code provided by the LLM. To avoid security issues, the code is parsed and checked to ensure that it does not contain any malicious code. Therefore, the code have a maximum execution time of 30 seconds by default. You can change this value in the Yaml configuration file of your cluster, for example to set the maximum execution time to 10 seconds:
AI:
EntityQuerierSkill:
ExecutionTimeout: 10
Note
Performance considerations
This skill executes C# code provided by the LLM using the Roslyn compiler. Every time the agent calls this skill, the code is parsed and compiled, which uses memory resources.
By default the concurrency level is set to 5, which means that only five pieces of code can be executed at a time, the others will be queued and wait up to 30 seconds before being executed.
You can change this value in the Yaml configuration file of your cluster, for example to set the concurrency level to 3:
AI:
EntityQuerierSkill:
MaxConcurrency: 3
You can also set the maximum time to wait for the code to be executed, by default it is set to 30 seconds, you can change this value in the Yaml configuration file of your cluster, for example to set the maximum waiting time to 10 seconds:
AI:
EntityQuerierSkill:
WaitTimeoutSeconds: 10
If this time is exceeded, an exception will be thrown.
EntityViewsExplorer Skill
Provides functionalities to explore entity views.
You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IEntitiesExplorerSkill interface.
You must include this skill if the agent needs to explore entity views to find an entity view needed to perform an action asked by the user. For example to create an order, the agent needs to explore the entity views in order to find the appropriate entity view to create an Order.
Functions provided by this skill:
| Function name | Description |
|---|---|
| string GetReadableEntityViews() | Provides a markdown list of all entity views with their description. Only entity views with read permission will be provided. |
| string GetWritableEntityViews() | Provides a markdown list of all entity views with their description. Only entity views with create, update or delete permission will be provided. |
| string GetEntityProperties(string entityViewName) | Provides a markdown list of all entity view property with their description for the specified entity View. |
EntityViewQuerierSkill
Provides functionalities to query entity views.
You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IEntitiesQuerierSkill interface.
You must include this skill if the agent needs to query entity views. For example to get the average price of a product, the agent needs to query the entity views to get the price of the product.
Functions provided by this skill:
| Function name | Description |
|---|---|
| string HowToDoODataQuery() | Provide instructions to create an ODataQuery |
DataCreatorSkill
Provides functionalities to create data.
You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IDataCreatorSkill interface.
You must include this skill if the agent needs to create data. For example to create an employee, the agent needs to create an JSON schema to create a JSON string and send it to the API.
Functions provided by this skill:
| Function name | Description |
|---|---|
| string? GetEntityViewJsonSchema(string entityViewName) | Provide a Json schema of POST API Model for the specified API |
| Task CreateEntityViewAsync(string? entityViewName, string? jsonString) | Create an entity view with the specified entity view name and JSON string |
MermaidGraphSkill
Provides functionalities to create mermaid graphs.
You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IMermaidGraphSkill interface.
You must include this skill if the agent needs to create mermaid graphs.
Functions provided by this skill:
| Function name | Description |
|---|---|
| string HowToDoMermaidGraph() | Provide instructions to build mermaid charts and diagrams |
UIInteractionSkill
Provides functionalities to interact with the UI.
You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IUIInteractionSkill interface.
You must include this skill if the agent needs to interact with UI. This skill can open a UI view in creation mode with initial data and can open an UI view in edition mode.
Functions provided by this skill:
| Function name | Description |
|---|---|
| string CreateNewEntityAsync(string? uiViewName, string? jsonString) | Opens the specified UI view with the initial data as JSON |
| string OpenUIViewNameAsync(string? uiViewName, string? identifiers, string? parameters) | Opens the UI view with the identifiers of an item and with parameters |
DataProposalSkill
Provides functionalities to propose new data in a UI form.
You can reference this skill as a dependency of other skills using GroupeIsa.Neos.Application.AI.Skills.IDataProposalSkill interface.
Functions provided by this skill:
| Function name | Description |
|---|---|
| string CreateNewEntityAsync(string? uiViewName, string? jsonString) | Open the specified UI view with the initial data as JSON |
Create your own skill
How to Monitor the Chatbot
You can create a class that implements the IChatBotInterceptor interface to get information about the conversation with the chatbot. Example:
public class ChatBotInterceptor : IChatBotInterceptor
{
/// <inheritdoc />
public Task OnFunctionInvokedAsync(string agentId, string threadId, string functionName, Dictionary<string, object?> parameters, object? result)
{
// Do what you want with the information about the function call.
}
/// <inheritdoc />
public Task OnPromptInvokedAsync(string agentId, string threadId, string question, string answer)
{
// Do what you want with the exchange between the user and the chatbot.
}
}
Once you have created the class, you need to register it in the Startup class:
public static class Startup
{
public static void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IChatBotInterceptor, ChatBotInterceptor>();
}
}