Flirty 202608.4.0
dotnet add package Flirty --version 202608.4.0
NuGet\Install-Package Flirty -Version 202608.4.0
<PackageReference Include="Flirty" Version="202608.4.0" />
<PackageVersion Include="Flirty" Version="202608.4.0" />
<PackageReference Include="Flirty" />
paket add Flirty --version 202608.4.0
#r "nuget: Flirty, 202608.4.0"
#:package Flirty@202608.4.0
#addin nuget:?package=Flirty&version=202608.4.0
#tool nuget:?package=Flirty&version=202608.4.0
Flirty
Reusable chatbot/dialog engine for .NET. You only build the UI – Flirty handles persistence, answer validation, branching, loops, resume, editable answers and triggers (back channels into your app). Dialogs are configured via a Blazor designer (also by non-technical users).
The core is a pure class library without an ASP.NET dependency and runs unchanged in
console, worker and web applications. HTTP endpoints are opt-in via the add-on package
Flirty.AspNetCore.
Features
| Feature | Implementation |
|---|---|
| Resume within a dialog | The session holds the current question; resumption via the session id |
| Editing answers after the fact | EditAnswerAsync + recomputation of the downstream path |
| Branching (multiple branches) | Transitions with sandboxed condition expressions (default: DynamicExpresso) |
| Loops (list up to the exit question) | Branching cycle + loop marker, iterations as a collection in the context |
| Trigger after an answer / on completion | In-process notifications (Mediator) and outbound webhooks |
| Answer validation | Type check + ValidationRules per question, before the handler in the pipeline |
| Dialog versioning | Published versions are immutable; changes go through a new version, running sessions stay on theirs |
| Multi-DB + auto-migration | SQLite / PostgreSQL / SQL Server, migrations per provider |
| Simple integration | services.AddFlirty(o => …), optionally app.MapFlirtyEndpoints() |
Projects
| Project | Purpose |
|---|---|
src/Flirty |
Core engine (domain, runtime, EF Core persistence, Mediator, DI extensions). No ASP.NET → usable in console/worker too. NuGet package. |
src/Flirty.AspNetCore |
Optional WebAPI endpoints (MapFlirtyEndpoints, MapFlirtyAdminEndpoints). NuGet package. |
src/Flirty.Mcp |
Optional MCP server (MapFlirtyMcp): the engine operations as Model Context Protocol tools → docs/MCP.md. NuGet package. |
src/Flirty.Designer |
Blazor Web App for configuring dialogs/questions/answers/branching/loops/triggers, incl. test runner. Multi-DB → docs/DESIGNER.md. |
src/Flirty.Migrations.* |
EF migrations per provider (SQLite, PostgreSQL, SQL Server); bundled into the Flirty package. |
src/Flirty.Samples |
Runnable console sample (core only, no ASP.NET) → docs/GETTING-STARTED-Console.md. |
src/Flirty.Samples.Web |
Runnable web sample (minimal API + static chat UI): resume/edit/branching/loop/trigger + webhook receiver, plus the MCP server at /mcp → docs/GETTING-STARTED-Sample-Web.md. |
tests/Flirty.Tests |
Unit/integration tests (xUnit). |
tests/Flirty.E2E |
Playwright E2E tests (web-sample chat UI and Blazor designer). |
Installation
dotnet add package Flirty # Core engine (usable without ASP.NET)
dotnet add package Flirty.AspNetCore # optional: ready-made WebAPI endpoints
dotnet add package Flirty.Mcp # optional: MCP server (independent of the above)
The target framework is .NET 10. The version scheme is date-based (
YYYYMM.Revision.0, e.g.202607.3.0) – not a SemVer signal, seedocs/NUGET-PACKAGING.md.
Quickstart (Console)
AddFlirty(o => …) wires up the complete stack (Mediator, runtime facade, persistence,
expression engine, validation). Excerpt from the console sample
(src/Flirty.Samples/Program.cs):
// SQLite in-memory (shared cache): as long as the keep-alive connection stays open,
// all DI-created FlirtyDbContext instances share the same database.
const string connectionString = "Data Source=FlirtyQuickstart;Mode=Memory;Cache=Shared";
using var keepAlive = new SqliteConnection(connectionString);
keepAlive.Open();
using var provider = new ServiceCollection()
.AddLogging()
.AddFlirty(o => o.UseSqlite(connectionString))
// Your own back channel: the engine calls it when the dialog completes.
.AddFlirtyHandler<DialogCompletedNotification, MyDoneHandler>()
.BuildServiceProvider();
using var scope = provider.CreateScope();
var engine = scope.ServiceProvider.GetRequiredService<IFlirtyEngine>();
var start = await engine.StartDialogAsync("onboarding", "user-1");
var result = await engine.SubmitAnswerAsync(start.SessionId, start.CurrentQuestion.Id, "\"dev\"");
// result.NextQuestion / result.IsCompleted drive the rest of the flow.
Careful with the migration:
o.ApplyMigrations()registers anIHostedServiceand therefore only takes effect inside a Generic Host. In a plainServiceCollectionsetup as above, create the schema instead withcontext.Database.EnsureCreated().
A complete, runnable example (project setup, seeding a dialog without the designer, a facade run,
your own INotificationHandler):
docs/GETTING-STARTED-Console.md.
Quickstart (Web / Endpoints)
In a web host o.ApplyMigrations() is the convenient choice – the WebApplicationBuilder is a Generic
Host and starts the migration service on boot. Excerpt from the web sample
(src/Flirty.Samples.Web/WebSampleApp.cs):
builder.Services.AddFlirty(o =>
{
o.UseSqlite(connectionString); // or UsePostgreSql(...) / UseSqlServer(...)
o.ApplyMigrations(); // auto-migration on start
o.AddWebhook(TriggerScope.OnDialogCompleted, baseUrl + "/demo/webhooks/flirty");
});
// Your own in-process handler as a back channel into the app.
builder.Services.AddFlirtyHandler<DialogCompletedNotification, DemoDialogCompletedHandler>();
var app = builder.Build();
app.MapFlirtyEndpoints("/flirty"); // package Flirty.AspNetCore
app.Run();
MapFlirtyEndpoints registers four endpoints (a thin layer over the Mediator commands) and returns the
RouteGroupBuilder – e.g. for .RequireAuthorization():
| Method & route | Meaning |
|---|---|
POST /flirty/sessions |
Start a dialog (or resume an existing session) |
GET /flirty/sessions/{id} |
Read the state (resume after a reload) |
POST /flirty/sessions/{id}/answers |
Submit an answer |
PUT /flirty/sessions/{id}/answers/{questionId} |
Edit an earlier answer |
Additionally, app.MapFlirtyAdminEndpoints("/flirty/admin") registers the configuration CRUD
(dialogs, questions, answer options, transitions, loops, triggers) – the same operations the
designer uses. Be sure to secure this in production (e.g. .RequireAuthorization()).
Full guide (setup, request/response examples, error mapping, admin CRUD):
docs/GETTING-STARTED-WebApi.md.
Start the designer
dotnet run --project src/Flirty.Designer
Then open http://localhost:5016. First, under Connections
(/connections), create, test and activate a connection profile (provider + connection string,
incl. "Migrate"); then, under Dialogs (/dialogs), configure dialogs, questions, answer options,
transitions, loops and triggers. The test runner (/dialogs/{id}/test) plays even
unpublished drafts through with the real engine. Details:
docs/DESIGNER.md.
Running the samples
dotnet run --project src/Flirty.Samples # console dialog in the terminal
dotnet run --project src/Flirty.Samples.Web # chat UI at http://localhost:5080
The web sample creates a demo dialog on start and shows branching, a loop over a list, resume after a reload, editing individual answers as well as fired triggers and received webhooks.
Documentation
Getting started
- Getting Started (Console):
docs/GETTING-STARTED-Console.md - Getting Started (WebAPI):
docs/GETTING-STARTED-WebApi.md - Getting Started (web sample / chat UI):
docs/GETTING-STARTED-Sample-Web.md - Designer (Blazor):
docs/DESIGNER.md
Concepts
- Architecture overview:
docs/ARCHITECTURE.md - Domain model & EF configuration:
docs/DOMAIN-MODEL.md - Runtime (start/resume/submit/edit):
docs/RUNTIME.md - Persistence & migrations:
docs/PERSISTENCE.md - Mediator setup:
docs/MEDIATOR.md - Branching / expressions:
docs/BRANCHING-EXPRESSIONS.md - Loops:
docs/LOOPS.md - Triggers (notifications + webhooks):
docs/TRIGGERS.md - Answer validation:
docs/VALIDATION.md - MCP server (tools for an MCP client):
docs/MCP.md
Project & operations
- NuGet packaging:
docs/NUGET-PACKAGING.md - CI pipeline:
docs/CI.md - Roadmap / backlog:
docs/ROADMAP.md,docs/BACKLOG.md - Decisions (ADRs):
docs/adr/– why Mediator, why an ASP.NET-free core, why a sandboxed expression engine, why migrations per provider, why published dialog versions are immutable, why the designer canvas is built in-house, why the canvas layout lives in its own table, why the MCP server is a package of its own, why an MCP client picks its database by route
Build & Test
dotnet build Flirty.sln
dotnet test tests/Flirty.Tests # unit/integration tests
dotnet test tests/Flirty.E2E # Playwright E2E (browser required, see below)
dotnet pack -c Release -o artifacts # Flirty.*.nupkg + Flirty.AspNetCore.*.nupkg (+ .snupkg)
The two test projects are deliberately started separately:
dotnet testwithout a target runs them in parallel, which makes the browser-driven E2E compete with the unit suite for the same cores. The E2E need Chromium (pwsh tests/Flirty.E2E/bin/Release/net10.0/playwright.ps1 install chromium); if it is missing, they skip themselves. The PostgreSQL/SQL Server tests need Docker and are likewise skipped without Docker. The target framework is .NET 10 (SDK required).
Publishing goes through the
release.ymlworkflow – manually and behind an approval gate:docs/NUGET-PACKAGING.md§ Publishing.
License & Feedback
MIT – see LICENSE.
Questions, bugs and requests are welcome as a GitHub issue.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- DynamicExpresso.Core (>= 2.19.3)
- Mediator.Abstractions (>= 3.0.2)
- Microsoft.EntityFrameworkCore (>= 10.0.9)
- Microsoft.EntityFrameworkCore.Sqlite (>= 10.0.9)
- Microsoft.EntityFrameworkCore.SqlServer (>= 10.0.9)
- Microsoft.Extensions.DependencyInjection (>= 10.0.10)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Http (>= 10.0.10)
- Microsoft.Extensions.Http.Resilience (>= 10.8.0)
- Microsoft.Extensions.Logging (>= 10.0.10)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.10)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 10.0.3)
- SQLitePCLRaw.lib.e_sqlite3 (>= 3.53.3)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Flirty:
| Package | Downloads |
|---|---|
|
Flirty.Mcp
Optional Model Context Protocol server (MapFlirtyMcp) for the Flirty dialog engine. |
|
|
Flirty.AspNetCore
Optional ASP.NET Core endpoints (MapFlirtyEndpoints) for the Flirty dialog engine. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 202608.4.0 | 112 | 8/7/2026 |
| 202608.3.0 | 121 | 8/5/2026 |