Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 5 additions & 150 deletions skills/sdk-install/csharp.md
Original file line number Diff line number Diff line change
@@ -1,155 +1,10 @@
# C# SDK Install

Reference guide for installing the Braintrust C# SDK.
**Read https://www.braintrust.dev/docs/sdks/csharp/install-and-instrument and follow it.**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prefetch the per-language install pages

When bt setup instrument launches a sandboxed or otherwise web-restricted coding agent, this stub leaves it without installation instructions. The setup prefetch only downloads URLs recognized by src/setup/docs.rs::workflow_from_url as /docs/instrument/...; these new /docs/sdks/... pages are excluded, while sdk_install_docs::write_sdk_install_docs merely writes this link into the temporary directory. Thus the CLI can report that the latest docs were fetched successfully and then require a second network access the agent may not have, causing installation to abort or be guessed. Add these language pages to the CLI's prefetch set and point the guides at the downloaded copies.

Useful? React with 👍 / 👎.


- SDK repo: https://github.com/braintrustdata/braintrust-sdk-dotnet
- NuGet: https://www.nuget.org/packages/Braintrust.Sdk
- Requires .NET 8.0+

## Find the latest version of the SDK

Look up the latest version from NuGet **without installing anything**. Do not guess -- use a read-only query so the environment stays unchanged until you write the version into the project file.

```bash
dotnet package search Braintrust.Sdk --exact-match
```

Then install that version (the latest published release):

### .NET CLI

```bash
dotnet add package Braintrust.Sdk --version <VERSION>
```

### Or add to .csproj

```xml
<ItemGroup>
<PackageReference Include="Braintrust.Sdk" Version="<VERSION>" />
</ItemGroup>
```

## Initialize the SDK

```csharp
using Braintrust.Sdk;
using Braintrust.Sdk.Config;

var apiKey = Environment.GetEnvironmentVariable("BRAINTRUST_API_KEY");
Braintrust? braintrust = null;
System.Diagnostics.ActivitySource? activitySource = null;

if (!string.IsNullOrEmpty(apiKey))
{
// Set the project name in code (do NOT require an env var for project name).
var config = BraintrustConfig.Of(
("BRAINTRUST_API_KEY", apiKey),
("BRAINTRUST_DEFAULT_PROJECT_NAME", "my-project")
);

braintrust = Braintrust.Get(config);
activitySource = braintrust.GetActivitySource();
}
```

`Braintrust.Get(config)` is the main entry point. The SDK requires an API key to be present, so initialize Braintrust conditionally and run the application normally when `BRAINTRUST_API_KEY` is missing. `GetActivitySource()` returns the `System.Diagnostics.ActivitySource` used to create spans.

## Install instrumentation

The C# SDK instruments LLM clients by wrapping them. Only instrument clients that are actually present in the project.

### OpenAI (`OpenAI` NuGet package)

```bash
dotnet add package OpenAI
```

Create an instrumented OpenAI client:
That page is the source of truth for installing and instrumenting the Braintrust C# SDK -- package installation, initialization, and the supported LLM client wrappers. Do not install or instrument from remembered snippets; they go stale.

```csharp
using Braintrust.Sdk;
using Braintrust.Sdk.Config;
using Braintrust.Sdk.Instrumentation.OpenAI;
Supporting references, if you need them:

var btApiKey = Environment.GetEnvironmentVariable("BRAINTRUST_API_KEY");
var openAIApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");

if (!string.IsNullOrEmpty(btApiKey) && !string.IsNullOrEmpty(openAIApiKey))
{
var config = BraintrustConfig.Of(
("BRAINTRUST_API_KEY", btApiKey),
("BRAINTRUST_DEFAULT_PROJECT_NAME", "my-project")
);
var braintrust = Braintrust.Get(config);
var activitySource = braintrust.GetActivitySource();
var client = BraintrustOpenAI.WrapOpenAI(activitySource, openAIApiKey);

// Optional: create a root activity so you can generate a permalink.
using var activity = activitySource.StartActivity("braintrust-openai-example");

var chatClient = client.GetChatClient("gpt-5-mini");
var response = await chatClient.CompleteChatAsync(
new ChatMessage[]
{
new SystemChatMessage("You are a helpful assistant."),
new UserChatMessage("What is the capital of France?")
}
);

if (activity != null)
{
var projectUri = await braintrust.GetProjectUriAsync();
var url = $"{projectUri}/logs?r={activity.TraceId}&s={activity.SpanId}";
Console.WriteLine($"View your data in Braintrust: {url}");
}
}
```

### Custom spans

For business logic that isn't an LLM call, create spans manually with the `ActivitySource`:

```csharp
using (var activity = activitySource.StartActivity("my-operation"))
{
activity?.SetTag("some.attribute", "value");
// LLM calls inside here are automatically nested under this span
}
```

## Run the application

Try to figure out how to run the application from the project structure:

- **dotnet run**: `dotnet run` or `dotnet run --project path/to/Project.csproj`
- **ASP.NET**: `dotnet run` (typically starts Kestrel)
- **Published app**: `dotnet path/to/app.dll`
- **Visual Studio / Rider**: run from IDE

If you can't determine how to run the app, ask the user.

## Generate a permalink (required)

The installer must produce a permalink to the emitted trace/logs in its final output.

In .NET, the most reliable permalink can be generated from the root Activity's TraceId/SpanId:

```csharp
if (braintrust != null && activitySource != null)
{
using var activity = activitySource.StartActivity("braintrust-install-verify");
if (activity != null)
{
// Perform a real operation that triggers LLM spans / instrumentation here.

var projectUri = await braintrust.GetProjectUriAsync();
var url = $"{projectUri}/logs?r={activity.TraceId}&s={activity.SpanId}";
Console.WriteLine($"View your data in Braintrust: {url}");
}
}
```

The final assistant response must include the printed URL.

If the SDK-generated URL is not available, construct the permalink manually using the URL format documented in `braintrust-url-formats.md` as described in the agent task (Step 5).
- SDK repo: https://github.com/braintrustdata/braintrust-sdk-dotnet
- NuGet: https://www.nuget.org/packages/Braintrust.Sdk
151 changes: 5 additions & 146 deletions skills/sdk-install/go.md
Original file line number Diff line number Diff line change
@@ -1,151 +1,10 @@
# Go SDK Install

Reference guide for installing the Braintrust Go SDK.
**Read https://www.braintrust.dev/docs/sdks/go/install-and-instrument and follow it.**

- SDK repo: https://github.com/braintrustdata/braintrust-sdk-go
- pkg.go.dev: https://pkg.go.dev/github.com/braintrustdata/braintrust-sdk-go
- Requires Go 1.22+

## Install the SDK

Install the latest Braintrust SDK. Do not hard-pin the SDK version unless the user asks -- `go get` without a version suffix is fine and will record whatever version `go mod tidy` resolves.

```bash
go get github.com/braintrustdata/braintrust-sdk-go
```

If you need to know what the latest version is:

```bash
go list -m -versions github.com/braintrustdata/braintrust-sdk-go
```

**Note:** Orchestrion, the build-time instrumentation tool described below, **must** be pinned to an exact version. That requirement is separate from the SDK itself.

## Instrument the application

**You must read https://www.braintrust.dev/docs/instrument/trace-llm-calls before instrumenting anything.** That page is the source of truth for supported providers and setup, and may have changed since this guide was written.

### Prefer automatic instrumentation (Orchestrion)

**Automatic instrumentation via [Orchestrion](https://github.com/DataDog/orchestrion) is the recommended path and should be used whenever possible.** It injects tracing at compile time with no wrapper code in the application, so LLM client calls are traced automatically across your codebase and third-party code.

Manual span/wrapper code should only be used as a **last resort** -- e.g. for bespoke business-logic spans, or when a provider isn't yet supported by the Orchestrion contrib packages. Don't reach for manual tracing before confirming Orchestrion can do the job.

### Quick start

Every Go project needs OpenTelemetry setup and a Braintrust client.

```go
package main

import (
"log"

"github.com/braintrustdata/braintrust-sdk-go"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/trace"
)

func main() {
tp := trace.NewTracerProvider()
otel.SetTracerProvider(tp)

_, err := braintrust.New(tp, braintrust.WithProject("my-project"))
if err != nil {
log.Fatal(err)
}
}
```

`braintrust.New` reads `BRAINTRUST_API_KEY` from the environment automatically.

### Requirement: persist Orchestrion into the normal build/run path

Auto-instrumentation requires the project to be built and run with Orchestrion. A one-off `orchestrion go build` during verification is **not enough** if the next developer, CI job, or deploy will go back to plain `go build` / `go run`.

**1. Resolve and pin an exact Orchestrion version:**

Orchestrion is a build-time dependency that modifies the Go toolchain, so it **must** be pinned to an exact version for reproducible builds -- this is different from the Braintrust SDK itself.

```bash
go list -m -versions github.com/DataDog/orchestrion
go install github.com/DataDog/orchestrion@vX.Y.Z
```

Do not use `@latest`. Prefer the newest version that is compatible with the project's existing `go` / `toolchain` version. If Orchestrion would require bumping the project's Go version or toolchain, ask the user before making that change.

**2. Create `orchestrion.tool.go` in the module root (the same directory as `go.mod`):**
That page is the source of truth for installing and instrumenting the Braintrust Go SDK -- supported providers, their `trace/contrib/` import paths, and build-time instrumentation setup. Do not install or instrument from remembered snippets; they go stale.

Prefer importing only the integrations the project actually uses. Use `trace/contrib/all` only if provider detection is genuinely unclear or the project uses many supported integrations.
Supporting references, if you need them:

To instrument all supported providers:

```go
//go:build tools

package main

import (
_ "github.com/DataDog/orchestrion"
_ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/all"
)
```

Or import only the integrations the project actually uses:

```go
//go:build tools

package main

import (
_ "github.com/DataDog/orchestrion"
_ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/anthropic" // anthropic-sdk-go
_ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/genai" // Google GenAI
_ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/github.com/sashabaranov/go-openai" // sashabaranov/go-openai
_ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/langchaingo" // LangChainGo
_ "github.com/braintrustdata/braintrust-sdk-go/trace/contrib/openai" // openai-go
)
```

Then run `go mod tidy` so the exact Orchestrion and contrib versions are recorded in `go.mod` / `go.sum`.

**3. Persist Orchestrion into the project's actual workflow:**

Update the command the project already expects developers or CI to use:

- `Makefile` / `justfile` / shell scripts: change `go build`, `go run`, and `go test` invocations to `orchestrion go ...` where appropriate.
- `Dockerfile`: change build steps to use Orchestrion.
- Bootstrap / CI / devcontainer setup: if the repo already has a checked-in way to install required tooling, add Orchestrion there too so future users do not hit `orchestrion: command not found`.
- Repo-local env/config files: if the project already uses a checked-in mechanism for env vars, set `GOFLAGS="-toolexec=orchestrion toolexec"` there.

A shell-local `export GOFLAGS=...` in the current terminal does **not** satisfy this requirement by itself, because it will not help the next user or CI run.

If you add `orchestrion.tool.go` but do **not** modify any persisted build/run path, treat the installation as incomplete.

**4. Verify using the same persisted command:**

After wiring Orchestrion into the normal workflow, run that exact command and confirm traces are emitted. Do not verify with a custom one-off command that the project will not use later.

After this, LLM client calls are automatically traced with no application wrapper code.

### Supported providers

For the current list of supported providers and their `trace/contrib/` import paths, see https://www.braintrust.dev/docs/instrument/trace-llm-calls.

## Run the application

Prefer the project's existing build/run entrypoint, and make sure that entrypoint now goes through Orchestrion.

Try to figure out how the project is normally run from the project structure:

- **Makefile / justfile / scripts**: prefer `make run`, `just run`, or the existing repo script if present
- **go run**: if the project is normally run directly, update that path to `orchestrion go run .` or `orchestrion go run ./cmd/myapp`
- **Docker**: check for a `Dockerfile` or container build script

If you can't determine how the app is supposed to be built or run in normal use, ask the user before proceeding.

## Generate a permalink (required)

Follow the permalink generation steps in the agent task (Step 5). Use the project name you configured in code above.
- SDK repo: https://github.com/braintrustdata/braintrust-sdk-go
- pkg.go.dev: https://pkg.go.dev/github.com/braintrustdata/braintrust-sdk-go
2 changes: 1 addition & 1 deletion skills/sdk-install/instrument-task.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- **Only add Braintrust code.** Do not refactor or modify unrelated code.
- **One language, one service per install run.** If the repo has more than one candidate, ask the user which one to instrument before starting. Do not instrument multiple languages or services in the same run.
- **If the language is unclear, ask the user.** Do not guess. See Step 2.
- **Install the latest Braintrust SDK.** Do not hard-pin the Braintrust SDK version unless the user asks for it -- use the package manager's normal install (which may produce an exact or a ranged version, whichever is idiomatic for that ecosystem). Build-time dependencies (e.g. Orchestrion for Go) must still be pinned to an exact version -- see the language-specific resource.
- **Install the latest Braintrust SDK.** Do not hard-pin the Braintrust SDK version unless the user asks for it -- use the package manager's normal install (which may produce an exact or a ranged version, whichever is idiomatic for that ecosystem). Build-time dependencies (e.g. Orchestrion for Go) must still be pinned to an exact version -- see the language's install docs.
- **Set the project name in code.** Do NOT configure project name via env vars.
- **App must run without Braintrust.** If `BRAINTRUST_API_KEY` is missing at runtime, do not crash.
- **Abort install if API key is not set.** (Do not modify runtime behavior.)
Expand Down
Loading
Loading