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
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
working-directory: agenttel-go
run: go test -race -count=1 -timeout=120s ./...

# agenttel-go/go.work links the GenAI submodules to this checkout's agenttel-go
- name: Test GenAI Anthropic
working-directory: agenttel-go/genai/anthropic
run: go test -race -count=1 -timeout=60s ./...
Expand All @@ -63,6 +64,16 @@ jobs:
working-directory: agenttel-go/genai/openai
run: go test -race -count=1 -timeout=60s ./...

# Build the submodules exactly as consumers do: against the agenttel-go
# release their go.mod pins (no workspace, no replace)
- name: GenAI submodules against released agenttel-go
working-directory: agenttel-go
env:
GOWORK: 'off'
run: |
(cd genai/anthropic && go mod verify && go vet ./... && go test -count=1 ./...)
(cd genai/openai && go mod verify && go vet ./... && go test -count=1 ./...)

- name: Vet
working-directory: agenttel-go
run: go vet ./...
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ All SDKs now accept the Spring Boot dialect:
- **Added:** net/http middleware sets decision attributes and, for Go 1.22+ `ServeMux` patterns, records `http.route` and matches `GET /items/{id}` after routing.
- **Fixed:** `examples/go-service-example` and `examples/gin-example` compile and run against the real API (`agenttel.New().WithConfigFile(...).Build()`, `engine.SpanProcessor()`, `otelhttp` / `otelgin`).
- **Docs:** minimum versions are Go 1.24 and `go.opentelemetry.io/otel/sdk` v1.39.0 (previously documented as 1.22 / 1.33.0).
- **GenAI submodules released:** `go.agenttel.dev/agenttel-go/genai/openai` and `.../genai/anthropic` are tagged `v0.4.0-alpha`. They now require the published `agenttel-go v0.4.0-alpha`; previously they pinned an unpublished `v0.1.0` plus a `replace` and could not be installed. In-repo development uses `agenttel-go/go.work`, and CI also builds them without it, the same way consumers do.
- **Breaking (config struct only):** YAML tags on `AgentTelConfig` are now kebab-case. camelCase files still load, with a warning.

### JVM
Expand Down
22 changes: 22 additions & 0 deletions agenttel-go/genai/anthropic/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package anthropic_test

import (
"context"

"github.com/anthropics/anthropic-sdk-go"

agenttelanthropic "go.agenttel.dev/agenttel-go/genai/anthropic"
)

// Wrap the Anthropic Messages service; every message call becomes a gen_ai.*
// span with token usage and agenttel.genai.cost_usd.
func ExampleWrap() {
client := anthropic.NewClient()
traced := agenttelanthropic.Wrap(&client.Messages)

_, _ = traced.CreateMessage(context.Background(), anthropic.MessageNewParams{
Model: anthropic.ModelClaudeSonnet4_5,
MaxTokens: 1024,
Messages: []anthropic.MessageParam{anthropic.NewUserMessage(anthropic.NewTextBlock("Hello"))},
})
}
6 changes: 2 additions & 4 deletions agenttel-go/genai/anthropic/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ toolchain go1.24.13

require (
github.com/anthropics/anthropic-sdk-go v1.27.1
go.agenttel.dev/agenttel-go v0.1.0
go.agenttel.dev/agenttel-go v0.4.0-alpha
go.opentelemetry.io/otel v1.39.0
go.opentelemetry.io/otel/sdk v1.39.0
go.opentelemetry.io/otel/trace v1.39.0
Expand All @@ -23,8 +23,6 @@ require (
github.com/tidwall/sjson v1.2.5 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel/metric v1.39.0 // indirect
golang.org/x/sync v0.16.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
)

replace go.agenttel.dev/agenttel-go => ../../
6 changes: 4 additions & 2 deletions agenttel-go/genai/anthropic/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
go.agenttel.dev/agenttel-go v0.4.0-alpha h1:xoHcxGouP+ZZYHR5rEMxDc/cwtcOTxyJYh0S3LHW7is=
go.agenttel.dev/agenttel-go v0.4.0-alpha/go.mod h1:bxtOzraHvRCDnQb19XzbsGOcU8NCj5maDpzYdPEbhjY=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
Expand All @@ -43,8 +45,8 @@ go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
Expand Down
21 changes: 21 additions & 0 deletions agenttel-go/genai/openai/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package openai_test

import (
"context"

goopenai "github.com/sashabaranov/go-openai"

agenttelopenai "go.agenttel.dev/agenttel-go/genai/openai"
)

// Wrap a go-openai client; every chat completion becomes a gen_ai.* span with
// token usage and agenttel.genai.cost_usd.
func ExampleWrap() {
client := goopenai.NewClient("sk-...")
traced := agenttelopenai.Wrap(client)

_, _ = traced.CreateChatCompletion(context.Background(), goopenai.ChatCompletionRequest{
Model: goopenai.GPT4o,
Messages: []goopenai.ChatCompletionMessage{{Role: goopenai.ChatMessageRoleUser, Content: "Hello"}},
})
}
4 changes: 1 addition & 3 deletions agenttel-go/genai/openai/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ toolchain go1.24.13

require (
github.com/sashabaranov/go-openai v1.36.1
go.agenttel.dev/agenttel-go v0.1.0
go.agenttel.dev/agenttel-go v0.4.0-alpha
go.opentelemetry.io/otel v1.39.0
go.opentelemetry.io/otel/sdk v1.39.0
go.opentelemetry.io/otel/trace v1.39.0
Expand All @@ -21,5 +21,3 @@ require (
go.opentelemetry.io/otel/metric v1.39.0 // indirect
golang.org/x/sys v0.39.0 // indirect
)

replace go.agenttel.dev/agenttel-go => ../../
2 changes: 2 additions & 0 deletions agenttel-go/genai/openai/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ github.com/sashabaranov/go-openai v1.36.1 h1:EVfRXwIlW2rUzpx6vR+aeIKCK/xylSrVYAx
github.com/sashabaranov/go-openai v1.36.1/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.agenttel.dev/agenttel-go v0.4.0-alpha h1:xoHcxGouP+ZZYHR5rEMxDc/cwtcOTxyJYh0S3LHW7is=
go.agenttel.dev/agenttel-go v0.4.0-alpha/go.mod h1:bxtOzraHvRCDnQb19XzbsGOcU8NCj5maDpzYdPEbhjY=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
Expand Down
10 changes: 10 additions & 0 deletions agenttel-go/go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Local development workspace: the GenAI submodules build against this
// checkout's agenttel-go instead of the released version their go.mod pins.
// Set GOWORK=off to build them exactly as consumers do.
go 1.24.0

use (
.
./genai/anthropic
./genai/openai
)
1 change: 1 addition & 0 deletions agenttel-go/go.work.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
45 changes: 39 additions & 6 deletions docs/getting-started/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,15 +334,48 @@ HTTP server spans get topology, static baselines and decision attributes (`retry

### 4. GenAI Instrumentation (Optional)

```go
import "go.agenttel.dev/agenttel-go/genai"
The OpenAI and Anthropic wrappers are separate Go modules, so the core SDK doesn't pull in either vendor SDK:

builder := genai.NewSpanBuilder(tracer)
ctx, span := builder.StartChatSpan(ctx, "gpt-4o", "openai")
// ... make LLM call ...
genai.EndSpanSuccess(span, promptTokens, completionTokens, "gpt-4o")
```bash
go get go.agenttel.dev/agenttel-go/genai/openai@v0.4.0-alpha # github.com/sashabaranov/go-openai
go get go.agenttel.dev/agenttel-go/genai/anthropic@v0.4.0-alpha # github.com/anthropics/anthropic-sdk-go
```

=== "OpenAI"

```go
import agenttelopenai "go.agenttel.dev/agenttel-go/genai/openai"

traced := agenttelopenai.Wrap(openai.NewClient(apiKey))
resp, err := traced.CreateChatCompletion(ctx, req) // also CreateChatCompletionStream
```

=== "Anthropic"

```go
import agenttelanthropic "go.agenttel.dev/agenttel-go/genai/anthropic"

client := anthropic.NewClient()
traced := agenttelanthropic.Wrap(&client.Messages)
msg, err := traced.CreateMessage(ctx, params) // also CreateMessageStreaming
```

=== "Any other LLM client"

```go
import "go.agenttel.dev/agenttel-go/genai"

ctx, span := genai.NewSpanBuilder(tracer).StartChatSpan(ctx, "gpt-4o", "openai")
// ... make the LLM call ...
genai.EndSpanSuccess(span, genai.ChatResult{
ResponseModel: "gpt-4o",
InputTokens: promptTokens,
OutputTokens: completionTokens,
})
```

Each call becomes a `gen_ai.*` span with token usage and `agenttel.genai.cost_usd`.

### 5. Agentic Observability (Optional)

```go
Expand Down
Loading