Go SDK

Native Go client for Trefur Observe. Batches and ships structured telemetry for agent observability and drift detection.

Install

go get github.com/trefur-ai/trefur-sdks/go/observe-go

Init

package main

import (
    "os"

    observe "github.com/trefur-ai/trefur-sdks/go/observe-go"
)

func main() {
    client := observe.Init(observe.Config{
        APIKey:    os.Getenv("TREFUR_API_KEY"),
        AgentName: os.Getenv("TREFUR_AGENT_NAME"),
    })
    defer client.Shutdown()

    // ... your agent code
}

Telemetry is buffered and shipped on a periodic flush. A short program can exit before that timer fires, so always defer client.Shutdown() right after Init. The deferred call runs on a normal return and on a panic, so it flushes the first trace on both the happy path and the error path.

Configuration

FieldTypeDefaultNotes
APIKeystringrequiredtrf_obs_*
Endpointstringhttps://observe.trefur.comIngest endpoint override
DebugboolfalseVerbose stderr logging
BatchSizeint10Buffer size before auto-flush
FlushIntervaltime.Duration5sPeriodic flush interval
AgentNamestringauto-detectedExplicit agent identity
AgentFrameworkstring"go"Reported in telemetry
Agent*AgentIdentityautoFull identity struct override
HTTPClient*http.Client10s timeout defaultCustom HTTP client (TLS pinning, proxies, etc.)

Recording telemetry

now := time.Now().UTC().Format(time.RFC3339)

client.Record(observe.TelemetryPayload{
    AgentName: "search-bot",
    Framework: "custom",
    Status:    "completed",
    StartedAt: now,
    Steps: []observe.StepPayload{
        {
            StepType:  "tool_call",
            ToolName:  "search",
            Status:    "completed",
            StartedAt: now,
            EndedAt:   now,
        },
    },
})

// Flush before process exit (also called by Shutdown).
client.Flush()

Automatic instrumentation

For outbound HTTP, the SDK hands you an *http.Client whose transport records each call as a structured step — no per-call wiring. Use it for your agent's outbound requests and every LLM REST call (Anthropic / OpenAI / Gemini) and known SaaS tool call is captured and classified automatically:

client := observe.Init(observe.Config{
    APIKey: os.Getenv("TREFUR_API_KEY"),
})
defer client.Shutdown()

// An *http.Client whose transport records every outbound call.
httpClient := observe.InstrumentedHTTPClientWith(client)

resp, err := httpClient.Get("https://api.openai.com/v1/models")

Already have your own *http.Client (custom timeouts, proxy, TLS)? Drop the instrumented transport onto it and keep your configuration:

httpClient := &http.Client{
    Transport: observe.NewTransportWithClient(nil, client),
}

Subprocess capture is explicit by design in Go (there is no safe way to globally intercept process creation). Swap exec.Command for the instrumented form and the subprocess is recorded as a cli_exec step:

out, err := observe.Command("git", "clone", repoURL).Output()

The binary name is classified into an enriched tool name (e.g. aws.s3, git.clone, kubernetes.apply) so subprocess activity is attributed to a known tool in your traces.

Privacy guarantees

The privacy boundary is enforced inside the wrapper — you get the trace (that it happened, the endpoint, the tool, the status, the timing) without the wrapper reaching for your payloads or credentials.

  • HTTP: the wrapper records the request method, the normalized endpoint (scheme + host + path, query string stripped), and the response status — and classifies the destination. It does not read or record request/response bodies, headers, or URL query strings.
  • Subprocess: the wrapper records the binary name, the redacted argument list, the exit code, and the duration. Arguments that look secret-bearing — the value after a sensitive flag (--password, --token, --api-key, …), the value half of a sensitive --flag=value / KEY=VALUE pair, and standalone tokens matching a known secret prefix (sk-, ghp_, trf_, Bearer …) or a long opaque string — are replaced with [REDACTED] before recording. Subprocess output is never captured — neither stdout nor stderr leaves the process.
  • Self-traffic is skipped: calls to Trefur's own ingest endpoints are never recorded, so instrumentation can't loop on itself.

OTel emission

The Go SDK also exposes an OTel exporter (otel_emit.go) and a cloud-detection helper (clouddetect.go) that auto-stamps cloud-provider fingerprint fields on every payload.

Environment variables

Canonical list: env-vars reference.

Troubleshooting

SymptomFix
Process exits before telemetry flushes.Always defer client.Shutdown(). The shutdown blocks for the flush interval or until the buffer drains, whichever comes first.
Need a custom transport (e.g. behind a corporate proxy).Pass HTTPClient: &http.Client{...} with the desired transport.

Source + tests live in trefur-ai/trefur-sdks under go/observe-go. License: Apache 2.0.