# Go SDK API

> Interfaces, functions, options, parameters, return values, and helpers for the Anectico Go SDK.

Canonical page: https://anectico.com/docs/reference/go-sdk/


This is the application-developer API for `github.com/anectico/anectico/sdks/go`. The SDK is safe for
concurrent use and follows Go/OpenTelemetry context conventions.

Use `ingest:write` for traces, metrics, logs, and errors. Add `analytics:write` for identity, groups,
events, and flag exposures; add `flags:read` for decisions.

## Construct and run a client

```go
client, err := anectico.New(
	 anectico.WithAPIKey(os.Getenv("ANECTICO_API_KEY")),
	 anectico.WithServiceName("orders-api"),
)
if err != nil {
	return err
}
if err := client.Start(ctx); err != nil {
	return err
}
defer client.Stop(shutdownCtx)
```

| API | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `New(opts ...Option)` | functional options | `(Client, error)` | Creates an unstarted client or returns a configuration or transport-initialization error. |
| `Start(ctx)` | lifecycle context | `error` | Validates config and starts enabled transports. |
| `Stop(ctx)` | deadline/cancellation context | `error` | Marks the client non-running, flushes, and releases client-owned providers. Final trace, metric, or log upload failures are returned. Concurrent calls share one terminal result. |
| `IsRunning()` | — | `bool` | Whether the client accepts telemetry. |
| `Health()` | — | `HealthStatus` | State, recent errors, uptime, and per-signal counters. |
| `Stats()` | — | `ClientStats` | Processed/dropped/export-failure counters and timestamps. |

The first `Stop` caller owns the transport shutdown, bounded by the earlier of
its context deadline and `ShutdownTimeout`. Other callers wait for that
operation and receive the identical completed error or `nil`. If a waiter's
context ends first, only that wait returns `ctx.Err()`; the owner continues the
shared shutdown. Calls made after completion return the cached terminal result.
`Start` waits for an in-flight stop before beginning a fresh lifecycle, at
which point the next `Stop` creates a new operation.

For signal-driven or fatal shutdown, catch `SIGTERM` or `os.Interrupt`, call
`Stop` with a bounded context, and inspect its error before exiting. Deferred
calls do not run after `os.Exit`. `SIGKILL` is not catchable and therefore has
no final-flush guarantee; configure the process supervisor's termination grace
period to cover the shutdown deadline.

Keep one client per service. Pass request contexts through all instrumentation so trace and person
correlation remain intact.

## Core `Client` methods

| Method | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `Tracer()` | — | OTel `trace.Tracer` | Underlying tracer for advanced instrumentation. |
| `Meter()` | — | OTel `metric.Meter` | Underlying meter for advanced instrumentation. |
| `Logger()` | — | `*slog.Logger` | Structured logger backed by the Anectico log provider. Use context-aware methods for request work. |
| `StartSpan(ctx, name, opts...)` | context; name; OTel options | `(context.Context, trace.Span)` | Starts a span and returns the child context. Caller must end the span. |
| `RecordMetric(name, value, labels)` | name; float; string map | — | Records one gauge value and caches the instrument by name. It has no context parameter. |
| `LogEvent(level, message, attrs...)` | `slog.Level`; message; attributes | — | Convenience log using a background context. Use `Logger().LogAttrs(ctx, ...)` for correlation. |
| `RecordLLMCall(ctx, opts)` | context; `LLMCallOptions` | — | Records one completed model call as a `gen_ai` span and directly attaches the resolved `anectico.distinct_id`, including with a caller-supplied tracer provider. |
| `RecordToolCall(ctx, name, opts)` | context; tool name/options | — | Records one completed tool execution. |
| `StartAgentRun(ctx, agent, opts)` | context; agent name/options | `(context.Context, AgentRun)` | Starts an agent span and returns its child context plus a safe handle. Call `run.End(status, reasonCode)`; the first valid terminal outcome wins. |
| `WrapHTTPClient(client)` | `*http.Client` | `*http.Client` | Returns a client that propagates trace and Anectico identity context. Its generated transport spans are Issue-suppressed; restrict its destinations. |
| `WrapHTTPTransport(base)` | `http.RoundTripper` | `http.RoundTripper` | Wraps a transport for outbound propagation/instrumentation and Issue-suppresses its generated client spans. |
| `GRPCDialOptions()` | — | `[]grpc.DialOption` | Installs the client stats handler for gRPC tracing and propagation. |

`LLMCallOptions.Model` is required. Other fields are `ResponseModel`, `Provider`, `Operation`, token
counts, `CostUSD`, `FinishReason`, `IsError`, `StartTime`, and `EndTime`. `Messages` and `Output` are
opt-in content. `ToolCallOptions` provides `Type`, `CallID`, `ConversationID`, `AgentName`, `IsError`,
and opt-in `Arguments`/`Result`. `AgentRunOptions` provides `AgentID`, `AgentVersion`, and
`ConversationID`. Set `AgentVersion` to the release label you deploy; it is optional and is emitted
as the standard `gen_ai.agent.version` span attribute.
Agent-run status is `completed`, `failed`, `timed_out`, `cancelled`, or `max_steps`. The optional
reason is normalized to a lowercase code matching `[a-z][a-z0-9_]{0,63}`; free text is rejected.
Calling `run.Span().End()` directly bypasses this contract and produces only the legacy inferred
status, so use `run.End(...)` for normal completion.

### Context assembly events

`AgentRun` exposes `RecordContextAssembly(modelCtx, value)`,
`RecordContextCompaction(modelCtx, value)`, and `RecordContextCache(modelCtx, value)`. Go requires
the explicit model context because OpenTelemetry Go has no ambient current-span API. The context
must contain a recording model span in the same trace with `gen_ai.operation.name` equal to
`chat`, `text_completion`, `generate_content`, `embeddings`, or `fetch_response`; the SDK refuses
the run span, a tool span, an ended span, and an absent span.

```go
runCtx, run := client.StartAgentRun(ctx, "support-planner", anectico.AgentRunOptions{})
modelCtx, modelSpan := client.Tracer().Start(runCtx, "chat gpt-4o",
	trace.WithSpanKind(trace.SpanKindClient),
	trace.WithAttributes(attribute.String("gen_ai.operation.name", "chat")),
)
err := run.RecordContextAssembly(modelCtx, anectico.ContextAssembly{
	BudgetTokens: 8192, ReservedOutputTokens: 1024, AssembledTokens: 6144,
	Overflow: "none", AssemblySHA256: assemblySHA256,
	Sources: []anectico.ContextSource{{
		Kind: "memory", ID: "memory:item-7", Sensitivity: "confidential",
		Tokens: 512, Position: 3, Visibility: "included",
	}},
})
modelSpan.End()
_ = run.End(anectico.AgentRunCompleted, "completed")
```

All values are validated against the [context event bounds](/docs/reference/agent-attributes#context-events)
before the event is attached, so an error records nothing. Compaction ratio is not a producer
field; the server derives it from before/after tokens. Provider wrappers add cache hit/miss events
automatically when OpenAI or Anthropic reports cache fields. An absent provider field produces no
event; a reported zero produces a miss.

Package-level `WrapHTTPClient`, `WrapHTTPTransport`, `GRPCDialOptions`, and
`GRPCClientStatsHandler` provide the same integration helpers when a `Client` reference is not
available.

## Errors, messages, users, and breadcrumbs

Breadcrumbs snapshot nested JSON data when added. If optional data cannot be serialized, the
breadcrumb is retained without that data so error reporting can still include the trail.

| Method | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `CaptureError(ctx, err, opts...)` | context; error; `ErrorOption`s | `string` | Captures an error and returns its generated ID; returns empty when capture is unavailable/sampled out. |
| `CaptureMessage(ctx, message, level, opts...)` | context; text; `ErrorLevel`; options | `string` | Captures a diagnostic message. |
| `AddBreadcrumb(category, message, opts...)` | category/message; breadcrumb options | — | Buffers trail context for the next captured error. |
| `SetUser(user)` | `*User` | — | Sets process-global error user context. |
| `GetUser(ctx)` | request context | `*User` | Returns context-local user first, then global user. |
| `ClearUser()` | — | — | Clears global error user context. |

`User` contains `ID`, `Email`, `Username`, `IPAddress`, `Segment`, and `Data`. Use
`ContextWithUser(ctx, user)` for concurrent request-local error context.

| Error option | Purpose |
| --- | --- |
| `WithLevel` | Override `debug`, `info`, `warning`, `error`, or `fatal`. |
| `WithTag` | Add one indexed tag. |
| `WithTags` | Add multiple indexed tags. |
| `WithExtra(key, value)` | Add one unindexed context value. |
| `WithErrorExtra(map)` | Add several unindexed context values in one option. |
| `WithUser` | Override user for one capture. |
| `WithFingerprint(parts...)` | Override grouping; comma separates components and `{{default}}` includes automatic grouping. |
| `WithStackTrace(pcs)` | Supply program counters rather than capture the current stack. |
| `WithErrorTimestamp(time)` | Supply the event timestamp. |

`WithTag` and `WithTags` keys are encoded as indexed `anectico.tag.*` telemetry attributes
automatically. Capture severity is also indexed as `error.level` for Issue filtering and context.

`WithBreadcrumbLevel(level)` sets severity and `WithBreadcrumbData(map)` attaches structured
breadcrumb context.

## Identity and groups

| API | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `client.Identify(ctx, distinctID, props)` | context; stable ID; person properties | `error` | Sets shared identity and queues the identity event for background delivery with retries. |
| `client.Group(ctx, groupType, groupKey, props)` | context; account type/key; properties | `error` | Records membership and `$groupidentify`. |
| `client.Reset(ctx)` | context | `error` | Logout: rotates anonymous identity and clears groups, global error-user context, and uncaptured breadcrumbs. Already-captured telemetry remains queued with its original attribution. |
| `ContextWithDistinctID(ctx, id)` | context; stable ID | `context.Context` | Sets request-local identity for concurrency-safe server work. |
| `DistinctIDFromContext(ctx)` | context | `(string, bool)` | Reads request-local identity. |
| `AdoptDistinctIDFromBaggage(ctx)` | context | context | Promotes trusted inbound baggage into request scope. |
| `DiscardDistinctIDFromBaggage(ctx)` | context | context | Removes untrusted Anectico identity baggage while preserving other context. |

Never adopt a public client's identity baggage until a trusted gateway has authenticated the request
and recreated that baggage.

## Diagnostic events: `Analytics`

Capture snapshots event properties when enqueueing. Later mutations do not change queued events.
Properties must be JSON-serializable; capture returns an error for invalid events before they enter the queue.
The built-in analytics and feature-flag HTTP clients do not follow redirects: configure the final
API endpoint directly so project credentials stay at that endpoint.

```go
events, err := anectico.NewAnalytics(anectico.AnalyticsConfig{
	Endpoint: "https://api.anectico.com",
	APIKey:   os.Getenv("ANECTICO_API_KEY"),
})
if err != nil {
	return err
}
defer func() { _ = events.Stop(ctx) }()
```

`AnalyticsConfig` fields are `Endpoint`, `APIKey`, `FlushAt` (default 20), `Interval` (zero means 5
seconds; negative disables the timer), and optional `HTTPClient` (default timeout 10 seconds).

`Release` and `AppVersion` are stamped as the reserved `$release`/`$app_version` string
properties on every `Capture`'d event when set; the SDK never auto-detects a server
deployment's version, so set them yourself from your own deploy pipeline (for example, reading
your own `ANECTICO_RELEASE` environment variable in application code — this package never reads
the environment itself). Leave them unset and the properties are omitted entirely, never sent as
`""`. See [Reserved event properties](/docs/investigate/event-schema#reserved-properties).

| API | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `NewAnalytics(config)` | `AnalyticsConfig` | `(*Analytics, error)` | Validates the absolute endpoint and API key, then starts a background flusher using a background lifecycle context. `AnalyticsConfig` also takes an optional `Logger` and an `OnDeliveryError` handler. |
| `NewAnalyticsWithContext(ctx, config)` | lifecycle context/config | `(*Analytics, error)` | Validates configuration and stops the background flusher when context is canceled; still call `Stop` to flush. |
| `Capture(ctx, event, props, opts...)` | context; name; properties; capture options | `error` | Queues an event using the call override, request context/baggage, then shared identity. |
| `Identify(ctx, distinctID, props, opts...)` | context; ID; properties; options | `error` | Queues an identity merge without changing process-global identity; safe for multi-person server batches. |
| `Group(ctx, type, key, props, opts...)` | context; group; properties; options | `error` | Queues membership for the resolved person; changes shared groups only for the shared person. |
| `Flush(ctx)` | deadline context | `error` | Sends queued events in chunks. Returns `nil` only when every batch it sent was accepted; an empty queue is `nil`. Returns `ErrAnalyticsDropped` for explicit refusals and `ErrAnalyticsRetryPending` for uncertain/retryable items; a mixed ledger or separate chunks in one flush can match both. |
| `Stats()` | — | `AnalyticsStats` | `Recorded`, `Delivered`, `Dropped`, `Queued`. `Delivered` counts queue-acknowledged attempts; `Dropped` counts explicit refusals/local discards; `Queued` includes uncertain items retained for retry. |
| `Reset(ctx)` | context | `error` | Attempts to flush, then rotates shared anonymous identity even on delivery failure; retained events keep their original attribution. |
| `Stop(ctx)` | deadline context | `error` | Stops the flusher and sends the remaining queue, returning what that final flush returned. Capture after stop returns `ErrAnalyticsClosed`. |
| `Disable()` | — | — | Immediately closes analytics collection and discards pending work without a final flush; active delivery settles separately. |

`Flush` validates the complete version 1 [capture acknowledgement](/docs/reference/rest-api#capture-acknowledgements).
Use both `errors.Is(err, ErrAnalyticsDropped)` and `errors.Is(err, ErrAnalyticsRetryPending)`:
a mixed ledger can contain refused items and uncertain siblings, and a later chunk can fail after an earlier chunk was refused. Both cases preserve the two error classifications. Check `Stats()` for their counts.
Queued items are never resent. Uncertain items retain their original message ID, timestamp, identity
and payload and wait at least one second (or the bounded server `Retry-After`) before retry.
Malformed/unrecognized responses remain uncertain, including HTTP 2xx and unrecognized 4xx bodies.

`Stop(ctx)` performs a final flush. For collection withdrawal, call `Disable()` instead:
collection closes immediately and pending events are discarded with `collection_disabled`.
Further Capture/Identify/Group calls return `ErrAnalyticsClosed`. Disable is nonblocking and
safe in a delivery callback; call `Flush(ctx)` outside callbacks to wait for an active request
to settle, then inspect Stats. A chunk already admitted to delivery may still reach the server;
its validated acceptance/refusal counts remain, but uncertain positions and later chunks are
never retried. A flush that discards work matches `ErrAnalyticsDropped`, without a pending-retry
classification for those positions. After settlement, Queued is zero. Repeated Disable is safe;
new consent requires a new Analytics instance. This does not erase stored events or disable
separate telemetry clients. Gate collection before initialization where your application requires it.

Explicit refusals are reported through `OnDeliveryError`, `Stats().Dropped` and a `WARN` log.
The callback runs once for a chunk's refused portion and excludes its uncertain siblings.
`DeliveryError.Reason` includes `invalid_event`, `quota_exceeded`, `mixed_rejection`,
request-failure reasons such as `unauthorized` and `bad_request`, and local `queue_overflow`,
`not_serializable` or `collection_disabled`. Fix the input, credentials or quota condition before resubmitting a refused
event. A callback panic is recovered. `Delivered` proves a queue acknowledgement, not storage
visibility, a unique stored occurrence or a completed identity mutation.

```go
events, err := anectico.NewAnalytics(anectico.AnalyticsConfig{
    Endpoint: "https://api.anectico.com",
    APIKey:   os.Getenv("ANECTICO_API_KEY"),
    OnDeliveryError: func(e anectico.DeliveryError) {
        myAlerting.Warnf("anectico dropped %d events: %d %s", e.Dropped, e.Status, e.Reason)
    },
})
```

Capture inherits shared `$groups` only when its resolved person matches the shared identity.
Explicit `$groups` in event properties take precedence. For concurrent requests, pass request-local
identity and event-local groups. `Identify` sends no anonymous alias unless `WithAnonDistinctID`
is supplied, so independent server-side imports do not merge through a shared anonymous ID.

A partial ledger updates `Delivered` only for queued items and `Dropped` only for explicit
refusals. Unknown items remain in `Queued`. An HTTP 200 can contain all three outcomes.

Analytics and flag endpoints must be absolute HTTP(S) base URLs without credentials, query strings,
or fragments. Remote flags validate before sending; local flags validate during construction.

Per-call options are `WithDistinctID`, `WithAnonDistinctID`, and `WithSessionID`.
Use `WithAnonDistinctID` when each server-side merge has its own anonymous alias. For a stateful
single-user/client application that should switch the shared identity used by later signals, call
`client.Identify` instead.

## Feature flags: `Flags`

Bootstrap data and returned payload containers are copied. Exposure deduplication distinguishes
identity, flag name, and the response's type and value. Remote decision responses must contain one
JSON document of at most 16 MiB, with boolean or string flag values. Invalid responses preserve the
last valid cache; overlapping reloads allow only the latest invocation to replace it.

`FlagsConfig` fields are `Endpoint`, `APIKey`, optional `HTTPClient`, optional `Bootstrap`, and an
optional `Capture(ctx, event, props, distinctID)` callback for exposures. The key needs `flags:read`;
the exposure callback usually calls `Analytics.Capture` and therefore needs `analytics:write`.

| Method | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `NewFlags(config)` | `FlagsConfig` | `*Flags` | Builds a concurrency-safe in-memory decision client. |
| `Reload(ctx, distinctID, personProperties, groups)` | targeting context | `error` | Calls `/api/v1/decide`; nil groups use shared memberships. |
| `GetFeatureFlag(ctx, key, distinctID)` | context; key; ID | `any` | Returns bool/variant/nil and emits one deduplicated exposure. |
| `IsFeatureEnabled(ctx, key, distinctID)` | context; key; ID | `bool` | True for `true` or a non-empty string variant. |
| `GetFeatureFlagPayload(key)` | key | `json.RawMessage` | Returns a copy of the payload or nil. |
| `GetAllFlags()` | — | `map[string]any` | Returns a copy of cached decisions. |
| `HadEvaluationErrors()` | — | `bool` | Whether the last decision used a fallback. |
| `Reset()` | — | — | Clears exposure dedup after identity changes. |
| `NewLocalFlagsClient(config)` | `LocalFlagsConfig{Endpoint, APIKey, ProjectID, HTTPClient?, Capture?, Now?}` | `(*LocalFlagsClient, error)` | Creates one exact-project cache; snapshot reads require `flags:read`, and an Anectico-backed `Capture` requires `analytics:write`. |
| `LocalFlagsClient.Refresh(ctx)` | context | `(LocalRefreshStatus, error)` | Fetches or conditionally revalidates a strict, bounded snapshot while retaining the last-known-good cache on failure. |
| `LocalFlagsClient.Evaluate(ctx, key, distinctID, personProperties)` | context, flag key, exact identity, person properties | `LocalEvaluationResult` | Evaluates only a fresh snapshot and emits a successful exposure through optional `Capture`. |
| `LocalFlagsClient.Reset()` | — | — | Clears local `(identity,key,value)` exposure deduplication; preserves the snapshot. |

`NewLocalFlagsClient(LocalFlagsConfig)` creates the project-bound server-side evaluator;
`ProjectID` must be one exact canonical UUID. `Refresh(ctx)` uses strong conditional validators and
serializes concurrent refreshes. `Evaluate(ctx, key, distinctID, personProperties)` returns a
`LocalEvaluationResult` and fails closed when the snapshot is missing/stale, the identity is empty,
or the rule requires authoritative cohort/group data. `LocalFlagsConfig.Capture` mirrors
`FlagsConfig.Capture`: successful `matched`/`default` decisions emit `$feature_flag_called` once per
identity/key/value, and `Reset()` reopens the dedup set without dropping the snapshot. A
callback wired to `Analytics.Capture` also requires `analytics:write`.

## Configuration options

Explicit service name/version options take precedence over their environment defaults. An
explicitly empty service name is invalid. Signal-specific and authentication headers override
general headers case-insensitively. Integer millisecond environment values that overflow
`time.Duration` fall back to the setting's default.

Options apply in order. `WithConfig(config)` is normally first; later options override its fields.

| Option family | Functions and effect |
| --- | --- |
| Identity | `WithServiceName`, `WithServiceVersion`, `WithEnvironment`, `WithProjectID`. |
| Authentication | `WithAPIKey` selects API-key auth; `WithJWTToken` selects JWT auth. Application integrations should use a project API key. |
| Endpoint/transport | `WithEndpoint`, `WithProtocol("http"\|"grpc")` (default `"http"`; `"grpc"` is opt-in for a self-hosted or tunneled deployment), `WithInsecure`, `WithHeaders`, `WithHeader`. |
| TLS | `WithTLS`, `WithTLSCerts(cert,key,ca)`, `WithTLSCA`, `WithTLSServerName`; `WithInsecureTLS` skips verification and is development-only. |
| Batching | `WithBatchTimeout`, `WithBatchSize`, `WithMaxQueueSize`, `WithExportTimeout`, `WithShutdownTimeout`, `WithRetryConfig`. |
| Signals/sampling | `WithTraceSampleRate`, `WithTraces`, `WithMetrics`, `WithLogs`, `WithAllTelemetry`. |
| Diagnostics | `WithDebug`, `WithLogLevel`, `WithLogOutput`. |
| Resources | `WithResourceAttribute`, `WithResourceAttributes`. |
| Errors | `WithErrorCapture`, `WithErrorSampleRate`, `WithMaxStackTraceFrames`, `WithAttachStackTrace`, `WithErrorEnvironment`, `WithErrorRelease`. |
| Providers | `WithTracerProvider` uses a caller-owned OTel provider and enables traces; the caller shuts it down after the Anectico client. |
| Presets | `WithProductionDefaults`, `WithDevelopmentDefaults`, `WithTestingDefaults`, `WithKubernetesDefaults`, `WithDockerDefaults`. Apply a preset before options that should override it. |

Defaults include the HTTP transport, a 10% trace sample rate, 100% captured errors, batch size 512,
queue size 2048, 5-second batch/shutdown timeouts, 30-second exports, and three retry attempts.
`DefaultConfig()` reads the equivalent `ANECTICO_*` and `OTEL_*` environment variables (including
`OTEL_EXPORTER_OTLP_PROTOCOL`, which also accepts the OTel-standard `http/protobuf` spelling as an
alias for `http`); `Config.Validate()` checks required values and bounds.

The selected authentication mode must have its matching credential: API-key mode
requires an API key and JWT mode requires a JWT. Sampling rates reject NaN and
infinity as well as values outside 0–1.

Managed Go providers attach the standard OpenTelemetry SDK resource identity to every trace,
metric, and log: `telemetry.sdk.language=go`, `telemetry.sdk.name=opentelemetry`, and the active
OpenTelemetry Go SDK version in `telemetry.sdk.version`. These reserved attributes describe the
emitting SDK and cannot be overridden with `WithResourceAttribute(s)`. Anectico does not implicitly
enable host or process resource detectors; add any reviewed infrastructure attributes explicitly.

The managed tracer provider uses parent-based sampling: local and remote child spans preserve the
parent's sampled or unsampled W3C decision, while `WithTraceSampleRate` applies only to new root
traces. `error.capture` and `message.capture` spans are always retained so explicit error/message
capture is not lost when ordinary traces are sampled out. `WithTracerProvider` remains fully
caller-owned; Anectico neither replaces its sampler nor applies these managed-provider rules.

## Authentication and error helpers

`ValidateAPIKey`, `IsAPIKeyFormat`, and `MaskAPIKey` support configuration UIs. `IsAuthError`,
`IsNetworkError`, `IsRetryableError`, `GetErrorSuggestion`, and `WrapGRPCError`
support custom transports. Prefer returning these errors rather than matching their strings.

## Advanced configuration and utility API

| API | Parameters | Returns/behavior |
| --- | --- | --- |
| `DefaultConfig()` | — | `*Config` populated from supported `ANECTICO_*`/`OTEL_*` variables and safe defaults. |
| `config.Validate()` | — | `error` for missing credentials/identity or inconsistent protocol, sampling, queues, timeouts, and TLS. |
| `config.GetEndpointForSignal(signal)` | `traces`, `metrics`, or `logs` | Signal-specific OTLP endpoint. |
| `config.GetHeadersForSignal(signal)` | signal name | Copy of headers including active authentication. |
| `config.Logger()` | — | SDK diagnostic `*slog.Logger`. |
| `NewTransport(config)` | validated `*Config` | `(Transport, error)` for custom lifecycle ownership; most applications should use `Client`. |
| `TLSConfig.Validate()` | — | Rejects incomplete certificate pairs and unsafe/inconsistent TLS bounds. |
| `TLSConfig.GetStandardTLSConfig()` | — | `(*tls.Config, error)` for HTTP transports. |
| `TLSConfig.GetTLSCredentials()` | — | `(credentials.TransportCredentials, error)` for gRPC. |
| `ContextWithUser(ctx, user)` | context; `*User` | Request-local error user. |
| `UserFromContext(ctx)` | context | Request-local `*User` or nil. |
| `user.ToOTelAttributes()` | — | OpenTelemetry `enduser.*` and `user.data.*` attributes. |
| `CaptureStackTrace(skip)` | number of caller frames to skip | Structured `[]StackFrame` for a custom error integration. |
| `GetPoolStats()` / `ResetPoolStats()` | — | SDK allocation-pool counters, and a test/debug reset. |

`Config` exposes the same fields represented by the functional options: service identity,
credentials, endpoint/protocol/headers/TLS, batch and retry values, signal switches, sampling,
logging, resources, and error settings. `TLSConfig` additionally accepts `Enabled`,
`InsecureSkipVerify`, certificate/key/CA files, `ServerName`, TLS version bounds, and cipher suites.
The package's typed sentinel errors (`ErrUnauthorized`, `ErrForbidden`, `ErrInvalidAPIKey`,
`ErrExpiredToken`, `ErrRateLimited`, `ErrInvalidCredentials`, `ErrConnectionFailed`, `ErrTimeout`,
and `ErrServiceUnavailable`) are compatible with `errors.Is`.

## Framework and model-provider packages

| Package/API | Parameters | Returns | Behavior |
| --- | --- | --- | --- |
| `instrumentation/openai.WrapClient(anecticoClient, client, opts...)` | Anectico client; official OpenAI client; options | instrumented client | Wraps `Chat.Completions.New` and `NewStreaming` calls while preserving provider responses, chunks, errors, and stream iteration. |
| `instrumentation/openai.WithCaptureContent()` | — | wrapper option | Opts into prompt/completion content; off by default. |
| `instrumentation/anthropic.WrapClient(anecticoClient, client, opts...)` | Anectico client; official Anthropic client; options | instrumented client | Wraps `Messages.New` and `NewStreaming` calls while preserving provider results, events, errors, and stream iteration. |
| `instrumentation/anthropic.WithCaptureContent()` | — | wrapper option | Opts into prompt/completion content; off by default. |
| `instrumentation/gin.Middleware(client)` / `MiddlewareWithOptions(client, opts)` | Anectico client; optional `Options` | Gin handler | Creates inbound request spans and request-scoped propagation, captures `c.Errors`, and captures handler panics recovered by Gin as one canonical Issue occurrence. |
| `instrumentation/echo.Middleware(client)` / `MiddlewareWithOptions(client, opts)` | Anectico client; optional `Options` | Echo middleware | Creates inbound request spans and request-scoped propagation. `DefaultSkipper` is the exported standard skip predicate. |
| `instrumentation/fiber.Middleware(client)` / `MiddlewareWithOptions(client, opts)` | Anectico client; optional `Options` | Fiber handler | Creates inbound request spans and request-scoped propagation. `DefaultNext` skips standard health paths; `GetSpan(ctx)` reads the active request span. |
| `instrumentation/grpc.UnaryServerInterceptor(client)` / `UnaryServerInterceptorWithOptions(client, opts)` | client; optional `ServerOptions` | unary server interceptor | Extracts trace context, creates the server span, and optionally adopts trusted identity. |
| `instrumentation/grpc.StreamServerInterceptor(client)` / `StreamServerInterceptorWithOptions(client, opts)` | client; optional `ServerOptions` | stream server interceptor | Instruments stream lifetime and propagation. |
| `instrumentation/grpc.UnaryClientInterceptor(client)` / `StreamClientInterceptor(client)` | client | client interceptor | Copies existing metadata, injects W3C trace/identity context, and traces RPCs. Stream completion is idempotent; transport errors remain spans rather than duplicate Issues. |
| `instrumentation/grpc.CombinedServerInterceptors(client)` | client | `[]grpc.ServerOption` | Installs both server interceptors. |
| `instrumentation/grpc.CombinedClientInterceptors(client)` | client | `[]grpc.DialOption` | Installs both client interceptors. |

Both `NewStreaming` wrappers keep the official `Next`/`Current`/`Err`/`Close` flow and record one
model call when the stream is exhausted, fails, or is abandoned. Always close the stream, normally
with `defer stream.Close()`.

Closing before the stream finished, or cancelling its context, is not an error: the call happened and
was billed, so the span keeps its normal status and carries `anectico.gen_ai.stream.abandoned = true`
instead. That keeps deliberate early exits out of your error rate while remaining distinguishable;
the token counts on such a span are the provider's last reported values and are partial by
construction. Provider stream failures, a `Close` error, and an expiring deadline record one
error-status model call.

Neither wrapper changes your request. `stream_options.include_usage` is never set for you — doing so
appends a terminal empty-`Choices` chunk that panics the usual `chunk.Choices[0]` loop, and is
rejected outright by some OpenAI-compatible gateways — so set `StreamOptions.IncludeUsage` yourself
when you want streaming token counts from OpenAI. Anthropic needs no such parameter: its usage
arrives on `message_start` and `message_delta`. A count the provider never reported is recorded as
absent, never as zero. Content capture can record sensitive text and remains off unless
`WithCaptureContent` is supplied.

Gin `Options` supports `TrustIncomingIdentity`, `SkipPaths`, request/response body capture,
`MaxBodySize`, custom attributes, span naming, filtering, captured-header allowlists, and sensitive
header redaction. Gin Recovery can be registered before or after Anectico; the configured recovery still
controls the response. Registering Recovery first (the `gin.Default()` order) retains the original
panic value in Anectico. When Recovery is inside Anectico, Gin has already discarded that value, so Anectico
records a generic panic message with the handler stack. In both orders, the failed server span stays
visible and correlated in Traces while the stacked `error.capture` child is the only Issue
occurrence. Echo provides the same controls through `Skipper` (rather than `SkipPaths` and a filter).
Fiber supports `Next`, custom attributes, span naming, and header controls. Every HTTP package
exports `WithSkipHealthCheck()` and `WithCaptureAllHeaders()` presets. Body or header capture can
collect secrets; keep it disabled unless a reviewed debugging need requires it. gRPC `ServerOptions`
contains `TrustIncomingIdentity` and an explicit `CaptureMetadata` allowlist.

Gin, Echo, and Fiber strip URL userinfo, query strings, and fragments from recorded
HTTP URLs. Each HTTP attribute is bounded independently; a truncated value receives
a `.truncated=true` sibling marker so one oversized request does not discard a batch.

Package-level and client-bound HTTP client/transport wrappers mark their
generated outbound spans with `anectico.issue.suppressed=true`. Transport failures
and cancellations keep their normal span status, trace/baggage propagation, and
HTTP metrics, so they remain diagnosable in Traces without producing stackless
Issues. To turn an actionable dependency failure into an Issue, translate it
into an explicit typed application/domain error after retries are exhausted and
call `CaptureError` once at that boundary.

The custom gRPC client interceptors inject the newly started client span as
`traceparent`/`tracestate` and propagate request identity in W3C `baggage`.
Generated client calls must receive the request context that carries the active
span and `anectico.ContextWithDistinctID` value. A client stream span ends on EOF,
the single response of a client-streaming RPC, a failed stream operation, or
caller cancellation. Successful `CloseSend` does not end the response side.
Concurrent or repeated terminal signals end the span once while returning the
original gRPC status unchanged. Client transport statuses do not create Issues.
The server interceptor captures one occurrence for unexpected server failures
(`Unknown`, `ResourceExhausted`, `Unimplemented`, `Internal`, `Unavailable`, or
`DataLoss`). Cancellation, deadlines, and expected caller/control statuses
remain visible as error-status spans without becoming Issues. Non-canonical
transport spans carry `anectico.issue.suppressed=true`; when server `CaptureError`
succeeds, its transport parent also carries the returned `error.id`. This
suppression remains exact if exporter batches separate or reorder the parent and
canonical `error.capture` child. If server capture is disabled, sampled out,
fails, or returns no ID, the actionable server transport span is left eligible
as the fallback Issue. For an external dependency, explicitly capture one typed
domain error after retries are exhausted when the failure should become an
Issue.

- [Install and use Go](/docs/instrument/go)
- [Identify customers safely](/docs/instrument/identity)
- [Capture errors and releases](/docs/instrument/errors)
