Un-monolithing, cross-framework support, CLI tool, architecture improvements, rich output, expoerters, data loaders, benchmarking and more
Pre-release
Pre-release
v0.5.0-beta
Added
- Monolith Modularization (ADR-016) — Split single
src/AgentEvalproject (~203 files, ~35K lines) into 6 internal sub-projects while shipping a single NuGet package. Resolves dependency coupling: non-MAF users no longer pullMicrosoft.Agents.AI, non-RedTeam users no longer pullPdfSharp-MigraDoc. Compiler-enforced dependency direction: Abstractions → Core → DataLoaders/MAF/RedTeam → Umbrella.AgentEval.Abstractions(~48 files) — Public contracts:IMetric,IEvaluableAgent,IStreamableAgent, modelsAgentEval.Core(~63 files) — Implementations: metrics, assertions, tracing, comparison, DI registrationAgentEval.DataLoaders(~23 files) — Dataset loaders (JSON/JSONL/CSV/YAML), exporters, output formattingAgentEval.MAF(7 files) — Microsoft Agent Framework integration (MAFAgentAdapter,MAFEvaluationHarness)AgentEval.RedTeam(61 files) — Security scanning, attack types, compliance reporting, PDF exportAgentEval(umbrella) — Single NuGet package containing all 6 DLLs per TFM viaTargetsForTfmSpecificBuildOutput- All sub-projects use
RootNamespace=AgentEval— zero namespace changes, zero API surface changes PrivateAssets="all"on umbrella ProjectReferences with explicit NuGet dependency declarationsInternalsVisibleToon all sub-projects →AgentEval.Tests- Phase 0: Fixed 11 cross-cutting coupling anomalies before split
- See ADR-016 for full rationale and alternatives considered
- Cross-Framework IChatClient Support — Universal adapter pattern for evaluating any
IChatClient-based AI agent regardless of underlying framework (Azure OpenAI, Ollama, Groq, LM Studio, Semantic Kernel, etc.):IChatClient.AsEvaluableAgent()extension method — One-liner wrapping anyIChatClientasIStreamableAgentfor evaluation. Located inAgentEval.Core.ChatClientExtensions. Parallels.AsIChatClient()from Microsoft.Extensions.AI.TestSummary.ToEvaluationReport()extension method — Bridges evaluation pipeline (TestSummary) to export pipeline (EvaluationReportforIResultExporter). Derives time boundaries fromPerformanceMetrics, mapsMetricResultstoMetricScores, supportsagentName/modelName/endpointprovenance, setsCategoryfor JUnit XML grouping.- NuGetConsumer Semantic Kernel demo — Real SK with
[KernelFunction]plugins (FlightPlugin.cs) evaluated by AgentEval via theAIFunctionFactory.Create()bridge pattern. 8-step demo: Kernel build → plugin registration → SK↔M.E.AI bridge → tool assertions → code metrics → LLM-as-judge → performance summary. Isolated project withMicrosoft.SemanticKernel 1.72.0andAzure.AI.OpenAI 2.7.0-beta.2. Located insamples/AgentEval.NuGetConsumer/. - Sample 27: Cross-Framework Evaluation — Universal IChatClient adapter pattern:
IChatClient→AsEvaluableAgent()→ evaluate →ToEvaluationReport()→ export to Markdown. - Documentation —
docs/cross-framework.mdwith capability table, SK bridge code example, NuGetConsumer link.
- AgentEval CLI (
agenteval eval) — Evaluate any OpenAI-compatible AI agent from the command line without writing C#. Supports all providers (OpenAI, Ollama, Groq, vLLM, LM Studio, Azure OpenAI, etc.) via the Chat Completions API standard. Features: 15 CLI options, 7 export formats (json, junit, xml, markdown, md, trx, csv), LLM-as-judge via--judge, system prompt from file, stderr progress reporting for Unix piping, and CI/CD exit codes (0=pass, 1=fail, 2=usage error, 3=runtime error). Packaged as a .NET tool (dotnet tool install AgentEval.Cli). Located insrc/AgentEval.Cli/. - Dependency Injection architecture (ADR-006) — All core services registered via
services.AddAgentEval(),services.AddAgentEvalDataLoaders(),services.AddAgentEvalRedTeam(), orservices.AddAgentEvalAll(). Interface-first design:IStochasticRunner,IModelComparer,IStatisticsCalculator,IToolUsageExtractor,ISnapshotComparer,ISnapshotStore, and all exporters/loaders registered with appropriate lifetimes. Configurable viaAgentEvalServiceOptions(lifetime, harness factory, logger factory). SeeAgentEvalServiceCollectionExtensions. - Rich Evaluation Output subsystem — Structured output formatting moved to
AgentEval.DataLoaders/Output/during modularization, contracts split toAgentEval.Abstractions/Output/:TableFormatter—PrintTable(),PrintComparisonTable(),PrintPerformanceSummary(),PrintToolSummary()with dynamic column selection and ANSI variance color-coding.StochasticResultExtensions— Fluentresult.PrintTable("Metrics"),result.PrintSummary(),result.PrintPerformanceSummary(),result.PrintToolSummary(),result.ToTableString().ComparisonResultExtensions—modelResults.PrintComparisonTable(),modelResults.ToComparisonTableString().OutputOptions— 15+ toggle properties (ShowScore,ShowPassRate,ShowDuration,ShowTTFT,ShowTokens,ShowCost,ShowToolCalls,ShowConfidenceInterval, etc.) withDefault,Minimal,Fullstatic presets and fluentWith()copy method.VerbosityLevelenum (None/Summary/Detailed/Full),VerbositySettings,VerbosityConfigurationwith environment variable support (AGENTEVAL_VERBOSITY,AGENTEVAL_SAVE_TRACES,AGENTEVAL_TRACE_DIR).EvaluationOutputWriter— 4-mode writer (Summary/Detailed/Full/None) producing tool timelines, performance sections, metric sections, and full JSON trace to anyTextWriter.AgentEvalTestBase— xUnit test base class with automatic tracing,RecordResult(),SaveTrace(),CreateResult()fluent builder pattern (TestResultBuilder).TimeTravelTrace— 22+ model classes for time-travel debugging (ExecutionStep, 13StepTypevalues,ToolCallStepData,AgentHandoffStepData, etc.).TraceArtifactManager—SaveTestResult(),SaveTrace(),LoadTrace(),ListTraceFiles(),GetMostRecentTrace(),CleanupOldTraces().
- Exporter registry and DI auto-discovery — Extensible exporter system with runtime registration:
IExporterRegistryinterface (in Abstractions) —Register(),Get(),GetRequired(),GetAll(),GetRegisteredFormats(),Contains(),Remove(),Clear().ExporterRegistryimplementation — Thread-safeConcurrentDictionary, pre-populated with 5 built-in exporters (JSON, JUnit XML, Markdown, TRX, CSV) via DI.- DI auto-discovery: custom
IResultExporterservices registered in DI are automatically picked up by the registry. FormatNamedefault interface member onIResultExporterfor string-based lookup.ResultExporterFactory— Static factory withCreate(ExportFormat)andCreateFromExtension(string).
- DataLoader factory and DI architecture — Extensible dataset loading with runtime registration:
IDatasetLoaderFactoryinterface (in Abstractions) —CreateFromExtension(),Create(),Register().DefaultDatasetLoaderFactoryimplementation — Dictionary-based registry for.jsonl,.ndjson,.json,.csv,.tsv,.yaml,.yml. Constructor acceptsIEnumerable<IDatasetLoader>for DI auto-discovery of custom loaders.DatasetLoaderFactoryrefactored to static convenience façade delegating toDefaultDatasetLoaderFactory.IsTrulyStreamingproperty onIDatasetLoader— distinguishes JSONL/CSV true streaming from JSON/YAML buffered loading..ndjsonand.tsvfile extension support added.DatasetTestCaseBenchmarkExtensions—ToToolAccuracyTestCase()andToTaskCompletionTestCase()bridging dataset test cases to benchmark types withrequired_paramsmetadata mapping.
- Benchmarking improvements — DI integration and multi-prompt support:
AgenticBenchmarknow acceptsIToolUsageExtractor?via DI (defaults toDefaultToolUsageExtractor.Instancefor non-DI usage).PerformanceBenchmark.RunLatencyBenchmarkAsync()gained multi-prompt overload (IEnumerable<string> prompts) to avoid server-side caching and produce more representative latency measurements.AgenticBenchmarkOptions.AddDefaultCompletionCriteria— boolean controlling auto-appended standard criteria.- Throughput benchmark
Task.Yield()fixes for both success and error paths preventing deadlocks with synchronous agents.
- Extensibility framework — Plugin system and registry pattern for custom extensions:
IMetricRegistry— now DI-registered as singleton with auto-population fromIMetricservices.IAgentEvalPluginlifecycle interface —InitializeAsync(),OnBeforeEvaluationAsync(),OnAfterEvaluationAsync(),ShutdownAsync(), withPluginId,Name,Version,Dependencies.IPluginContext— providesMetrics(IMetricRegistry),Logger,Configuration,GetConfig<T>().IResultTransformer— Post-processing withPriorityordering for composable result pipelines.- See Sample 26 for custom metrics, exporters, loaders, and attack registration via DI.
- Sample 22: Responsible AI — Toxicity, bias, misinformation metrics with counterfactual testing.
- Sample 23: Benchmark System — JSONL-loaded benchmarks: tool accuracy, latency, cost analysis with
DatasetTestCaseBenchmarkExtensions. - Sample 24: Calibrated Evaluator — Multi-model consensus evaluation with calibrated scoring.
- Sample 25: Dataset Loaders — Multi-format dataset pipeline: JSONL, JSON, YAML, CSV with
IDatasetLoaderFactory. - Sample 26: Extensibility — DI registries, custom metrics/exporters/loaders/attacks demonstrating all extension points.
Changed
- Snapshot Evaluation comprehensive review (28+ fixes) — Major audit and hardening of the snapshot comparison and storage system:
- Interfaces & DI: Added
ISnapshotComparerandISnapshotStoreinterfaces with DI registration (ADR-006 compliance). AddedInternalsVisibleTofor test project access to internal helpers. - Security: Sanitized suffix parameter in
GetSnapshotPathto prevent path traversal (CODE-22). AddedbasePathvalidation inSnapshotStoreconstructor (CODE-21). FixedSanitizeFileNamecollision resistance with SHA256 hash suffix (CODE-17). - Correctness: Fixed
JsonValueKind.Nullhandling in element comparison (CODE-12). Fixed boolean type guard treatingTrue/Falseas compatible types (CODE-30). FixedSemanticComparisonResultto store scrubbed values (CODE-33). FixedComputeSimpleSimilarityto split on all whitespace (CODE-32). FixedCompareArraysto continue comparing after length mismatch (CODE-23). FixedLoadAsyncTOCTOU with try/catch pattern (CODE-26/35). Fixed GUID regex word boundaries (CODE-16). Fixed duration regex word boundaries to prevent false positives (CODE-15). Fixed field name passed as parameter through recursion (CODE-20/34). - Validation: Added
SemanticThreshold[0.0, 1.0] range validation (CODE-31). Added null guards onComparemethod (TEST-12). - New features: Added
AllowExtraPropertiesoption (CODE-6). AddedDelete,ListSnapshots, andCounttoSnapshotStore(CODE-9/18). Added epsilon-based floating-point comparison (CODE-10). AddedCancellationTokensupport on all async methods (CODE-7). - Performance: Added
RegexOptions.Compiledon all default patterns (CODE-13). MadeJsonSerializerOptionsstatic inSnapshotStore(CODE-14). - Testing: Expanded test coverage from 23 to 51+ tests. Moved tests from
Benchmarks/toSnapshots/directory (TEST-1/7). Added thread safety documentation (CODE-19). Documentation aligned with code defaults and APIs.
- Interfaces & DI: Added
- Sample 27 simplified — Removed redundant MAF flight agent (Part B, ~350 lines) already demonstrated in Samples 2-3, 9-10, and NuGetConsumer. Now focused solely on the unique Universal IChatClient Adapter pattern.
- Cross-framework documentation fixed — Fixed broken Semantic Kernel code example in
docs/cross-framework.md(replaced non-existentAsChatClient()method with workingAIFunctionFactory.Create()bridge pattern). Added NuGetConsumer SK demo link. Fixed capability table footnote. - README updated — Sample count corrected from 26 to 27 with Sample 27 row added. Test counts now use qualitative descriptions instead of hard-coded numbers. Added CLI, DI, and cross-framework to Key Features. Expanded documentation table.
- Roadmap updated — Marked Red Team and CLI as shipped; added CLI Phase 2, MCP Server, Benchmark runner, and Verify.Xunit to "What's Next". Updated version history table through 0.6.0-beta.
- System.CommandLine upgraded from 2.0.0-beta4 to 2.0.3 stable — Breaking API change:
SetHandler→SetAction,IsRequired→Required,AddOption()→Options.Add(),AddAlias()→ constructor aliases,root.InvokeAsync(args)→root.Parse(args)thenparseResult.InvokeAsync(). Only affects the new CLI project; no existing code referenced System.CommandLine. - Test count increased from 6,573 to 7,345 — 2,435 (net8.0) + 2,455 (net9.0) + 2,455 (net10.0). New tests for DI service registration, snapshot evaluation improvements, CLI commands, cross-framework adapter, and export pipeline bridging.
Fixed
- Streaming tool extraction for ChatClientAgentAdapter —
InvokeStreamingAsyncnow yieldsToolCallStartedandToolCallCompletedchunks when the underlyingIChatClientstreamsFunctionCallContent/FunctionResultContent. Previously, streaming evaluations viaRunEvaluationStreamingAsyncproduced emptyToolUsageReportfor allIChatClient-based agents. Non-streaming path was unaffected.
``