进程外插件改为只读环境变量和自身配置,避免读宿主 appsettings;宿主按 plugin.json 声明注入 LLM / OpenWeather 等凭据。
3.9 KiB
3.9 KiB
MAF1 — Agent Instructions
.NET 10 多智能体工作流编排演示仓库(Microsoft Agents AI + ASP.NET Core + 进程外插件)。完整文档见 README.md 和 plugins/README.md。
项目结构(6 个工程,MAF1.slnx)
| 工程 | 作用 |
|---|---|
MAF1.Core |
唯一共享层:Agent、Tool、LLM 工厂、插件协议。所有工程都引用它 |
MAF1 |
命令行工作流(node/edge 两种条件写法) |
MAF1.Route |
命令行路由(方案 C,WithHandoff 交接) |
MAF1.Web |
ASP.NET Core Minimal API 可视化编排器 + wwwroot(原生 JS,无 npm) |
Plugins/file-city、Plugins/weather |
进程外插件(stdin/stdout JSON) |
构建 / 运行
dotnet build # 还原 + 编译(在仓库根目录)
dotnet run --project MAF1 -- node Data/cities.txt
dotnet run --project MAF1 -- edge Data/not-cities.txt
dotnet run --project MAF1.Route -- Graphs/city-weather.json
dotnet run --project MAF1.Web # 浏览器 http://127.0.0.1:5288
没有测试工程。验证靠 UI 示例图 + 两个 CLI 命令。解决方案是 MAF1.slnx(不是 .sln)。
关键陷阱(改代码前必读)
- 插件运行时读的是 bin 输出,不是源码树:
PluginScanner扫描MAF1.Web.exe旁的plugins/。改完Plugins/源码必须重新dotnet build(靠MAF1.Web.csproj的PublishPluginFolders目标复制)或点前端「刷新节点」。 - 不要提交 API Key:Key 走环境变量或
appsettings.json的Llm/Credentials段(环境变量优先)。注意**/Properties/launchSettings.json里目前硬编码了一个真实 Key,新增/修改配置时切勿再写入真实密钥,也勿把含 Key 的版本提交。 - 插件 stdout 只能输出一行 JSON:日志和提示走 stderr,否则宿主
ParseOutputs会解析失败。 - 天气查询必须用
WeatherTools.CreateHttpClient():带 20s 超时和正确 User-Agent,直接new HttpClient()可能被 wttr.in 拒绝。 - LLM 输出解析前先过
JsonText.UnwrapObject:剥离模型回复的json围栏后再反序列化。 - 进程外插件不要读宿主 appsettings:LLM 用
AgentFactory.LoadFromEnvironment();其它配置用插件目录自己的 json。stdin 协议见docs/plugin-protocol-v1.schema.json(protocolVersion1)。
约定
- JSON 序列化:camelCase + 反射(无 source gen)。统一入口
MAF1.PluginContract.PluginJson.Options;Web 用ConfigureHttpJsonOptions。个别类用[JsonPropertyName(...)]显式标注。 - LLM 创建只经
AgentFactory.Load/AgentFactory.CreateAgent(MAF1.Core/Utils/AgentFactory.cs)。识别环境变量OPENAI_API_KEY/OPENAI_ENDPOINT(或OPENAI_BASE_URL)/OPENAI_CHAT_MODEL;DeepSeek endpoint 会自动禁用 thinking(DeepSeekThinking.Disable)。 - 每个
Program.cs第一行调用WindowsConsole.EnableUtf8()(避免中文乱码)。 - Agent 用静态工厂:
FileCityAgent.Create/WeatherAgent.Create,业务逻辑集中在RunAsync。CLI、Web 系统节点、插件三处复用同一套。 - 文件组织:多数一文件一类;但
PluginManifest.cs、DecisionModels.cs、RouteGraph.cs等有意把多个紧相关小类放一个文件,属惯例。 - 命名空间与目录不严格对应:如
MAF1.Web/PluginHost/*.cs用MAF1.Plugins;Core 里Agents/FileCity用MAF1.Agents.FileCity,而AgentStepResult.cs用MAF1.Core.Agents。
建议的上手路径
README.md → MAF1.Core/Utils/AgentFactory.cs(LLM 配置)→ FileCityAgent.cs / WeatherAgent.cs(Agent 写法)→ PluginContract/PluginStdio.cs + MAF1.Web/PluginHost/PluginProcessRunner.cs(插件协议两端)→ MAF1/Workflows/CityWeatherWorkflow.cs(Workflow 用法)→ MAF1.Route/HandoffGraphBuilder.cs(Handoff 用法)。