Intellectus.AIAgent.Framework
2.0.0
dotnet add package Intellectus.AIAgent.Framework --version 2.0.0
NuGet\Install-Package Intellectus.AIAgent.Framework -Version 2.0.0
<PackageReference Include="Intellectus.AIAgent.Framework" Version="2.0.0" />
<PackageVersion Include="Intellectus.AIAgent.Framework" Version="2.0.0" />
<PackageReference Include="Intellectus.AIAgent.Framework" />
paket add Intellectus.AIAgent.Framework --version 2.0.0
#r "nuget: Intellectus.AIAgent.Framework, 2.0.0"
#:package Intellectus.AIAgent.Framework@2.0.0
#addin nuget:?package=Intellectus.AIAgent.Framework&version=2.0.0
#tool nuget:?package=Intellectus.AIAgent.Framework&version=2.0.0
Intellectus AI Agent Framework for .NET
Library provides an OpenAI Agent for .NET applications.
The agent is designed to facilitate communication between your application and OpenAI's large language models (LLMs),
enabling you to build intelligent conversational interfaces.
You can tell the Agent about your tools & the Agent can figure out which tool to use, given a natural language input.
Step 1:
Create your tools by implementing the ITool interface.
This interface defines the structure and behavior of your tools, allowing them to be seamlessly integrated into the agent framework.
The Agent can pass multiple inputs to the ExecuteAsync method of the tools, and the tools can return any object as output.
The multiple inputs are based on the reasoning result that you provide when creating the Agent instance.
Interface
public interface ITool
{
string Name { get; }
string Description { get; }
Task<object> ExecuteAsync(params string[] input);
}
Sample Tool Implementation
Let us say you have 2 tools. A Product tool & a Sales tool.
public class Constants
{
public const string PRODUCT_TOOL_NAME = "ProductTool";
public const string SALES_TOOL_NAME = "SalesTool";
}
Product tool
The ExecuteAsync method of the ProductTool class takes a product name as input and returns product information.
public class ProductData
{
public string ProductName { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public decimal Price { get; set; }
}
public class ProductTool : ITool
{
public string Name => Constants.PRODUCT_TOOL_NAME;
public string Description => "Provides product information for a given product. Input: product name.";
public Task<object> ExecuteAsync(params string[] input)
{
return Task.FromResult((object)new ProductData
{
ProductName = input[0],
Description = "A high-quality product.",
Price = 29.99m
});
}
}
Sales tool
The ExecuteAsync method of the SalesTool class takes a product name and an optional year as input.
public class SalesData
{
public string ProductName { get; set; } = string.Empty;
public decimal TotalSales { get; set; }
public int UnitsSold { get; set; }
public int? Year { get; set; } = null; // Optional, default to null if not provided
}
public class SalesTool : ITool
{
public string Name => Constants.SALES_TOOL_NAME;
public string Description => "Provides sales data for a given product. Input: product name, year.";
public Task<object> ExecuteAsync(params string[] input)
{
var productName = input[0].Trim();
var year =
input.Length > 1
?
int.Parse(input[1].Trim())
:
0;
return Task.FromResult((object)
(year == 0
?
//Total sales and units sold for the product without year
new SalesData
{
ProductName = productName,
TotalSales = 10000.50m,
UnitsSold = 2000
}
:
//Total sales and units sold for the product for the specified year
new SalesData
{
ProductName = productName,
TotalSales = 500.50m,
UnitsSold = 50,
Year = year
}));
}
}
Step 2:
Wire up the tools in your application and register them with the agent framework.
Add the settings with OpenAI details (API Key, LLM), the list of tools and the reasoning result.
The tools can be dependency injected too.
The reasoning result is a string that describes the output format of the reasoning which is the expected input for the tools.
The agent will use this information to understand how to interact with the tools during conversations.
In the example, ProductName will be passed to Product tool and ProductName and/or Year (optional) to the Sales tool.
Using Dependency Injection
Use extension AddIntellectusAIAgentFramework to wire up the framework for DI.
using AgentFramework.Demo;
using Intellectus.AIAgent.Framework;
using Microsoft.Extensions.DependencyInjection;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
if (string.IsNullOrWhiteSpace(apiKey))
{
Console.WriteLine("Please set the OPENAI_API_KEY environment variable.");
return;
}
// Create an Agent with the configured settings
var services = new ServiceCollection();
// Register tools with DI
services.AddScoped<ITool, SalesTool>();
services.AddScoped<ITool, ProductTool>();
// Register the framework and configure settings
services.AddIntellectusAIAgentFramework(settings =>
{
settings.OpenAIAPIKey = apiKey;
settings.OpenAILLMModel = "gpt-4o-mini";
settings.ReasoningResult = @"<ProductName>:<Year>
Year is optional.
";
//Add tools without using DI
//settings.Tools = new List<ITool> { new SalesTool(), new ProductTool() };
});
var sp = services.BuildServiceProvider();
var agent = sp.GetRequiredService<IAgent>();
Console.WriteLine("Agent ready. Type 'exit' to quit.\n");
while (true)
{
Console.Write("You: ");
var input = Console.ReadLine();
if (string.Equals(input, "exit", StringComparison.OrdinalIgnoreCase))
break;
var response = await agent.RespondAsync(input);
Console.WriteLine($"Agent: {response.Response}\n");
}
Without using Dependency Injection
Use the AgentBuilder to build the Agent.
using AgentFramework.Demo;
using Intellectus.AIAgent.Framework;
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
var agent = new AgentBuilder()
.AddTool(new ProductTool())
.AddTool(new SalesTool())
.AddOpenAIAPIKey(apiKey)
.AddOpenAILLM("gpt-4o-mini")
.AddReasoningResult(@"<ProductName>:<Year>
Year is optional.
")
.ToAgent();
Console.WriteLine("Agent ready. Type 'exit' to quit.\n");
while (true)
{
Console.Write("You: ");
var input = Console.ReadLine();
if (string.Equals(input, "exit", StringComparison.OrdinalIgnoreCase))
break;
var response = await agent.RespondAsync(input);
Console.WriteLine($"Agent: {response.Response}\n");
}
Agent Response
The Agent returns below AgentResponse.
The ToolOutput property contains the object returned by the Tool.
public class AgentResponse
{
public string RequestId { get; set; } = string.Empty;
public string Response { get; set; } = string.Empty;
public string ReasoningResult { get; set; } = string.Empty;
public string ToolName { get; set; } = string.Empty;
public object? ToolOutput { get; set; } = null;
public string Error { get; set; } = string.Empty;
}
Running Agent on threads
You can run the Agent on threads.
You subscribe to events to get the Agent's response asynchronously.
Provide a RequestId to Agent's RespondThreadAsync method to co-relate it to the response.
This method returns a response too.
Event handlers
General purpose event handler
You subscribe to event OnAgentResponse to get the Agent's response asynchronously.
This event gets all the events for all tools.
If needed, you can have multiple event handlers to process the response differently.
Tool specific event handler
You can add event handlers specific for a tool.
So, only events for that tool are published to that handler.
If needed, you can add multiple handlers for the same tool to process the response differently.
You can use the Filter to specify which response gets published to the handler.
Console.WriteLine("Running Agent on threads...");
var inputs = new List<(string input, string reqId)>()
{
("What is the sales in 2026 of xyz?", Guid.NewGuid().ToString()),
("What is the sales of xyz?", Guid.NewGuid().ToString()),
("Give me information about xyz.", Guid.NewGuid().ToString())
};
// General purpose event handler for all tools.
// You can add multiple.
agent.OnAgentResponse += async response =>
{
Console.WriteLine($"OnAgentResponse: RequestId: {response.RequestId}, Tool Name: {response.ToolName}, Response: {response.Response}");
};
// Tool specific event handler.
// You can Add multiple for the same tool.
agent.OnAgentToolResponse.Add(new AgentToolResponseEvent
{
ToolName = Constants.PRODUCT_TOOL_NAME,
OnAgentResponse = HandleProductToolResponse
});
agent.OnAgentToolResponse.Add(new AgentToolResponseEvent
{
ToolName = Constants.SALES_TOOL_NAME,
Filter = response => ((SalesData)response.ToolOutput!).Year == null,
OnAgentResponse = HandleSalesToolByTotalResponse
});
agent.OnAgentToolResponse.Add(new AgentToolResponseEvent
{
ToolName = Constants.SALES_TOOL_NAME,
Filter = response => ((SalesData)response.ToolOutput!).Year > 0,
OnAgentResponse = HandleSalesToolByYearResponse
});
foreach (var input in inputs)
{
Console.WriteLine(Environment.NewLine);
Console.WriteLine(input);
var response = await agent.RespondThreadAsync(input.input, input.reqId);
Console.WriteLine($"Agent: RequestId: {response.RequestId}, Tool Name: {response.ToolName}, Response: {response.Response}");
//OR
//var response = await Task.Run(async () => await agent.RespondAsync(input.input, input.reqId));
}
Console.ReadLine();
async Task HandleProductToolResponse(AgentResponse response)
{
Console.WriteLine($"{Constants.PRODUCT_TOOL_NAME} event: RequestId: {response.RequestId}, Response: {response.Response}");
}
async Task HandleSalesToolByTotalResponse(AgentResponse response)
{
Console.WriteLine($"{Constants.SALES_TOOL_NAME} by Total event: RequestId: {response.RequestId}, Response: {response.Response}");
}
async Task HandleSalesToolByYearResponse(AgentResponse response)
{
Console.WriteLine($"{Constants.SALES_TOOL_NAME} by Year event: RequestId: {response.RequestId}, Response: {response.Response}");
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- OpenAI (>= 2.12.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Added tool specific event handlers for improved workflow. Added method to run agent on a thread.