Bitzsoft.Integrations.AgentFramework 1.0.0-alpha.10

This is a prerelease version of Bitzsoft.Integrations.AgentFramework.
dotnet add package Bitzsoft.Integrations.AgentFramework --version 1.0.0-alpha.10
                    
NuGet\Install-Package Bitzsoft.Integrations.AgentFramework -Version 1.0.0-alpha.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bitzsoft.Integrations.AgentFramework" Version="1.0.0-alpha.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bitzsoft.Integrations.AgentFramework" Version="1.0.0-alpha.10" />
                    
Directory.Packages.props
<PackageReference Include="Bitzsoft.Integrations.AgentFramework" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bitzsoft.Integrations.AgentFramework --version 1.0.0-alpha.10
                    
#r "nuget: Bitzsoft.Integrations.AgentFramework, 1.0.0-alpha.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bitzsoft.Integrations.AgentFramework@1.0.0-alpha.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bitzsoft.Integrations.AgentFramework&version=1.0.0-alpha.10&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Bitzsoft.Integrations.AgentFramework&version=1.0.0-alpha.10&prerelease
                    
Install as a Cake Tool

Bitzsoft.Integrations.AgentFramework

Microsoft Agent Framework 的 Provider-neutral DI 集成。包直接公开官方 Microsoft.Agents.AI.AIAgentChatClientAgentAgentSession,不再用 Semantic Kernel 聊天包装器冒充 Agent Framework。

版本与兼容性

dotnet add package Bitzsoft.Integrations.AgentFramework
  • 目标框架:net8.0;net10.0
  • Microsoft Agent Framework:Microsoft.Agents.AI 1.15.0 正式版;
  • 模型抽象:Microsoft.Extensions.AI.IChatClient
  • 不依赖 Semantic Kernel;
  • 不保存模型端点、API Key 或租户凭据。

AI 包维持 .NET 8 起步,不为 .NET 5 宿主伪造兼容性。仍运行 .NET 5 的业务系统应把 Agent 能力部署为独立 .NET 8/10 服务,通过受控 HTTP、MCP 或 A2A 边界调用。

设计边界

本包负责把宿主的 IChatClient 组装成官方 AIAgent,并提供企业会话持久化 Seam:

  • 模型供应商、endpoint、凭据、重试和模型级日志属于 IChatClient
  • Agent 名称、描述和开发者指令属于 AgentOptions
  • 工具由宿主通过工厂注入;
  • 会话使用 Agent Framework 原生 AgentSession
  • 默认使用官方 ToolApprovalAgent 中间件处理工具审批队列和会话内审批规则;
  • IAgentSessionCoordinator 负责租户隔离、租约、恢复、Run 和乐观并发保存;
  • Store 和分布式租约由宿主接数据库、Redis 或企业数据平台;
  • 工作流、多 Agent 编排、Hosting、A2A、MCP client 与 Foundry connector 直接使用微软 官方扩展包,本包不复制其 API。

Agent 以 transient 注册,工具工厂会在当前解析 scope 中执行,避免把请求级或租户级 业务服务捕获到根容器。会话状态不依赖 Agent DI 生命周期;需要持久化时使用协调器, 不要把已解析的 Agent、MCP 连接或工具缓存到其创建 scope 之外。

这种分层允许 OpenAI、Azure OpenAI、DeepSeek、通义千问、Ollama 或其他 Microsoft.Extensions.AI Provider 使用相同 Agent 注册代码。

注册默认 Agent

先注册一个 IChatClient。下面使用本仓库的 OpenAI-compatible 客户端作为示例:

// 模型层负责 Provider、租户凭据、遥测和请求审计。
services.AddBitzChatClient(options =>
{
    options.ProviderId = "approved-provider";
    options.ProfileId = "deepseek";
    options.ModelId = "approved-model";
    options.EnableTelemetry = true;
});

// Agent 层只配置身份、指令、工具和审批中间件。
services.AddBitzsoftAIAgent(options =>
{
    options.Name = "customer-support";
    options.Description = "Answers questions from approved support sources.";
    options.Instructions =
        "Use only approved tools and sources. "
        + "Ask for human approval before any side effect.";
});

EnableToolApprovalMiddleware 默认为 true,此时解析的 AIAgent 是官方 ToolApprovalAgent,内部仍使用 ChatClientAgent。完全可信、只读且无需审批队列的 场景可以显式关闭;不要仅为减少一次中间件调用而关闭安全能力。

业务代码直接依赖官方抽象:

public sealed class SupportService(AIAgent agent)
{
    public async Task<string> AskAsync(
        string question,
        CancellationToken cancellationToken)
    {
        var response = await agent.RunAsync(
            question,
            cancellationToken: cancellationToken);
        return response.Text;
    }
}

完整最小示例

以下示例使用开发环境的进程内凭据与会话 Store;生产替换方式见后文:

using Bitzsoft.Integrations.AgentFramework;
using Bitzsoft.Integrations.AgentFramework.Sessions;
using Bitzsoft.Integrations.AI;
using Bitzsoft.Integrations.Core;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

// 仅开发/测试:生产环境应接入 Vault/KMS 和数据库/Redis。
services.AddInMemoryIntegrationCredentials();
services.AddInMemoryBitzAgentSessions(options =>
{
    options.LeaseDuration = TimeSpan.FromMinutes(2);
    options.MaxSerializedStateBytes = 16 * 1024 * 1024;
});

// 注册模型;API Key 不进入 Options。
services.AddBitzChatClient(options =>
{
    options.ProviderId = "deepseek-dev";
    options.ProfileId = "deepseek";
    options.ModelId = "deepseek-chat";
});

// 默认启用官方 ToolApprovalAgent;本示例没有写操作工具。
services.AddBitzsoftAIAgent(options =>
{
    options.Name = "customer-support";
    options.Description = "只读客户支持助手";
    options.Instructions =
        "只依据已授权资料回答;资料不足时明确说明,不得编造。";
});

await using var provider = services.BuildServiceProvider(
    new ServiceProviderOptions { ValidateScopes = true });

// 写入 tenant-a 的开发模型密钥。
var credentialStore = provider.GetRequiredService<
    InMemoryIntegrationCredentialStore>();
using (var credential = new IntegrationCredential(
[
    new(AICredentialFieldNames.ApiKey, "<从 User Secrets 读取的 API Key>")
]))
{
    credentialStore.Set(
        new IntegrationCredentialKey(
            tenantId: "tenant-a",
            providerKey: "AI:deepseek-dev",
            environment: IntegrationEnvironments.Development),
        credential);
}

// Agent、Coordinator 和业务依赖都在当前请求 Scope 中解析。
using var scope = provider.CreateScope();
var contextAccessor = scope.ServiceProvider.GetRequiredService<
    IIntegrationContextAccessor>();
using (contextAccessor.Push(new IntegrationContext(
    tenantId: "tenant-a",
    environment: IntegrationEnvironments.Development,
    correlationId: Guid.NewGuid().ToString("N"))))
{
    var agent = scope.ServiceProvider.GetRequiredService<AIAgent>();
    var coordinator = scope.ServiceProvider.GetRequiredService<
        IAgentSessionCoordinator>();

    // sessionId 是租户内稳定会话 ID;协调器负责租约、恢复、CAS 保存。
    var result = await coordinator.RunAsync(
        agent,
        agentName: "customer-support",
        sessionId: "conversation-42",
        messages:
        [
            new ChatMessage(
                ChatRole.User,
                "客户反馈无法下载电子发票,应如何排查?")
        ]);

    Console.WriteLine(result.Response.Text);
    Console.WriteLine($"Saved session version: {result.SessionVersion}");
}

流式响应

// 必须完整消费异步流,协调器才会持久化最终会话状态。
await foreach (var update in agent.RunStreamingAsync(
    "Summarize the incident.",
    cancellationToken: cancellationToken))
{
    await output.WriteAsync(update.Text, cancellationToken);
}

AgentResponseUpdate 不只有文本;工具调用、审批请求和其他内容应按其内容类型处理, 不能只拼接 Text 后假定 Agent 已成功完成全部动作。

命名 Agent 与多模型

为不同职责注册独立的 keyed IChatClient,再把 Agent 绑定到对应 key:

// 不同职责使用独立模型 Key、Agent Key、权限和成本中心。
services.AddKeyedSingleton<IChatClient>(
    "finance-model",
    financeChatClient);

services.AddBitzsoftAIAgent(
    "finance",
    options =>
    {
        options.Name = "finance";
        options.Description = "Read-only finance analysis.";
        options.Instructions =
            "Never post journals or approve payments.";
    },
    chatClientServiceKey: "finance-model");

var financeAgent =
    serviceProvider.GetRequiredKeyedService<AIAgent>("finance");

模型选择发生在 IChatClient 注册层。不要给单个 Agent 增加一个会被静默忽略的 model 字符串参数;不同模型应是不同的命名客户端/Agent,以便单独授权、限流和核算。

工具

// 工具工厂在当前 Scope 执行,可以安全解析请求级业务服务。
services.AddBitzsoftAIAgent(
    options =>
    {
        options.Name = "knowledge";
        options.Description = "Searches the approved knowledge base.";
        options.Instructions = "Cite the retrieved source.";
    },
    serviceProvider =>
    {
        var search = serviceProvider
            .GetRequiredService<ApprovedKnowledgeSearch>();
        var payment = serviceProvider
            .GetRequiredService<ApprovedPaymentService>();
        return new List<AITool>
        {
            // 只读工具仍必须在业务服务内部校验租户和数据权限。
            AIFunctionFactory.Create(search.SearchAsync),
            // 有副作用工具必须进入官方审批队列。
            new ApprovalRequiredAIFunction(
                AIFunctionFactory.Create(payment.SubmitAsync))
        };
    });

所有模型生成的工具参数都必须视为不可信输入。查询工具应再次执行租户、字段和数据范围 授权;写入、付款、发信、删除、发布等有副作用工具应包装为 ApprovalRequiredAIFunction。默认 ToolApprovalAgent 会协调审批请求,但实际执行边界 仍必须重新校验审批主体、参数和幂等键。不要仅靠系统提示词授权,也不要配置 “全部工具永久自动批准”规则。

会话与持久化

生产协调器

业务层不应自行重复“读取—反序列化—运行—序列化—写入”流程。本包的协调器会在模型 调用前取得会话租约,并在调用完成后用 expectedVersion 原子保存:

// 协调器不提供生产 Store;宿主必须显式注册数据库和分布式租约实现。
services.AddBitzAgentSessionCoordinator(options =>
{
    options.LeaseDuration = TimeSpan.FromMinutes(2);
    options.MaxSerializedStateBytes = 16 * 1024 * 1024;
});
services.AddSingleton<IAgentSessionStore, DatabaseAgentSessionStore>();
services.AddSingleton<IAgentSessionLeaseManager, RedisAgentSessionLeaseManager>();

每次操作必须设置 IntegrationContext。最终存储键包含 tenant + environment + region + agent + session:

// 当前上下文参与会话存储键,禁止跨租户恢复状态。
using var contextScope = contextAccessor.Push(
    new IntegrationContext(
        tenantId,
        region,
        environment,
        correlationId));

var result = await coordinator.RunAsync(
    agent,
    agentName: "customer-support",
    sessionId: conversationId,
    messages: [new ChatMessage(ChatRole.User, question)],
    cancellationToken: cancellationToken);

agentName 必须与当前 Agent 的 Name 一致,防止把一种 Agent 的状态恢复给另一种 Agent。调用成功后可记录 result.SessionVersion,但不要把序列化状态或审批内容写入普通 日志。

流式会话

// 提前 break 或取消会使本次流式状态不保存。
await foreach (var update in coordinator.RunStreamingAsync(
    agent,
    "customer-support",
    conversationId,
    [new ChatMessage(ChatRole.User, question)],
    cancellationToken: cancellationToken))
{
    await output.WriteAsync(update.Text, cancellationToken);
}

只有完整消费异步流后会保存新会话状态。调用方提前停止、取消或流式执行失败时不会提交 不完整状态;租约仍会释放。最后一个 update 之后的持久化失败会作为枚举异常返回,因此 调用方必须等待枚举自然结束,不能在收到文本后立即丢弃枚举器。

开发与测试

services.AddInMemoryBitzAgentSessions();

进程内实现支持租户隔离、CAS 和单进程互斥,但不支持重启恢复或多节点,不能作为生产 Store。生产实现至少需要:

  • IAgentSessionStore.SaveAsync/DeleteAsync 原子比较 expectedVersion
  • IAgentSessionLeaseManager 在句柄存活期间自动续租,进程失联后按 LeaseDuration 自动释放;
  • KMS 管理的静态加密、访问审计和保留/删除策略;
  • serialized state 完整性保护,防止消息角色或审批状态被篡改;
  • 部署时绑定 Agent/Schema 版本,升级不兼容时执行迁移或显式失效;
  • 上下文压缩、摘要或归档策略,避免会话无限增长;
  • 有副作用工具使用业务幂等键。模型完成但进程在保存前崩溃时属于结果不确定场景, 会话租约无法替代业务幂等。

MaxSerializedStateBytes 默认 16 MiB,可按存储能力调整或设为 null。该限制只作用于 会话状态,与 RequestLogging 的完整兆级请求/响应记录策略无关。

日志与可观测性

Agent Framework 自身支持 middleware 与 OpenTelemetry。本包不重复记录一份 Agent 正文;请求/响应审计应在 IChatClient 管道统一完成,以免同一提示词落两份日志。

使用 Bitzsoft.Integrations.AI 时可接入 Bitzsoft.Integrations.RequestLogging。普通模型请求与响应默认完整记录,不强制限制或 截断兆级正文;token/API Key 等凭据交换必须抑制,业务定义的 secret/PII 字段必须脱敏。 生产环境应另外配置日志访问控制、静态加密、保留期和删除流程。

OpenTelemetry 默认不应导出提示词、工具参数和响应正文。只有在受控开发环境明确开启 sensitive data,并确认 exporter、采样与保留策略后才允许采集。

安全检查清单

  • 系统指令只能来自受控配置,不能拼接最终用户输入;
  • RAG 文档和 MCP/A2A 消息同样是不可信内容,必须防 prompt injection;
  • 工具在执行边界做身份、租户、资源和参数授权;
  • 有副作用工具需要人审、幂等键与结果核对;
  • 模型输出在进入 HTML、SQL、Shell、模板或文件路径前必须验证/编码;
  • session 与 continuation token 视为敏感数据;
  • 对成本、并发、工具轮次和上下文长度设置宿主策略;
  • 在上线前用真实模型测试拒答、越权、提示词注入、工具参数污染与取消。

当前未封装

本包当前不封装 Workflows、multi-agent orchestration、Agent Hosting、Foundry Hosted Agent、A2A client/server、DevUI、Evaluation 或 Agent Harness。这些功能在微软官方包中 已经有稳定或快速演进的实现,重复包一层商业价值低、升级成本高。出现明确 ToB 场景时, 优先提供企业策略 Adapter(审批、租户隔离、持久化、审计),而不是复制官方 API。

官方资料

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Bitzsoft.Integrations.AgentFramework:

Package Downloads
Bitzsoft.Integrations.All

Bitzsoft 第三方集成聚合包 — net5.0 包含传统连接器,net8.0+ 额外包含受上游 TFM 限制的 AI 模块

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-alpha.10 35 7/26/2026
1.0.0-alpha.9 62 7/12/2026
1.0.0-alpha.8 307 7/1/2026
1.0.0-alpha.7 75 6/16/2026
1.0.0-alpha.6 70 6/16/2026
1.0.0-alpha.5 64 6/14/2026
1.0.0-alpha.4 68 6/14/2026
1.0.0-alpha.3 63 6/7/2026
1.0.0-alpha.2 69 5/29/2026
1.0.0-alpha.1 67 5/28/2026