Firstflow.Sdk
1.0.0
See the version list below for details.
dotnet add package Firstflow.Sdk --version 1.0.0
NuGet\Install-Package Firstflow.Sdk -Version 1.0.0
<PackageReference Include="Firstflow.Sdk" Version="1.0.0" />
<PackageVersion Include="Firstflow.Sdk" Version="1.0.0" />
<PackageReference Include="Firstflow.Sdk" />
paket add Firstflow.Sdk --version 1.0.0
#r "nuget: Firstflow.Sdk, 1.0.0"
#:package Firstflow.Sdk@1.0.0
#addin nuget:?package=Firstflow.Sdk&version=1.0.0
#tool nuget:?package=Firstflow.Sdk&version=1.0.0
Firstflow.Sdk (.NET)
Firstflow server SDK for .NET. Sign widget auth tokens and forward LLM
observability/analytics telemetry to Firstflow Cloud. The wire contract matches
the Node @firstflow/sdk byte-for-byte, so both SDKs talk to the same backend.
Status:
0.0.1-alpha. Auth + manual instrumentation, theIChatClientauto-capture middleware (UseFirstflow()), and OpenTelemetry GenAI spans are all implemented.
Install
dotnet add package Firstflow.Sdk
Targets net8.0.
Configuration
All values can come from configuration or these environment variables:
| Variable | Purpose |
|---|---|
FIRSTFLOW_API_KEY |
Bearer token for telemetry ingestion. Required for everything except SignToken. |
FIRSTFLOW_API_BASE_URL |
Override the cloud base URL (default https://api.firstflow.app). |
FIRSTFLOW_SIGNING_SECRET |
Workspace signing secret (fss_…) used by SignToken. |
FIRSTFLOW_DEBUG |
Log queue/forwarding diagnostics. |
ASP.NET Core (dependency injection)
builder.Services.AddFirstflow(); // binds env vars; or AddFirstflow(o => o.ApiKey = "...")
public sealed class ChatController(IFirstflowClient firstflow) : ControllerBase
{
[HttpGet("/widget-token")]
public string Token() => firstflow.SignToken(new SignTokenOptions
{
AgentId = "agt_abc123",
UserId = User.Identity!.Name!,
Traits = new Dictionary<string, object?> { ["plan"] = "pro" },
});
}
AddFirstflow registers a singleton IFirstflowClient, wires an
IHttpClientFactory client, and adds a hosted service that flushes pending
telemetry on shutdown.
Console / non-DI (static facade)
using Firstflow;
var token = FirstflowSdk.SignToken(new SignTokenOptions { AgentId = "agt_abc123", UserId = "u_1" });
FirstflowSdk.Observe(new ObserveInput
{
FirstflowAgentId = "agt_abc123",
SessionId = "sess_1",
UserId = "u_1",
Role = "assistant",
Content = "Hello!",
Model = "gpt-4o",
InputTokens = 1200,
OutputTokens = 80, // cost is filled in from the pricing table automatically
});
In short-lived environments (e.g. AWS Lambda) call await FirstflowSdk.FlushAsync()
before the handler returns — background drain isn't guaranteed there.
Automatic LLM capture (Microsoft.Extensions.AI)
Wrap any IChatClient (OpenAI, Azure OpenAI, Anthropic, Ollama, …) with the
Firstflow middleware to capture prompts, completions, token usage, cost, latency,
and streaming automatically:
using Microsoft.Extensions.AI;
IChatClient client = openAiClient
.AsIChatClient()
.AsBuilder()
.UseFirstflow() // sits alongside UseOpenTelemetry()/UseLogging()
.Build();
Tag each call with the agent/session/user it belongs to. Calls without all three pass through unobserved:
var options = new ChatOptions { ModelId = "gpt-4o" }
.WithFirstflow(agentId: "agt_abc123", sessionId: "sess_1", userId: "u_1");
var response = await client.GetResponseAsync("Hello!", options);
Token usage and cost come from the normalized UsageDetails, so the same wrapper
works across providers — streaming included.
OpenTelemetry GenAI spans
The middleware emits a span per call via the Firstflow.ChatClient activity
source, following the OpenTelemetry GenAI semantic conventions and tagged with
firstflow.agent_id / session_id / user_id (also set as baggage so child
spans inherit them). Register the source to export it:
builder.Services.AddOpenTelemetry().WithTracing(t => t
.AddSource("Firstflow.ChatClient")
.AddOtlpExporter());
Prompt and completion content is excluded by default. Enable it with
FIRSTFLOW_CAPTURE_LLM_CONTENT=true or UseFirstflow(configure: o => o.CaptureLlmContent = true).
When no tracer listens to the source, span creation is a no-op with no overhead.
Note: a direct decorator for the official OpenAI .NET SDK (for callers who bypass
IChatClient) is intentionally not included — wrap viaAsIChatClient().
What you can record
SignToken— mint a tamper-proof widget JWT (HS256, no network).Observe— record a conversation turn (with token usage / cost / latency).Outcome— signal how a session ended (completed/abandoned/escalated/ custom).Track/Identify— analytics events and user traits.Trace— a trace with nested spans for detailed observability.ListAccessibleAgentsAsync— the agents an API key can access.
All telemetry calls are fire-and-forget: they enqueue and return immediately, never blocking the request and never throwing.
| Product | Versions 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 was computed. 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. |
-
net8.0
- Microsoft.Extensions.AI (>= 10.7.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.9)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.9)
- Microsoft.Extensions.Http (>= 10.0.9)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.9)
- Microsoft.Extensions.Options (>= 10.0.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.