Documentation
¶
Overview ¶
Package reflect — Reflexion-class self-correction (paper #51 AlphaGRPO / Shinn 2023 Reflexion). Pairs with §4.14 self-aware error recovery: when a tool call fails, generate a STRUCTURED verbal reflection ("you tried X, it failed because Y, try Z") and inject it as a system message before the next model call.
Design split:
- IsFailureOutput / classify the result. Errors are obvious; the harder shape is "tool reported success but the body contains 'FAIL', 'error:', exit-code 1, etc." — test runners and linters do this constantly.
- Reflector interface: Reflect(Failure) -> Reflection. Two impls today:
- HeuristicReflector: deterministic, no LLM, instant. Catches the obvious shapes (build error, test failure, permission denied, not-found) by pattern. Cheap rope.
- LLM-backed impl is deliberately not in this package yet — keeping the wiring above the LLM dep so callers can pick. The interface is the contract.
- FormatSystemNote: prose the agent reads. Stays terse so the model doesn't drown its own reasoning in the reflection.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FormatSystemNote ¶
func FormatSystemNote(toolName string, r Reflection) string
FormatSystemNote produces the prose injected as a system message before the next model turn. Kept short so it doesn't dominate the context — the model still has the raw tool result above; this is the structured cue, not a replacement.
func IsFailureOutput ¶
IsFailureOutput returns true when the tool's output body — even without a Go-level error — looks like a failure the agent should reflect on. Conservative: we err on the side of NOT reflecting since each reflection injects a system message and costs model attention.
Types ¶
type Failure ¶
type Failure struct {
ToolName string
Input string // raw JSON argument, may be empty
Output string // stringified tool output
Error string // Go-level error, empty if none
}
Failure is the input to the reflector. Output / Error may both be populated (a Go error AND a failure-shaped body); reflectors should read both.
type FailureMode ¶
type FailureMode string
FailureMode is a coarse bucket the reflector tags the failure with. Used both for grouping in the failhypo store and for the HeuristicReflector to pick a retry plan.
const ( FailureBuildError FailureMode = "build_error" FailureTestFailure FailureMode = "test_failure" FailureLintError FailureMode = "lint_error" FailurePermissionDenied FailureMode = "permission_denied" FailureNotFound FailureMode = "not_found" FailureTimeout FailureMode = "timeout" FailureSyntax FailureMode = "syntax_error" FailureGeneric FailureMode = "generic" )
type HeuristicReflector ¶
type HeuristicReflector struct{}
HeuristicReflector is the no-LLM baseline. It classifies the failure mode and picks a canned root-cause + hypothesis from a small table. The point: even without spending a model call, the agent sees a STRUCTURED reflection on the next turn instead of just the raw error — that alone moves it off the "retry the same thing" attractor.
func (HeuristicReflector) Reflect ¶
func (HeuristicReflector) Reflect(f Failure) Reflection
type Reflection ¶
type Reflection struct {
Mode FailureMode
RootCause string
Hypothesis string
// Confidence is the reflector's own estimate (0..1). Below 0.5
// the caller may choose to surface the failure to the user
// instead of retrying silently.
Confidence float64
}
Reflection is what the reflector produces. RootCause is the one-sentence diagnosis; Hypothesis is what to try next; the agent sees both in the injected system note.
type Reflector ¶
type Reflector interface {
Reflect(f Failure) Reflection
}
Reflector is the minimal surface the agent loop calls after a failed tool. Keep it tiny — single method, no error path (failure-mode reflection should be best-effort).