Skip to main content
Agent SDK for Go emits structured logs throughout the agent lifecycle — config validation, runtime execution, workflow steps, and exporter diagnostics. Logs are separate from Telemetry (run summaries) and Tracing (spans).

Default behavior

Without observability config, the SDK uses a default logger writing to stderr at level error. Set the level with WithLogLevel:
a, err := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithLogLevel("debug"), // debug, info, warn, error
)
No OTLP export unless you configure it.

OTLP log export

When WithObservabilityConfig is set and DisableLogs is false, SDK logs export to your OTLP backend automatically — the default logger is bridged to the same OpenTelemetry LoggerProvider:
a, err := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithObservabilityConfig(&agent.ObservabilityConfig{
        Endpoint: "collector:4317",
        Protocol: agent.OTLPProtocolGRPC,
        Insecure: true,
        // DisableLogs: true, // skip OTLP log export
    }),
    agent.WithLogLevel("info"),
)
defer a.Close() // flushes buffered log records
No separate WithLogger call is needed for OTLP — the SDK wires logger.DefaultLoggerWithOtelProvider when logs are enabled. Use the same WithObservabilityConfig and log level on NewAgentWorker for worker-side log export.

Custom logger + OTLP

If you pass WithLogger with a custom logger, OTLP logs from WithObservabilityConfig are not automatically bridged — the SDK warns at build time. Bridge manually:
import (
    "github.com/agenticenv/agent-sdk-go/pkg/logger"
    "github.com/agenticenv/agent-sdk-go/pkg/observability"
)

logs, _ := observability.NewLogs(
    observability.WithName("my-service"),
    observability.WithEndpoint("collector:4317"),
    observability.WithInsecure(true),
)

a, err := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithLogs(logs),
    agent.WithLogger(logger.DefaultLoggerWithOtelProvider("info", logs.Provider())),
)
When WithObservabilityConfig enables logs, any standalone WithLogs value is replaced by the OTLP client built from config.

Bring your own logs exporter

Use WithLogs with observability.NewLogs when not using WithObservabilityConfig:
logs, err := observability.NewLogs(
    observability.WithName("my-service"),
    observability.WithEndpoint("collector:4317"),
    observability.WithProtocol(observability.ProtocolHTTP),
    observability.WithInsecure(true),
)

a, err := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithLogs(logs),
    agent.WithLogLevel("info"),
)

Disable logging

agent.WithLogger(agent.NoopLogger())
Discards all SDK log output — useful in tests or when an external wrapper captures everything.

Log levels

LevelTypical content
errorDefault — failures and misconfiguration
warnDeprecated paths, config overrides, fingerprint warnings
infoAgent config summary, worker start/stop, run lifecycle
debugPer-iteration detail, hook activity, exporter diagnostics

Shutdown and flush

ProcessFlush behavior
Agent.Close()Shuts down tracer, metrics, and logs exporters
AgentWorker.Stop()Flushes OTLP on standalone worker processes
Embedded local workerFlushes via Agent.Close() only
OTLP log records are batched before export. Allow a brief drain window on shutdown in production — call Agent.Close() or AgentWorker.Stop() before the process exits, not just on signal receipt.

Integrate with your logging pipeline

Write to a file or stdout — override the default logger with a custom writer:
import (
    "os"
    "github.com/agenticenv/agent-sdk-go/pkg/logger"
)

f, _ := os.OpenFile("agent.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
a, err := agent.NewAgent(
    agent.WithLLMClient(llmClient),
    agent.WithLogger(logger.DefaultLoggerWithWriter("info", f)),
)
Forward to an aggregator (Loki, Datadog, Splunk) via the OTLP Collector. Wire OTLP log export from the SDK, then configure the collector to forward to your backend:
# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"

exporters:
  loki:
    endpoint: "http://loki:3100/loki/api/v1/push"
  debug:
    verbosity: basic

service:
  pipelines:
    logs:
      receivers: [otlp]
      exporters: [loki, debug]
Forward to an existing slog pipeline — implement interfaces.Logger wrapping your handler and pass it to WithLogger.

Hooks logging

Hook examples in the repository log hook activity to stderr with a [hooks] prefix. See Hooks and Hooks example. Example: Observability · Logs example.

Example

Observability

OTLP traces, metrics, and logs

Tracing

OTLP traces in the same config block

Metrics

OTLP metrics export

Configuration

WithLogger, WithLogLevel, WithObservabilityConfig

CLI

agentctl log file output