BotWire.AspNetCore 0.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package BotWire.AspNetCore --version 0.1.0
                    
NuGet\Install-Package BotWire.AspNetCore -Version 0.1.0
                    
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="BotWire.AspNetCore" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BotWire.AspNetCore" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="BotWire.AspNetCore" />
                    
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 BotWire.AspNetCore --version 0.1.0
                    
#r "nuget: BotWire.AspNetCore, 0.1.0"
                    
#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 BotWire.AspNetCore@0.1.0
                    
#: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=BotWire.AspNetCore&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=BotWire.AspNetCore&version=0.1.0
                    
Install as a Cake Tool

BotWire

Low-cost AI customer-support for your .NET website. Drop one NuGet package into your ASP.NET Core app, point it at your FAQ, and ship a 24/7 support assistant that answers customers instantly — and quietly opens a support ticket the moment a human is actually needed.

No SaaS seat fees. No per-conversation pricing. You bring your own OpenAI-compatible API key, so your only running cost is the model tokens — pennies per conversation with gpt-4o-mini or DeepSeek.

BotWire chat widget on a demo store

Why BotWire

  • Cheap to run. No platform subscription. Bring your own key; pay only for model tokens. Run it on gpt-4o-mini, DeepSeek, or any OpenAI-compatible endpoint to keep costs near zero.
  • One package, two lines of code. AddBotWire() + MapBotWire(). The chat widget, streaming endpoint, escalation logic, and ticket email are all included.
  • Grounded in your docs. Answers come only from the Markdown knowledge base you supply — no hallucinated policies, prices, or promises.
  • Knows when to get a human. When a customer needs account/order access or asks for a person, BotWire collects their contact details and raises a support ticket instead of guessing.
  • Multilingual out of the box. Replies in whatever language the customer writes in; you choose the language your team reads tickets in.
  • Zero-dependency widget. A ~12KB Web Component (Shadow DOM, no framework) you embed with a single <script> tag.
  • Self-hostable & open. AGPL-3.0. Your data and prompts stay in your app. Commercial licenses available if AGPL doesn't fit.

How it works

1. The customer asks — BotWire answers from your FAQ, streaming token-by-token.

Bot answering a return-policy question

2. When the question needs a human, it collects contact details instead of guessing.

Bot collecting customer email for escalation

3. A support ticket is created and emailed to your team — the customer gets a confirmation.

Support ticket confirmation in the widget

Quick start

Install the package:

dotnet add package BotWire.AspNetCore

Wire it up in Program.cs:

builder.Services.AddBotWire(opts =>
{
    opts.TopicDescription = "Online store customer support";
    opts.Documents        = ["docs/faq.md"];
    opts.ChatProvider     = new OpenAIProviderOptions { ApiKey = "sk-...", Model = "gpt-4o-mini" };

    // Optional: email tickets to your team when the bot escalates.
    opts.Email = new EmailOptions
    {
        SmtpHost = "smtp.example.com", Port = 587,
        FromAddress = "support-bot@example.com", ToAddress = "support@example.com",
    };
});

app.UseCors();
app.MapBotWire();

Embed the widget on any page:

<script src="/botwire/widget.js"></script>
<botwire-widget
    data-endpoint="/support"
    data-title="Acme Support"
    data-primary-color="#6366f1"
    data-position="bottom-right">
</botwire-widget>

That's it — the bot answers from docs/faq.md and raises tickets when it can't.

Configuration reference

Property Default Description
TopicDescription (required) Short phrase describing your support scope, injected into the system prompt.
Documents [] Paths to Markdown knowledge-base files.
ChatProvider (required) LLM provider — ApiKey, Model, optional BaseUrl for OpenAI-compatible APIs (e.g. DeepSeek).
MaxMessageLength 2000 Max user message length in characters.
MaxRequestsPerIpPerMinute 20 IP rate-limit cap.
SessionTtl 2 hours Idle session lifetime.
Email null SMTP settings for ticket notification emails. null disables email.
TicketLanguage "English" Language the AI writes ticket summary/details in. Customer-facing replies always match the customer's own language.

Customization

Custom system prompt

Register your own ISystemPromptBuilder before calling AddBotWire() to fully replace the built-in prompt:

builder.Services.AddSingleton<ISystemPromptBuilder, MyPromptBuilder>();
builder.Services.AddBotWire(opts => { ... });

ISystemPromptBuilder.Build(documents) receives the loaded knowledge-base document contents and must return the complete system prompt. Your implementation must preserve the control-word contract: the model's first line must be either ANSWER or ESCALATE on its own line, otherwise escalation and ticket creation stop working.

Ticket language

Set TicketLanguage to any natural-language name the model understands. The AI writes ticket summary and details in that language regardless of what language the customer used:

builder.Services.AddBotWire(opts =>
{
    opts.TicketLanguage = "简体中文"; // or "Français", "日本語", etc.
});

Customer-facing chat replies are not affected — the bot always replies in the same language the customer wrote in.

React to created tickets

Hook OnTicketCreated to push tickets into your own system (database, queue, CRM) in addition to (or instead of) email:

opts.OnTicketCreated = async ticket =>
{
    await db.Tickets.AddAsync(ticket);
    await db.SaveChangesAsync();
};

Custom email template

Register your own IEmailTemplateFormatter to control how tickets are formatted in email:

builder.Services.AddSingleton<IEmailTemplateFormatter, MyEmailFormatter>();

Running tests

Unit tests (no API key needed)

dotnet test --filter "Category!=RequiresMailpit"

Integration tests — LLM (requires an OpenAI-compatible API key)

Set the provider env vars, then run:

# PowerShell — OpenAI (default)
$env:BOTWIRE_TEST_API_KEY = "sk-..."
dotnet test tests/BotWire.AspNetCore.IntegrationTests

# PowerShell — DeepSeek (or any OpenAI-compatible provider)
$env:BOTWIRE_TEST_API_KEY  = "sk-..."
$env:BOTWIRE_TEST_MODEL    = "deepseek-chat"
$env:BOTWIRE_TEST_BASE_URL = "https://api.deepseek.com"
dotnet test tests/BotWire.AspNetCore.IntegrationTests
# bash / CI — OpenAI (default)
export BOTWIRE_TEST_API_KEY=sk-...
dotnet test tests/BotWire.AspNetCore.IntegrationTests
Env var Default Description
BOTWIRE_TEST_API_KEY (required to run LLM tests) API key for the test provider.
BOTWIRE_TEST_MODEL gpt-4o-mini Model name.
BOTWIRE_TEST_BASE_URL (unset = standard OpenAI) Base URL for OpenAI-compatible providers.

LLM tests are skipped automatically when BOTWIRE_TEST_API_KEY is not set.

Integration tests — email escalation (requires Mailpit)

Install Mailpit and start it (SMTP on :1025, web UI on :8025):

mailpit

Then:

$env:BOTWIRE_TEST_API_KEY = "sk-..."
$env:MAILPIT_ENABLED      = "1"
dotnet test tests/BotWire.AspNetCore.IntegrationTests

Mailpit tests are tagged Category=RequiresMailpit and skipped unless both variables are set.

To exclude Mailpit tests from CI:

dotnet test --filter "Category!=RequiresMailpit"

AI provider & responsible use

BotWire does not include or provide any AI model or API. You supply your own OpenAI-compatible API key and account, and your only AI cost is what that provider charges. When you deploy BotWire:

  • Customer messages and your knowledge-base content are sent to the third-party LLM provider you configure. You are responsible for that provider's terms, pricing, data-processing, and privacy obligations.
  • You are responsible for the AI-generated output shown to your customers, and for disclosing AI use to end users where required by law.
  • BotWire grounds answers in your documents and includes prompt-injection defenses, but language-model output can still be wrong. Do not rely on it for decisions that require guaranteed accuracy without human review.

Customer PII

Handling your customers' personal data is your responsibility. BotWire ships a best-effort PII guard (enabled by default) that blocks user messages matching common patterns — email addresses, phone numbers, and credit-card-like numbers — before they are sent to the AI provider. Add your own patterns via PiiGuard.AdditionalPatterns:

builder.Services.AddBotWire(opts =>
{
    opts.PiiGuard.AdditionalPatterns.Add(@"\bACME-\d{6}\b"); // e.g. internal account numbers
});

This guard is regex-based and not exhaustive: it will not catch every form of personal data, and it rejects rather than redacts. You must confirm, for your own jurisdiction and data, that no personal data you are not permitted to share is sent to your AI provider — for example by tuning the patterns, restricting your knowledge-base content, and choosing a provider whose data-processing terms meet your obligations.

License

BotWire is available under the AGPL v3. Commercial licenses are available for proprietary use — see COMMERCIAL.md.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.4.0 106 6/26/2026
0.3.0 128 6/17/2026
0.2.0 119 6/12/2026
0.1.0 110 6/10/2026