Microsoft.Extensions.AI Integration
The AI21 SDK implements IChatClient from Microsoft.Extensions.AI, providing a unified interface for chat completions with text, streaming, tool calling, and reasoning support.
Installation
| dotnet add package tryAGI.AI21
|
Chat Completions
Ai21Client directly implements IChatClient, so you can use it with the standard MEAI interface without any adapters.
| using Microsoft.Extensions.AI;
using AI21;
IChatClient client = new Ai21Client(apiKey: Environment.GetEnvironmentVariable("AI21_API_KEY")!);
var response = await client.GetResponseAsync(
"What is the capital of France?",
new ChatOptions { ModelId = "jamba-1.5-mini" });
Console.WriteLine(response.Text);
|
Streaming
| using Microsoft.Extensions.AI;
using AI21;
IChatClient client = new Ai21Client(apiKey: Environment.GetEnvironmentVariable("AI21_API_KEY")!);
await foreach (var update in client.GetStreamingResponseAsync(
"Explain quantum computing in simple terms.",
new ChatOptions { ModelId = "jamba-1.5-mini" }))
{
Console.Write(update.Text);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 | using Microsoft.Extensions.AI;
using AI21;
IChatClient client = new Ai21Client(apiKey: Environment.GetEnvironmentVariable("AI21_API_KEY")!);
var tool = AIFunctionFactory.Create(
(string location) => $"The weather in {location} is sunny, 22C.",
"GetWeather",
"Gets the current weather for a given location.");
var options = new ChatOptions
{
ModelId = "jamba-1.5-mini",
Tools = [tool],
};
var messages = new List<ChatMessage>
{
new(ChatRole.User, "What is the weather in London?"),
};
// The loop handles automatic tool invocation
while (true)
{
var response = await client.GetResponseAsync(messages, options);
messages.AddRange(response.ToChatMessages());
if (response.FinishReason == ChatFinishReason.ToolCalls)
{
var results = await response.CallToolsAsync(options);
messages.AddRange(results);
continue;
}
Console.WriteLine(response.Text);
break;
}
|
Reasoning
AI21 Jamba models support reasoning content. When reasoning is present, it is returned as TextReasoningContent in the response message.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | using Microsoft.Extensions.AI;
using AI21;
IChatClient client = new Ai21Client(apiKey: Environment.GetEnvironmentVariable("AI21_API_KEY")!);
var response = await client.GetResponseAsync(
"If a train leaves at 3pm going 60mph and another leaves at 4pm going 90mph, when do they meet?",
new ChatOptions { ModelId = "jamba-1.5-mini" });
foreach (var content in response.Messages.SelectMany(m => m.Contents))
{
switch (content)
{
case TextReasoningContent reasoning:
Console.WriteLine($"Reasoning: {reasoning.Text}");
break;
case TextContent text:
Console.WriteLine($"Answer: {text.Text}");
break;
}
}
|
Dependency Injection
| using Microsoft.Extensions.AI;
using AI21;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IChatClient>(
new Ai21Client(apiKey: builder.Configuration["AI21:ApiKey"]!));
|
| var metadata = client.GetService<ChatClientMetadata>();
Console.WriteLine($"Provider: {metadata?.ProviderName}"); // "Ai21Client"
Console.WriteLine($"Endpoint: {metadata?.ProviderUri}");
|