Documentation
¶
Overview ¶
Package agent adapts Agent Framework events to the official OpenTelemetry tracing and metrics APIs. The Agent Kernel does not import OpenTelemetry.
Each Process activation is an in-process invoke_agent span named after its Deployment, with matching gen_ai.invoke_agent.duration. A restored activation starts a new observation interval; the process activation attribute separates it from an initial invocation. Process IDs remain runtime attributes, not stable gen_ai.agent.id values. Model selection stays at the model boundary. Durable Process, Step, and Effect spans are keyed by the active incarnation, so overlapping old and restored instances never share span ownership.
Register an Observer as an Engine EventListener and wrap each Deployment's Dispatcher with Observer.WrapDispatcher to make downstream model and tool spans children of their Effect span. Close the Engine before the Observer. Wrap the selected TreeDurability with Observer.WrapTreeDurability to observe protocol acknowledgment duration, proposed snapshot bytes, and conflict or unresolved outcomes. This integration does not select storage, read heads, infer rollback, or measure the age of stored state.
Failed invocations use the declared Failure code as error.type. Other error terminations use agent.<termination cause>; Step and Effect failures use agent.step.failed and agent.effect.<settlement status>. Kernel fact messages contain these stable classifications, never application failure diagnostics. RuntimeStopped ends the affected instance's spans and activation duration without recording a logical Process exit or terminal usage measurements.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var (
ErrInvalidObserverConfig = errors.New("agent otel: invalid observer configuration")
)
Functions ¶
This section is empty.
Types ¶
type Observer ¶
type Observer struct {
// contains filtered or unexported fields
}
Observer projects immutable Framework Event facts into OpenTelemetry spans and metrics. It implements agent.EventListener and is safe for concurrent calls. Observer never receives Process behavior or application state. Observer values must be constructed with NewObserver and must not be copied after first use.
func NewObserver ¶
func NewObserver(config ObserverConfig) (*Observer, error)
NewObserver validates providers and creates the observation instruments. Instrument construction failures wrap ErrInvalidObserverConfig. Export failures remain with the configured providers and never change Agent state.
func (*Observer) Close ¶
func (o *Observer) Close()
Close prevents new observation, waits for callbacks already in flight, and then ends any incomplete spans. It is safe to call concurrently and is idempotent; normally Engine.Close leaves no incomplete Process spans.
func (*Observer) WrapDispatcher ¶ added in v0.15.0
func (o *Observer) WrapDispatcher(next agent.Dispatcher) (agent.Dispatcher, error)
WrapDispatcher propagates the observed Effect span into downstream calls. Register this same Observer as an Engine EventListener: the Engine publishes EffectStarted before dispatch and EffectFinished after dispatch returns. Without an active observed Effect, the caller's context passes through. The returned decorator preserves replay policy, settlement, and Delta delivery.
func (*Observer) WrapTreeDurability ¶ added in v0.16.0
func (o *Observer) WrapTreeDurability(next agent.TreeDurability) (agent.TreeDurability, error)
WrapTreeDurability observes the existing port so instrumentation cannot select a different commit or fencing path. Metric labels stay bounded to avoid one time series per tree; identities belong only in traces. Adapter diagnostics are excluded because they can contain credentials or payloads. An error other than an explicit conflict remains unresolved because a lost response cannot prove whether storage committed.
Example ¶
package main
import (
"context"
"fmt"
agent "github.com/Tangerg/scope/agent"
"github.com/Tangerg/scope/agent/agenttest"
agentotel "github.com/Tangerg/scope/otel/agent"
)
func main() {
observer, err := agentotel.NewObserver(agentotel.ObserverConfig{})
if err != nil {
panic(err)
}
defer observer.Close()
durability, err := observer.WrapTreeDurability(agenttest.NewMemoryTreeDurability())
if err != nil {
panic(err)
}
engine, err := agent.NewEngine(agent.EngineConfig{
TreeDurability: durability,
EventListeners: []agent.EventListener{observer},
})
if err != nil {
panic(err)
}
if err := engine.Close(context.Background()); err != nil {
panic(err)
}
fmt.Println("durability observation configured")
}
Output: durability observation configured
type ObserverConfig ¶
type ObserverConfig struct {
// TracerProvider creates Process, Step, and Effect spans. Nil uses the
// OpenTelemetry global provider.
TracerProvider trace.TracerProvider
// MeterProvider creates Process lifecycle and usage instruments, Step/Effect
// duration histograms, durability duration and snapshot size, and the Delta
// drop counter. Nil uses the OpenTelemetry global provider.
MeterProvider metric.MeterProvider
}
ObserverConfig selects the official OpenTelemetry providers used by Observer. A nil provider uses the corresponding OpenTelemetry global provider.