loopdetect

package
v0.99.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: GPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package loopdetect detects repetitive tool-call patterns in an agent run.

Detectors cover generic repeats, no-progress streaks, ping-pong alternation, a global circuit breaker, and a post-compaction identical-triple guard.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ArgsHash

func ArgsHash(toolName string, args map[string]any) string

ArgsHash returns a stable fingerprint for tool name + args.

func ResultHash

func ResultHash(toolName string, result msg.ToolResultMessage) string

ResultHash returns a stable fingerprint for a completed tool result.

Types

type Config

type Config struct {
	// Enabled master-switches all detectors including post-compaction.
	Enabled bool
	// Window is the sliding history size.
	Window int
	// GenericWarn is the same tool+args count that emits a warning.
	GenericWarn int
	// GenericCritical is the same tool+args count that blocks (recoverable).
	GenericCritical int
	// NoProgressCritical blocks when identical tool+args+result streak reaches this count.
	NoProgressCritical int
	// PingPongWarn warns on alternating A/B no-progress streaks.
	PingPongWarn int
	// PingPongCritical blocks on alternating A/B no-progress streaks.
	PingPongCritical int
	// GlobalCircuitBreaker hard-stops on any no-progress streak of this length.
	GlobalCircuitBreaker int
	// PostCompactionIdentical hard-stops when the same triple repeats this many times while armed.
	PostCompactionIdentical int
	// PostCompactionWatch limits completed tool calls watched after arming.
	PostCompactionWatch int
}

Config holds thresholds for tool-loop detectors.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns conservative defaults from the loop-detection plan.

type Decision

type Decision struct {
	// Level is warn, critical, or empty when not stuck.
	Level Level
	// Detector names which pattern fired.
	Detector DetectorName
	// Count is the effective streak including the pending call when applicable.
	Count int
	// Message is a human-readable block/warn reason for logs and tool errors.
	Message string
	// Terminate requests a hard stop of the agent loop after a blocked result.
	Terminate bool
	// ArgsHash is the stable fingerprint for the pending tool+args.
	ArgsHash string
}

Decision is the outcome of Check before a tool executes.

func (Decision) Stuck

func (d Decision) Stuck() bool

Stuck reports whether any detector fired.

type Detector

type Detector struct {
	// contains filtered or unexported fields
}

Detector tracks run-scoped tool-call history for loop patterns.

func NewDetector

func NewDetector(cfg Config) *Detector

NewDetector creates a run-scoped loop detector.

func (*Detector) ArmPostCompaction

func (d *Detector) ArmPostCompaction()

ArmPostCompaction arms the short post-compaction guard window.

func (*Detector) Check

func (d *Detector) Check(toolName string, args map[string]any) Decision

Check evaluates pending tool+args against history before execution.

func (*Detector) Config

func (d *Detector) Config() Config

Config returns the resolved detector configuration.

func (*Detector) ObserveResult

func (d *Detector) ObserveResult(toolName string, args map[string]any, result msg.ToolResultMessage)

ObserveResult records a completed tool invocation (not blocked calls).

func (*Detector) Reset

func (d *Detector) Reset()

Reset clears history and post-compaction arm state.

func (*Detector) ResetFingerprint

func (d *Detector) ResetFingerprint(argsHash string)

ResetFingerprint removes history entries for one args hash (after user allow).

type DetectorName

type DetectorName string

DetectorName identifies which pattern fired.

const (
	// DetectorGenericRepeat is repeated identical tool+args.
	DetectorGenericRepeat DetectorName = "generic_repeat"
	// DetectorNoProgress is repeated identical tool+args+result.
	DetectorNoProgress DetectorName = "no_progress"
	// DetectorPingPong is alternating A/B calls without progress.
	DetectorPingPong DetectorName = "ping_pong"
	// DetectorGlobalCircuitBreaker is the hard no-progress cap.
	DetectorGlobalCircuitBreaker DetectorName = "global_circuit_breaker"
	// DetectorPostCompaction is the post-compaction identical-triple guard.
	DetectorPostCompaction DetectorName = "post_compaction"
)

type Level

type Level string

Level is the severity of a loop-detection hit.

const (
	// LevelNone means no loop detected.
	LevelNone Level = ""
	// LevelWarn is observational only.
	LevelWarn Level = "warn"
	// LevelCritical blocks or terminates depending on Detector.
	LevelCritical Level = "critical"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL