workflow

package
v0.17.11 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

View Source
const (
	WorkflowWhenAlways    = "always"
	WorkflowWhenOnSuccess = "on_success"
	WorkflowWhenOnError   = "on_error"

	DefaultWorkflowOrchestrationStateFile  = ".sprout/workflow_state.json"
	DefaultWorkflowOrchestrationEventsFile = ".sprout/workflow_events.jsonl"
	DefaultWorkflowConversationSessionID   = "workflow"
)
View Source
const PathModeReadOnly = "read_only"

PathModeReadOnly declares the declared external folder is read-only — writes against any path under it must be refused by the filesystem gate.

View Source
const PathModeReadWrite = "read_write"

PathModeReadWrite declares the declared external folder is fully readable and writable for the duration of the workflow run.

Variables

This section is empty.

Functions

func ApplyWorkflowCommandOverrides

func ApplyWorkflowCommandOverrides(cfg *AgentWorkflowConfig, overrides *CLIOverrides)

func ApplyWorkflowInitialOverrides

func ApplyWorkflowInitialOverrides(chatAgent *agent.Agent, cfg *AgentWorkflowConfig, overrides *CLIOverrides) error

func ApplyWorkflowRuntimeAllowedPaths added in v0.17.7

func ApplyWorkflowRuntimeAllowedPaths(chatAgent *agent.Agent, paths []AllowedPath) (snapshotPaths []string, snapshotModes map[string]string, addedPaths []string, err error)

ApplyWorkflowRuntimeAllowedPaths adds each path in paths (derived from AllowedPath entries in the step's runtime config) to the agent's session allowlist and records the declared mode. This lets the cd-target gate (Phase 2.1) and the filesystem gate (Phase 2.2) see the paths as approved for the duration of the step.

Snapshot semantics: the snapshot captures the state BEFORE any paths are added, so restoreWorkflowRuntimeAllowedPaths can undo only the paths this step added — not paths contributed by earlier steps. This means consecutive steps that declare overlapping paths have the documented "last restore wins" behavior: step 2's snapshot contains step 1's contribution; step 2's restore removes both step 2's new paths AND step 1's old paths. Declare overlapping paths in each step that needs them, or promote them to the workflow-level AllowedPaths, if you need per-step isolation.

Idempotent: adding a path that's already on the allowlist is a no-op; it is NOT included in addedPaths, so it will NOT be removed on restore.

func ApplyWorkflowRuntimeOverrides

func ApplyWorkflowRuntimeOverrides(chatAgent *agent.Agent, runtime AgentWorkflowRuntime, overrides *CLIOverrides) error

func ApplyWorkflowSubagentOverrides

func ApplyWorkflowSubagentOverrides(subagentTypes map[string]configuration.SubagentType, overrides WorkflowSubagentOverrides)

ApplyWorkflowSubagentOverrides patches the SubagentTypes map entries matching the given overrides. No error is returned for unknown personas — they are skipped. Log lines are emitted for every skip and every successful apply so that silent divergence between the workflow JSON and the actual SubagentTypes is visible.

func AttachWorkflowBudget

func AttachWorkflowBudget(chatAgent *agent.Agent, cfg *AgentWorkflowConfig) (stop func())

AttachWorkflowBudget wires the workflow's USD budget and progress heartbeat onto the agent. Returns a stop function the caller MUST invoke before the agent shuts down — it unregisters callbacks and stops the heartbeat goroutine. If no budget is configured the returned stop is a no-op and no goroutines are started.

Heartbeat semantics:

  • Default cadence: 600s when a budget is configured, off otherwise.
  • cfg.Progress.HeartbeatSeconds > 0 overrides the cadence.
  • The heartbeat prints to stdout in a single line so it composes with existing console output without clobbering it.

func EmitWorkflowOrchestrationEvent

func EmitWorkflowOrchestrationEvent(cfg *AgentWorkflowConfig, eventType string, payload map[string]interface{}) error

func FindSubagentTypeMapKey

func FindSubagentTypeMapKey(subagentTypes map[string]configuration.SubagentType, normalizedID string) (string, bool)

FindSubagentTypeMapKey finds the original map key in SubagentTypes matching the given normalized persona ID. It mirrors the lookup logic in config.go GetSubagentType.

func IsSystemPathPrefix added in v0.17.7

func IsSystemPathPrefix(p string) bool

IsSystemPathPrefix reports whether the (already-cleaned, absolute) path falls under one of the OS system directories. Used by the loader to emit a warning when a workflow declares an allowed_path inside a system prefix — the user is touching platform infrastructure and deserves the louder heads-up, even though the workflow is allowed to proceed.

The list mirrors pkg/agent/path_tier.go::systemPathPrefixes; both should grow together if a new OS system directory is added. We keep the list local to the workflow package rather than importing the agent package (workflow is a leaf dependency — agent imports workflow, not the other way around).

Exported (capitalized) so pkg/automate/discovery.go::Summarize can reuse the same prefix list when rendering the WebUI/CLI summary.

func IsValidWorkflowWhen

func IsValidWorkflowWhen(v string) bool

func LoadLoopCheckpoint

func LoadLoopCheckpoint(workDir string) (int, error)

LoadLoopCheckpoint reads the fallback checkpoint file and returns the line number. Returns (0, nil) if the file doesn't exist.

func LoopCheckpointFilePath

func LoopCheckpointFilePath(workDir string) string

LoopCheckpointFilePath returns the path to the lightweight fallback checkpoint file that stores just the TODO line number.

func NormalizeReasoningEffort

func NormalizeReasoningEffort(v string) string

func NormalizeWorkflowPaths

func NormalizeWorkflowPaths(paths []string) []string

func NormalizeWorkflowPersonaID

func NormalizeWorkflowPersonaID(raw string) string

NormalizeWorkflowPersonaID normalizes a persona ID the same way config.go does.

func NormalizeWorkflowWhen

func NormalizeWorkflowWhen(v string) string

func ParseBudgetWarnList

func ParseBudgetWarnList(s string) ([]float64, error)

ParseBudgetWarnList parses a comma-separated list of fractional thresholds (e.g. "0.5,0.8") into a sorted []float64. Each value must be in (0, 1].

func PersistLoopCheckpoint

func PersistLoopCheckpoint(workDir string, lineNum int) error

PersistLoopCheckpoint writes just the line number to the fallback checkpoint file using an atomic write (temp file + rename).

func PersistWorkflowCheckpoint

func PersistWorkflowCheckpoint(cfg *AgentWorkflowConfig, state *WorkflowExecutionState, chatAgent *agent.Agent) error

func PersistWorkflowConversationState

func PersistWorkflowConversationState(chatAgent *agent.Agent, cfg *AgentWorkflowConfig) error

func PersistWorkflowExecutionState

func PersistWorkflowExecutionState(cfg *AgentWorkflowConfig, state *WorkflowExecutionState) error

func PrepareWorkflowRuntimeRestorer

func PrepareWorkflowRuntimeRestorer(chatAgent *agent.Agent, cfg *AgentWorkflowConfig, overrides *CLIOverrides) (func() error, error)

func RemoveLoopCheckpoint

func RemoveLoopCheckpoint(workDir string)

RemoveLoopCheckpoint deletes the fallback checkpoint file, ignoring not-found errors.

func ResolveStepPrompt

func ResolveStepPrompt(step AgentWorkflowStep) (string, error)

func ResolveWorkflowInitialPrompt

func ResolveWorkflowInitialPrompt(cliQuery string, cfg *AgentWorkflowConfig) (string, error)

func ResolveWorkflowTextOrFile

func ResolveWorkflowTextOrFile(text, filePath, label string) (string, error)

func RestoreWorkflowConversationState

func RestoreWorkflowConversationState(chatAgent *agent.Agent, cfg *AgentWorkflowConfig, state *WorkflowExecutionState) error

func RestoreWorkflowRuntimeAllowedPaths added in v0.17.7

func RestoreWorkflowRuntimeAllowedPaths(chatAgent *agent.Agent, snapshotPaths []string, snapshotModes map[string]string, addedPaths []string) error

restoreWorkflowRuntimeAllowedPaths undoes the paths added by the matching ApplyWorkflowRuntimeAllowedPaths call for this step. It is called at every step exit point (success, failure, skip, shell) to ensure no step's allowed_paths leak into the next step.

Restore semantics:

  • For each path in addedPaths: if it was NOT in snapshotPaths, remove it from the allowlist (it was added by this step).
  • For each path in snapshotPaths: restore its mode from snapshotModes (may be different from what a prior step left behind).

This means if step 1 adds /a and step 2 adds /b then /a:

  • After step 1: allowlist = [/a]
  • Step 2 snapshot: [/a]
  • Step 2 addedPaths: [/b] (/a was already there)
  • Step 2 restore removes [/b], leaves [/a]
  • After step 2: allowlist = [/a]

This is the documented "steps don't inherit paths from prior steps" behavior.

func RunAgentWorkflow

func RunAgentWorkflow(ctx context.Context, chatAgent *agent.Agent, eventBus *events.EventBus, cfg *AgentWorkflowConfig, state *WorkflowExecutionState, queryExecutor QueryExecutor, overrides *CLIOverrides) (bool, error)

func RunAgentWorkflowLoop

func RunAgentWorkflowLoop(ctx context.Context, chatAgent *agent.Agent, eventBus *events.EventBus, cfg *AgentWorkflowConfig, state *WorkflowExecutionState, queryExecutor QueryExecutor, overrides *CLIOverrides) (bool, error)

RunAgentWorkflowLoop iterates over unchecked TODO items, processing each with a fresh agent context. Between items, the conversation is cleared.

func ShouldRestoreWorkflowConversationState

func ShouldRestoreWorkflowConversationState(state *WorkflowExecutionState) bool

func ShouldRunWorkflowStep

func ShouldRunWorkflowStep(when string, hasError bool) bool

func ShouldYieldBeforeWorkflowStep

func ShouldYieldBeforeWorkflowStep(cfg *AgentWorkflowConfig, state *WorkflowExecutionState, nextStep AgentWorkflowStep, chatAgent *agent.Agent) bool

func StepFileTriggersSatisfied

func StepFileTriggersSatisfied(step AgentWorkflowStep) (bool, error)

func WorkflowEffectiveStepProvider

func WorkflowEffectiveStepProvider(chatAgent *agent.Agent, step AgentWorkflowStep) string

func WriteFileAtomic

func WriteFileAtomic(path string, data []byte, perm os.FileMode) error

WriteFileAtomic writes data to path atomically by writing to a temp file in the same directory and then renaming. This prevents partial/corrupt state files if the process crashes mid-write.

Types

type AgentWorkflowBudgetConfig

type AgentWorkflowBudgetConfig struct {
	// USD is the hard cap on cumulative cost across the workflow.
	// <= 0 means no cap.
	USD float64 `json:"usd,omitempty"`
	// WarnAt is a list of fractional thresholds (0.0–1.0). When the
	// cumulative spend first crosses each threshold, a single warning
	// is emitted to stdout and (when wired) the event bus.
	// Empty defaults to [0.50, 0.80].
	WarnAt []float64 `json:"warn_at,omitempty"`
	// OnExceed controls what happens when USD is reached.
	// "truncate" (default) sets the truncation flag so the run finishes
	// the current LLM response and stops gracefully. "stop" is reserved
	// for future hard-kill behavior; today it's treated like truncate.
	OnExceed string `json:"on_exceed,omitempty"`
}

AgentWorkflowBudgetConfig caps the total USD spend of a workflow run (primary agent + every subagent it spawns share the same budget).

USD-denominated rather than tokens because mixed-provider workflows route different personas to different price tiers — a token cap that covers an Opus orchestrator would let a DeepSeek coder consume 50× the work for the same budget, defeating the cap.

type AgentWorkflowConfig

type AgentWorkflowConfig struct {
	Description             string                            `json:"description,omitempty"`
	Initial                 *AgentWorkflowInitial             `json:"initial,omitempty"`
	Steps                   []AgentWorkflowStep               `json:"steps"`
	ContinueOnError         bool                              `json:"continue_on_error,omitempty"`
	PersistRuntimeOverrides *bool                             `json:"persist_runtime_overrides,omitempty"`
	Orchestration           *AgentWorkflowOrchestrationConfig `json:"orchestration,omitempty"`
	NoWebUI                 *bool                             `json:"no_web_ui,omitempty"`
	WebPort                 *int                              `json:"web_port,omitempty"`
	Daemon                  *bool                             `json:"daemon,omitempty"`
	Budget                  *AgentWorkflowBudgetConfig        `json:"budget,omitempty"`
	Progress                *AgentWorkflowProgressConfig      `json:"progress,omitempty"`

	// SubagentTimeoutSeconds overrides the per-run_subagent tool timeout
	// (default 1800 = 30 minutes). Set higher for very large refactors.
	SubagentTimeoutSeconds *int `json:"subagent_timeout_seconds,omitempty"`

	// RequiresApproval controls whether the run_automate agent tool must
	// surface an intent-confirmation prompt to the user before launching
	// this workflow. Pointer so we can distinguish "unset" (default: true)
	// from explicit false. Set to false for workflows that exist
	// specifically so an agent can invoke them mid-task — e.g. a
	// validation workflow referenced from AGENTS.md that the model must
	// run before considering work done. Anyone with workflow-file access
	// can flip this, so the security implication should be obvious to a
	// reader of the JSON.
	//
	// Only affects the agent tool path. The CLI (`sprout automate run`)
	// always prompts unless --yes is passed, because a human at the
	// keyboard might still fat-finger the wrong workflow.
	RequiresApproval *bool `json:"requires_approval,omitempty"`

	// Loop configures the workflow to iterate over a TODO file, processing
	// each unchecked item independently with a fresh agent context.
	// When Loop is set, Steps are ignored — the loop IS the execution plan.
	Loop *AgentWorkflowLoopConfig `json:"loop,omitempty"`

	// AllowedPaths declares the external directories the workflow needs
	// to read or write outside the workspace. Each entry is validated by
	// AllowedPath.Validate and pre-seeded into the running agent's
	// session allowlist (with mode) at run start so the workflow
	// doesn't re-prompt for every external access. See
	// `roadmap/SP-128-workflow-allowed-paths.md` for the full design.
	AllowedPaths []AllowedPath `json:"allowed_paths,omitempty"`
}

AgentWorkflowConfig defines non-interactive workflow orchestration.

func LoadAgentWorkflowConfig

func LoadAgentWorkflowConfig(path string) (*AgentWorkflowConfig, error)

func (*AgentWorkflowConfig) IsApprovalRequired

func (c *AgentWorkflowConfig) IsApprovalRequired() bool

IsApprovalRequired reports whether the run_automate tool path should surface an intent-confirmation prompt before launching this workflow. Defaults to true when unset.

func (*AgentWorkflowConfig) OrchestrationEnabled

func (c *AgentWorkflowConfig) OrchestrationEnabled() bool

func (*AgentWorkflowConfig) OrchestrationResumeEnabled

func (c *AgentWorkflowConfig) OrchestrationResumeEnabled() bool

func (*AgentWorkflowConfig) OrchestrationYieldOnProviderHandoff

func (c *AgentWorkflowConfig) OrchestrationYieldOnProviderHandoff() bool

func (*AgentWorkflowConfig) ShouldPersistRuntimeOverrides

func (c *AgentWorkflowConfig) ShouldPersistRuntimeOverrides() bool

func (*AgentWorkflowConfig) Validate

func (c *AgentWorkflowConfig) Validate() error

type AgentWorkflowInitial

type AgentWorkflowInitial struct {
	Prompt       string        `json:"prompt,omitempty"`
	PromptFile   string        `json:"prompt_file,omitempty"`
	AllowedPaths []AllowedPath `json:"allowed_paths,omitempty"`
	AgentWorkflowRuntime
}

AgentWorkflowInitial is the first run definition (can replace CLI prompt).

type AgentWorkflowLoopConfig

type AgentWorkflowLoopConfig struct {
	// TodoFile is the markdown file to scan for [ ] items. Default: TODO.md.
	TodoFile string `json:"todo_file,omitempty"`
	// GatePromptFile is the system prompt for the gate LLM call that
	// parses each TODO section into a structured delegation prompt.
	// Required. The gate call uses the agent's existing client.
	GatePromptFile string `json:"gate_prompt_file,omitempty"`
	// MaxRetries is the number of retry attempts on build failure
	// before skipping an item. Default: 2.
	MaxRetries int `json:"max_retries,omitempty"`
	// MaxIterations caps the agent iterations per item. Default: 50.
	MaxIterations int `json:"max_iterations,omitempty"`
	// BuildCommand is run after each item to verify. Default: "go build ./...".
	BuildCommand string `json:"build_command,omitempty"`
}

AgentWorkflowLoopConfig configures the workflow to iterate over a TODO file, processing each unchecked item independently with a fresh agent context. When Loop is set, Steps are ignored — the loop IS the execution plan.

type AgentWorkflowOrchestrationConfig

type AgentWorkflowOrchestrationConfig struct {
	Enabled                bool   `json:"enabled,omitempty"`
	Resume                 *bool  `json:"resume,omitempty"`
	YieldOnProviderHandoff *bool  `json:"yield_on_provider_handoff,omitempty"`
	StateFile              string `json:"state_file,omitempty"`
	EventsFile             string `json:"events_file,omitempty"`
	ConversationSessionID  string `json:"conversation_session_id,omitempty"`
}

AgentWorkflowOrchestrationConfig enables external orchestration integration.

type AgentWorkflowProgressConfig

type AgentWorkflowProgressConfig struct {
	// HeartbeatSeconds is the interval at which the workflow prints a
	// progress line ([budget] $X of $Y · iter N · elapsed Tm).
	// <= 0 disables the heartbeat. Default 600 (10 min) when Budget is set.
	HeartbeatSeconds int `json:"heartbeat_seconds,omitempty"`
}

AgentWorkflowProgressConfig controls runtime visibility of the workflow.

type AgentWorkflowRuntime

type AgentWorkflowRuntime struct {
	SkipPrompt        *bool                     `json:"skip_prompt,omitempty"`
	Provider          string                    `json:"provider,omitempty"`
	Model             string                    `json:"model,omitempty"`
	Persona           string                    `json:"persona,omitempty"`
	DryRun            *bool                     `json:"dry_run,omitempty"`
	MaxIterations     *int                      `json:"max_iterations,omitempty"`
	NoStream          *bool                     `json:"no_stream,omitempty"`
	SystemPrompt      string                    `json:"system_prompt,omitempty"`
	SystemPromptFile  string                    `json:"system_prompt_file,omitempty"`
	Unsafe            *bool                     `json:"unsafe,omitempty"`
	NoSubagents       *bool                     `json:"no_subagents,omitempty"`
	ResourceDirectory string                    `json:"resource_directory,omitempty"`
	ReasoningEffort   string                    `json:"reasoning_effort,omitempty"`
	SubagentOverrides WorkflowSubagentOverrides `json:"subagent_overrides,omitempty"`
	// RiskProfile selects a named shell-command risk cascade preset
	// for this step / initial run (SP-058). One of: readonly,
	// cautious, default, permissive, unrestricted. Per-step values
	// override the workflow-level initial setting and the global
	// config. Unknown values fall through to the agent's default
	// resolution chain (override > config > "default").
	RiskProfile string `json:"risk_profile,omitempty"`
}

AgentWorkflowRuntime contains runtime options aligned with agent CLI flags.

func (*AgentWorkflowRuntime) Validate

func (r *AgentWorkflowRuntime) Validate(prefix string) error

type AgentWorkflowStep

type AgentWorkflowStep struct {
	Name          string        `json:"name,omitempty"`
	Prompt        string        `json:"prompt,omitempty"`
	PromptFile    string        `json:"prompt_file,omitempty"`
	Command       string        `json:"command,omitempty"`
	CommandFile   string        `json:"command_file,omitempty"`
	When          string        `json:"when,omitempty"`
	FileExists    []string      `json:"file_exists,omitempty"`
	FileNotExists []string      `json:"file_not_exists,omitempty"`
	AllowedPaths  []AllowedPath `json:"allowed_paths,omitempty"`
	AgentWorkflowRuntime
}

AgentWorkflowStep is a single step executed after the initial query.

A step is either an agent step (Prompt or PromptFile) or a shell step (Command or CommandFile). The two kinds are mutually exclusive — validation fails if both are set or neither is set.

Shell steps run the command via the user's $SHELL (or /bin/sh) with the workflow's working directory and inherit stdout/stderr. They do NOT trigger model inference; they are useful for cheap, deterministic steps like `make build`, `git status`, or invoking a custom script that prepares state for the next agent step.

func (AgentWorkflowStep) IsShellStep

func (s AgentWorkflowStep) IsShellStep() bool

IsShellStep reports whether the step is configured to run a shell command instead of triggering model inference.

type AllowedPath added in v0.17.7

type AllowedPath struct {
	// Path is the absolute path to the directory. Must be absolute,
	// free of `..` traversal after Clean(), and must not start with
	// `~` (refuse to expand; user must provide the canonical absolute
	// path).
	Path string `json:"path"`

	// Mode is one of {read_only, read_write}. The filesystem layer
	// enforces this: a write tool called against a read_only entry
	// gets a security error explaining the declared mode blocked it.
	Mode string `json:"mode"`

	// Reason is surfaced verbatim in the launch confirmation dialog
	// so the user understands why the workflow needs this path.
	// Strongly recommended; loader does not require it.
	Reason string `json:"reason,omitempty"`
}

AllowedPath is a single directory the workflow needs access to outside the workspace. Declared at the workflow level so the user can review every external path in one place at launch time, and the runtime can pre-seed the session allowlist so no per-tool approval dialogs fire mid-run.

Rules enforced by Validate:

  • Path must be absolute (filepath.IsAbs).
  • Path must not contain `..` segments after filepath.Clean.
  • Path must not start with `~` (we refuse to expand — the workflow author must supply a canonical absolute path).
  • Mode must be one of {read_only, read_write} (case-sensitive).
  • Reason is optional; loader does not require it.

Paths that fall under a known system prefix (see isSystemPathPrefix) trigger a warning via log.Printf — the loader surfaces that warning so the user is aware the workflow touches platform infrastructure, but the path itself is allowed. Sensitive-path blocking is enforced elsewhere (filesystem tier classification / path_tier.go).

func (*AllowedPath) Validate added in v0.17.7

func (a *AllowedPath) Validate() error

Validate enforces the schema rules documented on AllowedPath. Returns nil for a valid entry; a descriptive error otherwise. The error message identifies the offending field so the loader can attribute the failure to the right entry index.

type CLIOverrides

type CLIOverrides struct {
	SetWebUI    func(disabled bool)
	SetWebPort  func(port int)
	SetDaemon   func(enabled bool)
	SetNoStream func(enabled bool)
	GetNoStream func() bool

	// Budget/heartbeat CLI overrides. Zero values mean "inherit JSON".
	BudgetUSD        float64
	BudgetWarn       string
	HeartbeatSeconds int
}

CLIOverrides provides the callback functions that applyWorkflowCommandOverrides needs to mutate CLI-level global flags (web UI, port, daemon, streaming, budget, heartbeat). The cmd/ package constructs this with closures over its real flag variables.

type QueryExecutor

type QueryExecutor func(ctx context.Context, chatAgent *agent.Agent, eventBus *events.EventBus, query string) error

QueryExecutor is the signature of cmd.ProcessQuery. The runner and loop accept this as a dependency so the workflow package never imports cmd/.

type WorkflowExecutionState

type WorkflowExecutionState struct {
	Version            int    `json:"version"`
	InitialCompleted   bool   `json:"initial_completed"`
	NextStepIndex      int    `json:"next_step_index"`
	CurrentTodoLineNum int    `json:"current_todo_line_num,omitempty"`
	HasError           bool   `json:"has_error"`
	FirstError         string `json:"first_error,omitempty"`
	LastProvider       string `json:"last_provider,omitempty"`
	Complete           bool   `json:"complete"`
	UpdatedAt          string `json:"updated_at,omitempty"`
}

WorkflowExecutionState tracks workflow execution progress for checkpoint/resume support.

func LoadWorkflowExecutionState

func LoadWorkflowExecutionState(cfg *AgentWorkflowConfig) (*WorkflowExecutionState, error)

func NewWorkflowExecutionState

func NewWorkflowExecutionState() *WorkflowExecutionState

type WorkflowSubagentOverride

type WorkflowSubagentOverride struct {
	Provider string `json:"provider,omitempty"`
	Model    string `json:"model,omitempty"`
}

WorkflowSubagentOverride defines per-persona subagent provider/model overrides.

type WorkflowSubagentOverrides

type WorkflowSubagentOverrides map[string]WorkflowSubagentOverride

WorkflowSubagentOverrides maps persona IDs to their subagent routing overrides. Keys are normalized persona IDs (lowercase, hyphens→underscores). Values override provider/model for subagents with that persona.

Jump to

Keyboard shortcuts

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