Documentation
¶
Overview ¶
Package agent stitches the heuristic registry, LLM provider, and read-only tool runner into a single Scan operation.
The flow:
- Run every registered heuristic concurrently → []Finding.
- If zero findings, short-circuit with an empty Recommendation slice (no LLM call needed; nothing to triage).
- Otherwise build the system prompt, an initial user message summarizing the findings, and call Provider.Generate in a loop: - if the model returns tool calls, dispatch each via the Runner, thread the results back as message-history Tool messages, and continue. - if the model returns no tool calls, parse its text as a JSON array of Recommendations and return.
- Cap the loop at Config.MaxToolCalls — the safety rail described in docs/plans/2026-05-02-sentra-design.md → "Safety rails".
The orchestrator never inspects file contents and never executes a recommendation — that's `sentra agent scan --apply`'s job (Phase 11.3). Apply is gated behind interactive confirms so the agent loop stays a pure "advice" surface.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrBudgetExhausted = errors.New("agent: tool-call budget exhausted")
ErrBudgetExhausted is returned by Scan when the model exceeded Config.MaxToolCalls without ever emitting a final response. Callers receive whatever recommendations the loop accumulated along the way (currently always empty, since recommendations only land via the final-text path — but the contract leaves room for future "partial emit" semantics without a breaking signature change).
var ErrInvalidConfig = errors.New("agent: invalid config")
ErrInvalidConfig is returned by Config.Validate (and so by Scan, before any work) when a numeric cap is negative. Defaults only replaces zero, so a negative agent.max_findings_to_llm (or the env override) used to survive to `findings[:n]` and panic in the middle of a scan. A negative cap is a typo, not a request, so it is an error rather than a clamp.
var ErrInvalidResponse = errors.New("agent: model emitted invalid response")
ErrInvalidResponse is returned by Scan when the model's final text isn't a JSON array of Recommendation. The orchestrator does not attempt to repair the output — surfacing the error lets the caller decide whether to retry, fall back, or surface the problem to the user.
Functions ¶
This section is empty.
Types ¶
type Agent ¶
type Agent struct {
Repo *repo.Repo
Heuristics *heuristics.Registry
Provider llm.Provider
Config Config
// Actions is the registered action vocabulary the LLM is told
// it can emit. The system prompt's "Action is one of: ..." list
// is generated from this registry, so the model's vocabulary
// matches the dispatcher's vocabulary by construction. Nil
// falls back to action.NewDefaultRegistry() — production wires
// the same registry the CLI's dispatcher uses.
Actions *action.Registry
}
Agent is the orchestrator. Repo and Heuristics are required; Provider is required for any non-trivial Scan (no-finding short-circuits skip it). Config governs the loop's safety rails.
func (*Agent) Scan ¶
func (a *Agent) Scan(ctx context.Context, root string, stream chan<- string) ([]Recommendation, error)
Scan runs the heuristics, then drives the LLM loop until the model emits a final JSON array of recommendations or the tool-call budget is exhausted. The stream channel receives the model's text as it arrives; pass nil to disable. Scan owns no goroutines that outlive the call — when Scan returns, the stream channel won't see any more writes.
On no findings, Scan short-circuits with an empty result and writes a synthetic "no findings" message to stream so the TUI's tail viewport has something to display.
type Config ¶
type Config struct {
// MaxFindingsToLLM caps how many findings are fed into the initial
// user message. Larger N → more model context cost; defaults to 50
// per the design doc when zero.
MaxFindingsToLLM int
// MaxToolCalls is the per-Scan tool-call budget. Once the loop has
// dispatched this many tool calls, the next round must produce a
// final response or Scan fails with ErrBudgetExhausted. Defaults
// to 10 when zero.
MaxToolCalls int
// Model is the LLM model identifier passed through to the provider.
// The provider is free to ignore this if the value is empty.
Model string
// Walker controls the filesystem walk used to populate
// heuristics.Input.Walked. The zero value uses walker defaults.
Walker walker.Options
// InputConfig carries heuristic thresholds and policies sourced
// from the CLI config. Zero values preserve each heuristic's
// documented defaults.
InputConfig heuristics.InputConfig
// LocalOnly skips the LLM loop and converts heuristic findings
// directly into conservative recommendations.
LocalOnly bool
// Categories limits findings to matching Finding.Category or
// Finding.Heuristic values before local or LLM triage.
Categories []string
}
Config tunes the orchestrator's behavior. The zero value is unusable — MaxToolCalls of 0 would budget out before the first call. Tests build it inline; production wires it from sentra.yaml via the CLI.
func (Config) Defaults ¶
Defaults fills in sensible default values for any zero-valued Config fields. Pulled out so tests can exercise the defaulting behavior independent of Scan; CLI wiring also calls it after koanf merge.
func (Config) Validate ¶ added in v0.5.0
Validate rejects caps the orchestrator cannot honor. Every numeric field that is sliced or looped on belongs here: MaxFindingsToLLM bounds a slice expression and MaxToolCalls bounds the loop budget. Zero is fine (Defaults fills it); negative is ErrInvalidConfig.
type Recommendation ¶
type Recommendation struct {
ID string `json:"id"`
Action string `json:"action"`
Target string `json:"target"`
Severity string `json:"severity"`
Rationale string `json:"rationale"`
}
Recommendation is the structured advice the LLM returns for a finding- like situation. The CLI renders these as a styled table; the TUI streams them in as the loop progresses.
Action is one of: "prune_snapshot", "add_to_ignore", "flag_secret", "none". The CLI's --apply path dispatches each action through a small handler map; "none" is a no-op, used by the model to flag findings the user should know about but where there's no automatic remediation.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package action defines the vocabulary of remediations the Sentra agent can recommend, and a registry that maps each verb to a concrete side-effect.
|
Package action defines the vocabulary of remediations the Sentra agent can recommend, and a registry that maps each verb to a concrete side-effect. |
|
Package heuristics implements local rules that scan a walked tree, snapshot history, and live-blob set, producing structured Finding records the LLM agent can later triage.
|
Package heuristics implements local rules that scan a walked tree, snapshot history, and live-blob set, producing structured Finding records the LLM agent can later triage. |
|
Package llm defines the provider abstraction the Sentra agent uses to talk to a language model.
|
Package llm defines the provider abstraction the Sentra agent uses to talk to a language model. |
|
Package tools implements the read-only investigation toolset the Sentra agent advertises to the LLM.
|
Package tools implements the read-only investigation toolset the Sentra agent advertises to the LLM. |