Documentation
¶
Overview ¶
Package steer is stream rules and the watchdog for one session (2.0 W3, #175): Session implements loop.Steering. A session is a chat (across its turns), an agent run, or one MCP chat call.
Index ¶
- Constants
- func BallotQuestions() []decide.Question
- func NewToolGate(mode, workspace string, goal func() string, logf func(string)) tools.AskAdvisor
- func ToolGate(mode string, o decide.Oracle, goal func() string, logf func(string)) tools.AskAdvisor
- type Finding
- type Options
- type Session
- func (s *Session) Ballot(ctx context.Context) (v Verdict, acting bool)
- func (s *Session) Calls(_ int, calls []loop.ToolCall) bool
- func (s *Session) Close()
- func (s *Session) EndStream() bool
- func (s *Session) Observe(ev loop.Event) bool
- func (s *Session) Reminders(b loop.Boundary) []loop.Reminder
- func (s *Session) Request(_ int, interrupt func())
- func (s *Session) SetGoal(goal string)
- func (s *Session) Settle(id string)
- func (s *Session) Steering() loop.Steering
- func (s *Session) Wait()
- type Severity
- type Verdict
Constants ¶
const ( QOnTrack = "on_track" QLooping = "looping" QDrifting = "drifting_from_goal" QPersonaBreak = "persona_break" QUnverified = "claims_unverified_success" QUnsafe = "unsafe_next_action" )
The watchdog ballot's questions (spec §5 W3).
const ( ActAt = 0.70 LogFrom = 0.30 )
The band: a flag at or above ActAt is acted on; one from LogFrom up to ActAt is logged only (spec: 0.30–0.70 is logged, not acted on).
const ( QDestructive = "destructive" QExfiltration = "exfiltration" QBeyondScope = "beyond_requested_scope" )
The tool gate's questions (spec §5 W3).
const DefaultEvery = 3
DefaultEvery is the ballot's cadence, in requests (spec: every 3 turns).
Variables ¶
This section is empty.
Functions ¶
func BallotQuestions ¶
BallotQuestions is the fixed ballot, with heuristic answers where the transcript alone can tell (the default oracle).
func NewToolGate ¶
func NewToolGate(mode, workspace string, goal func() string, logf func(string)) tools.AskAdvisor
NewToolGate is ToolGate on Jev (decide.NewJev, "gate" in the stats), or nil when jev_gate is off: no key is read for a gate that is off. Paths in the pending call are sent relative to workspace, or as <path>.
func ToolGate ¶
ToolGate is jev_gate as a tools.AskAdvisor (spec §5 W3). It asks the oracle (Jev, falling back to the heuristic) about each call the policy allows that is not read-only, plus web_fetch (a read that can carry data out in its URL). "on": any answer at or above ActAt turns the call into an Ask, never the reverse. "shadow": it logs what it would do. goal is read per call (the chat's goal changes per turn). Nil when mode is off.
Types ¶
type Finding ¶
type Finding struct {
ID string
P float64 // the flag, 0..1 (on_track: how far off track)
Severity Severity
Source string // the oracle that answered
}
Finding is one flagged answer.
type Options ¶
type Options struct {
Rules *rules.Set
RulesMode string // config.StreamRulesMode(): off, shadow or on
// RuntimeVerifies: an agent run with verification commands (the
// task-complete-before-verify rule stands down).
RuntimeVerifies bool
// Watchdog is config.WatchdogMode(): off, shadow or on.
Watchdog string
// Oracle answers the ballot; nil is the heuristic.
Oracle decide.Oracle
// Every is the ballot cadence in requests; 0 is DefaultEvery.
Every int
// Goal is what the session is for (the agent goal, the MCP prompt).
// The chat sets it per turn with SetGoal.
Goal string
// FinalRepliesToGate: an agent run, whose completion gate asks its own
// ballot at a final reply; the background ballot skips final replies
// (it runs at the next request's end instead).
FinalRepliesToGate bool
// Context is the run's: cancelling it cancels a background ballot, as
// Close does. nil: context.Background().
Context context.Context
// Logf gets shadow lines, fires and verdicts. nil: none.
Logf func(string)
}
Options configure a Session.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is one session's steering. Safe for concurrent use.
func New ¶
New returns a Session, or nil when there is nothing to steer: stream rules off (or none loaded) and the watchdog off. Use Steering to put it on a Loop, and Close it when the session ends.
func (*Session) Ballot ¶
Ballot asks the ballot now and waits for the answer: the agent's completion gate (spec: "before a completion is accepted"). acting is false when the watchdog is off or in shadow (the verdict is then logged only). The oracle is Guarded, so this waits at most decide.Timeout. Nil-safe.
func (*Session) Close ¶
func (s *Session) Close()
Close ends the session: a background ballot is cancelled and its verdict dropped, no new one starts, and Close returns once it has finished (so nothing logs after the run). Nil-safe.
func (*Session) EndStream ¶
EndStream scans the reply text the matcher's batching held back (loop.StreamEnder).
func (*Session) Reminders ¶
Reminders hands out what is due at b. A run's start also takes appended reminders a final reply left behind, and any boundary but a retry takes interrupt reminders whose interrupt the loop did not honour (the turn had used its re-runs), so no reminder is lost. Batched watchdog nits ride on the first reminder handed out, or go alone at a run's start.
func (*Session) SetGoal ¶
SetGoal sets what the ballot judges progress against (the chat: each turn's prompt). A changed goal drops watchdog reminders and nits not yet handed out, the verdict of a ballot still running, and the turns the watchdog saw (the same call under two prompts is not a loop); the request cadence carries on. Nil-safe.
func (*Session) Settle ¶
Settle says a finding was acted on another way (the completion gate's veto names unverified success): watchdog reminders about it that are pending lose its advice, and ballots in the next steerGap requests do not repeat it. Nil-safe.
type Verdict ¶
type Verdict struct {
Act []Finding // at or above ActAt, most severe first
Logged []Finding // in the band, logged only
}
Verdict is one ballot's outcome.