Firstflow.Sdk
1.0.1
dotnet add package Firstflow.Sdk --version 1.0.1
NuGet\Install-Package Firstflow.Sdk -Version 1.0.1
<PackageReference Include="Firstflow.Sdk" Version="1.0.1" />
<PackageVersion Include="Firstflow.Sdk" Version="1.0.1" />
<PackageReference Include="Firstflow.Sdk" />
paket add Firstflow.Sdk --version 1.0.1
#r "nuget: Firstflow.Sdk, 1.0.1"
#:package Firstflow.Sdk@1.0.1
#addin nuget:?package=Firstflow.Sdk&version=1.0.1
#tool nuget:?package=Firstflow.Sdk&version=1.0.1
Firstflow.Sdk (.NET)
Firstflow server SDK for .NET. Forward LLM observability and product-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:
1.0.0. 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. |
FIRSTFLOW_API_BASE_URL |
Override the cloud base URL (default https://api.firstflow.app). |
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
{
[HttpPost("/chat")]
public async Task<IActionResult> Send(ChatRequest req)
{
var reply = await CallYourLlm(req);
// Record the turn — token counts, cost, latency, etc.
firstflow.Observe(new ObserveInput
{
FirstflowAgentId = "agt_abc123",
SessionId = req.SessionId,
UserId = req.UserId,
Role = "assistant",
Content = reply.Text,
Model = "gpt-4o",
InputTokens = reply.InputTokens,
OutputTokens = reply.OutputTokens, // cost is auto-derived from the pricing table
});
return Ok(reply);
}
}
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;
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
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.