Documentation
¶
Overview ¶
Package profiles supplies preset agent.Profile constructors.
A profile picks two tool-name lists — ActiveTools (eager) and DeferredTools (lazy via TOOL_SEARCH) — an LLM target, and a system prompt. Each profile builds its own system prompt internally via the sysprompt package; callers never pass a sysprompt string in. The invariant: a distinct system prompt always lives behind a distinct profile constructor — never as an ad-hoc input — so two agents on the same Profile behave identically.
Adding a new profile = one function composing name lists from the family Names() helpers plus a buildSysPrompt call.
Index ¶
- Variables
- type Agent
- func (a *Agent) AgentID() string
- func (a *Agent) Broker() permission.Broker
- func (a *Agent) Compact(ctx context.Context, kind string) error
- func (a *Agent) Continue(ctx context.Context) (string, error)
- func (a *Agent) CyclePermissionMode() string
- func (a *Agent) DeferredNames() []tools.ToolName
- func (a *Agent) Describe(name tools.ToolName) (tools.Descriptor, error)
- func (a *Agent) Effort() string
- func (a *Agent) IsAsync() bool
- func (a *Agent) IsSubagent() bool
- func (a *Agent) ListMainProfiles() []ui.ProfileChoice
- func (a *Agent) Logger() *slog.Logger
- func (a *Agent) MaxIterations() int
- func (a *Agent) Model() string
- func (a *Agent) ParentID() string
- func (a *Agent) PermissionBroker() permission.Broker
- func (a *Agent) PermissionMode() permission.Mode
- func (a *Agent) PermissionModeName() string
- func (a *Agent) PermissionStore() *permission.Store
- func (a *Agent) PlanModeState() *permission.PlanModeState
- func (a *Agent) PrePlanMode() permission.Mode
- func (a *Agent) Profile() Profile
- func (a *Agent) ProfileName() string
- func (a *Agent) ResolveTool(name tools.ToolName) (tools.Tool, error)
- func (a *Agent) RespondPermission(id string, dec ui.PermissionDecision) error
- func (a *Agent) RespondQuestion(id string, resp ui.QuestionResponse) error
- func (a *Agent) Run(ctx context.Context, prompt string) (string, error)
- func (a *Agent) Session() *session.Session
- func (a *Agent) SetEffort(level string) error
- func (a *Agent) SetMaxIterations(n int)
- func (a *Agent) SetPermissionMode(m permission.Mode)
- func (a *Agent) SetPrePlanMode(m permission.Mode)
- func (a *Agent) Sink() event.Sink
- func (a *Agent) Skills() []ui.Skill
- func (a *Agent) Spawn(ctx context.Context, req meta.SpawnRequest) (string, error)
- func (a *Agent) Status() constant.AgentStatus
- func (a *Agent) SubagentTypes() []string
- func (a *Agent) SwitchLLM(provider constant.LLMProvider, model constant.Model) error
- func (a *Agent) SwitchProfile(name string) error
- func (a *Agent) Tool(name string) (tools.Tool, bool)
- func (a *Agent) ToolState() *toolset.ToolState
- func (a *Agent) Workdir() string
- type AgentRegistry
- func (r *AgentRegistry) All() []sysprompt.AgentDefinition
- func (r *AgentRegistry) Get(name string) (sysprompt.AgentDefinition, bool)
- func (r *AgentRegistry) ListMain() []sysprompt.AgentDefinition
- func (r *AgentRegistry) ListSubagent() []sysprompt.AgentDefinition
- func (r *AgentRegistry) Register(def sysprompt.AgentDefinition) (sysprompt.AgentDefinition, bool)
- type AgentType
- type Option
- func WithAgentRegistry(r *AgentRegistry) Option
- func WithAsync(async bool) Option
- func WithConfig(cfg *config.Config) Option
- func WithCustomTool(name tools.ToolName, factory pubtoolset.ToolFactory) Option
- func WithMaxIterations(n int) Option
- func WithMemorySnapshot(snap memdir.Snapshot) Option
- func WithName(name string) Option
- func WithPermissionBroker(b permission.Broker) Option
- func WithPermissionMode(m permission.Mode) Option
- func WithPermissionStore(s *permission.Store) Option
- func WithPersona(name string) Option
- func WithQuestionBroker(b question.Broker) Option
- func WithSink(s event.Sink) Option
- func WithSkillRefs(refs []sysprompt.SkillRef) Option
- func WithSkillRegistry(r *skill.Registry) Option
- func WithStream(stream bool) Option
- type Profile
- func Explore(cfg *config.Config, provider constant.LLMProvider, model constant.Model, ...) Profile
- func General(cfg *config.Config, provider constant.LLMProvider, model constant.Model, ...) Profile
- func Main(cfg *config.Config, provider constant.LLMProvider, model constant.Model, ...) Profile
- func Plan(cfg *config.Config, provider constant.LLMProvider, model constant.Model, ...) Profile
- func ResolveMainProfile(cfg *config.Config, reg *AgentRegistry, name string, ...) (Profile, error)
Constants ¶
This section is empty.
Variables ¶
var ErrIterLimit = errors.New("agent: iteration limit reached")
ErrIterLimit is returned by Run / Continue when the loop hits maxIters without the model producing a terminal text response. The agent is paused, not failed — call Continue(ctx) to resume from the same session.
var ErrRunInProgress = errors.New("agent: run already in progress")
ErrRunInProgress is returned by Run / Continue when another goroutine is already executing the loop for this agent. Concurrent runs would race on session.Messages and corrupt the assistant-toolcall → tool-result invariant the LLM providers require, so the second caller fails fast instead.
Functions ¶
This section is empty.
Types ¶
type Agent ¶
Agent runs a chat loop against an llm.Client, configured by a Profile.
Tool lifecycle (three phases for the model's view of a tool):
ACTIVE — built eagerly in New() and sent (name + description + schema) to the LLM on every Complete call. The model can call them with no preamble.
DEFERRED — listed in the profile's allowlist but NOT built at startup. The model sees them by name only (typically referenced in the system prompt). It must call TOOL_SEARCH to fetch a deferred tool's full schema; TOOL_SEARCH uses toolset.Describe, which reads metadata without building. Construction is intentionally postponed.
RESOLVED — the first time the model actually invokes a deferred tool, the dispatcher calls ResolveTool(name): the tool is built, cached in the active map, executed, and remains available (with its schema sent to the LLM) on every subsequent turn.
toolState holds the shared state container toolset.Build threads into stateful tool constructors. The TUI and session-persist layer read state through it (e.g. agent.ToolState().TodoStore().List()).
sink is the event consumer (nil => Discard). ParentID is empty for the root agent and the root's AgentID for subagents — see Option AsSubagent.
func New ¶
New constructs an agent with a fresh ID, a per-agent logger, and the given profile applied. ActiveTools are built immediately; DeferredTools are recorded as an allowlist and only built on the first ResolveTool call.
Options run after the agent struct is populated from the profile and before the LLM client is constructed, so they can influence either layer.
func (*Agent) Broker ¶
func (a *Agent) Broker() permission.Broker
Broker is an alias for PermissionBroker that satisfies mode.PlanModeController. Kept short so the controller interface stays terse — EnterPlanMode / ExitPlanMode only know the agent through this interface, not the full *Agent.
func (*Agent) Compact ¶
Compact is the manual entry point invoked by the TUI's /compact chooser. Unlike the auto path it bypasses the threshold check and the micro→full escalation — the user explicitly picked a kind.
Refuses with ErrRunInProgress when a Run is currently driving the loop, same guard SwitchLLM uses; the caller (TUI) surfaces that as a hint rather than queueing.
kind is "micro" or "full"; any other value is an error.
func (*Agent) Continue ¶
Continue resumes a paused agent without appending a new user message. Used after ErrIterLimit (the "press enter to keep going" path) and after /resume reloads a session snapshot.
func (*Agent) CyclePermissionMode ¶
CyclePermissionMode advances the mode in Shift+Tab order and returns the new mode name. Implements ui.Controller.
Unlike SetPermissionMode, this method does NOT emit a KindModeChanged event. It is called from the TUI's Update goroutine (via the Shift+Tab handler), and emitting would call tea.Program.Send() back into the same event loop — a guaranteed deadlock since bubbletea's p.msgs channel is unbuffered. The TUI already updates its status bar directly, so the event is redundant on this path.
func (*Agent) DeferredNames ¶
DeferredNames returns the canonical list of tool names the profile allows to be lazy-loaded. TOOL_SEARCH uses this to know which names it may describe (and the system-prompt builder uses it to advertise them).
Part of the meta.DeferredLookup interface; the agent installs itself as the lookup target via toolState.SetDeferredLookup in New().
func (*Agent) Describe ¶
Describe returns the metadata for a deferred tool by name. Delegates to toolset.Describe, which constructs a throwaway instance to read its static fields — no agent state is mutated and no tool is "loaded".
Part of the meta.DeferredLookup interface, used by TOOL_SEARCH.
func (*Agent) IsSubagent ¶
IsSubagent reports whether this agent was constructed with AsSubagent. The AGENT tool checks this to enforce the "subagents cannot spawn subagents" invariant.
func (*Agent) ListMainProfiles ¶
func (a *Agent) ListMainProfiles() []ui.ProfileChoice
ListMainProfiles enumerates the personas the /profile picker can switch to. Pulls from the registry's ListMain(); subagents return nil (they don't drive the picker).
func (*Agent) Logger ¶
Logger exposes the agent's logger so callers can emit records that share the agent's structured context.
func (*Agent) MaxIterations ¶
MaxIterations returns the current loop cap. Safe to call from any goroutine — backed by an atomic load.
func (*Agent) Model ¶
Model returns the model id the agent's LLM client is bound to. Wraps llm.Client.Model() so the ui.Controller interface stays independent of the llm package. Empty when no client is attached.
func (*Agent) PermissionBroker ¶
func (a *Agent) PermissionBroker() permission.Broker
PermissionBroker exposes the shared approval back-channel.
func (*Agent) PermissionMode ¶
func (a *Agent) PermissionMode() permission.Mode
PermissionMode returns the agent's current permission stance. Safe to call from any goroutine.
func (*Agent) PermissionModeName ¶
PermissionModeName returns the mode as a plain string (ui.Controller uses a string-typed interface to avoid importing internal/permission).
func (*Agent) PermissionStore ¶
func (a *Agent) PermissionStore() *permission.Store
PermissionStore exposes the shared rule store. Returns nil if the caller didn't install one (tests, headless CLI runs).
func (*Agent) PlanModeState ¶
func (a *Agent) PlanModeState() *permission.PlanModeState
PlanModeState exposes the unified plan-mode state holder so the attachment computer (internal/agent/attachments) can read the reminder-cycle counters without going through the agent's narrow permission-mode interface.
func (*Agent) PrePlanMode ¶
func (a *Agent) PrePlanMode() permission.Mode
PrePlanMode returns the mode that was active immediately before plan mode became active. Empty until the first plan-mode entry; ExitPlanMode falls back to ModeDefault when empty.
Reads through the unified plan-mode state holder so the TUI's Shift+Tab path and the EnterPlanMode tool path agree on what was stashed.
func (*Agent) ProfileName ¶
ProfileName returns the active persona's wire name ("evva", "nono", ...). Used by the TUI status bar and the /profile picker's current-row marker. Subagents return the persona kind they were constructed under.
func (*Agent) ResolveTool ¶
ResolveTool returns the runnable instance for a tool name, building it on the fly if it's a still-unmaterialized deferred tool. This is the path the tool-call dispatcher takes whenever the LLM invokes a tool by name:
- If the name is already in the active map (either built at New() or resolved on a previous turn), the cached instance is returned.
- Otherwise, if the name is in the deferred allowlist, the tool is built via toolset.Build, cached in active, and returned. Its schema will be advertised to the LLM from the next turn forward.
- Otherwise, the name is rejected — the agent never silently expands beyond the profile's declared authority.
Note: TOOL_SEARCH should NOT call this — it only fetches descriptors via toolset.Describe. The build is triggered by the first actual invocation.
func (*Agent) RespondPermission ¶
func (a *Agent) RespondPermission(id string, dec ui.PermissionDecision) error
RespondPermission forwards the user's approval choice from the TUI to the broker. The id ties back to a single blocked Broker.Request call. Returns ui.ErrUnknownPermission if the id is no longer pending (already answered or cancelled). Implements ui.Controller.
func (*Agent) RespondQuestion ¶
func (a *Agent) RespondQuestion(id string, resp ui.QuestionResponse) error
RespondQuestion forwards the user's answers from the TUI to the question broker. id ties back to a single blocked question.Broker.Request call. Implements ui.Controller.
func (*Agent) Run ¶
Run drives the agent to completion for a single user turn.
It appends a RoleUser{prompt} message to the session and then loops: LLM completion → if tool_use, dispatch all tool calls in parallel, append the collected results as a single RoleTool message, repeat. The loop exits when the model emits no tool calls (normal terminal), the context is cancelled, the iteration cap is hit (ErrIterLimit), or a Go-level error aborts.
Events flow to the agent's Sink. The returned llm.Response is the final assistant turn — or the zero value when the loop ended without one.
func (*Agent) SetEffort ¶
SetEffort updates the effort level at runtime. Validates the name, applies it to the LLM client, and persists to config.
func (*Agent) SetMaxIterations ¶
SetMaxIterations updates the loop cap. Takes effect at the next iteration boundary (loop.go:74 reads a.maxIters via atomic.Load). Values <= 0 are clamped to 1.
func (*Agent) SetPermissionMode ¶
func (a *Agent) SetPermissionMode(m permission.Mode)
SetPermissionMode updates the agent's permission stance at runtime. Every entry path (Shift+Tab cycle, EnterPlanMode / ExitPlanMode tools, future SDK control messages) routes through here so the plan-mode transition hub runs exactly once per mode change and the TUI receives a single KindModeChanged event per change.
Validates the mode; ignores unknown values to keep the system in a known-good state. Idempotent on no-op transitions: same-mode calls neither run side effects nor emit the change event.
Mode changes don't propagate to already-spawned subagents — they captured the mode at spawn time. New spawns see the updated mode.
func (*Agent) SetPrePlanMode ¶
func (a *Agent) SetPrePlanMode(m permission.Mode)
SetPrePlanMode is retained on the PlanModeController interface for the EnterPlanMode tool, but new code should rely on SetPermissionMode (which runs the transition hub and stashes the prior mode automatically).
func (*Agent) Sink ¶
Sink returns the agent's event sink. Used by the AGENT tool to wrap with BubbleUp when spawning a subagent. Returns event.Discard if no sink was installed.
func (*Agent) Skills ¶
Skills returns the user-installed skill catalog as the UI sees it — name + description per entry, sorted by name. Implements ui.Controller so the TUI's slash-suggestion panel can list skills alongside the built-in commands without reaching into ToolState directly.
Returns nil when no registry was installed (e.g. tests / headless callers that didn't pass WithSkillRegistry).
func (*Agent) Spawn ¶
Spawn implements meta.SubagentSpawner. The AGENT tool's lookup resolves to *Agent (the root agent registers itself via SetSubagentSpawner in New).
Spawn:
- Rejects calls from a subagent (the "main only" invariant).
- Picks a Profile via subagentProfile, inheriting the ParentID's provider, options, and any baseline preferences.
- Overrides the model based on req.Level via LLMProvider.ModelForLevel — 1 is the normal tier, 2 is the big tier.
- Constructs a child agent with event.BubbleUp routing its events back to the ParentID's Sink, tagged with the ParentID's AgentID.
- Registers the child in the ParentID's SpawnGroup panel — every mutation is observable through the unified ToolState change stream.
- Runs the child: - Sync mode: blocks until child.Run completes, removes from panel on return, and propagates the child's text through the tool result. - Async mode: spawns a goroutine that runs the child and marks the panel entry Report / Crushed on exit. Returns immediately with an ack message; the ParentID loop will pick up the eventual result via AgentGroup.DrainCompleted between turns.
func (*Agent) Status ¶
func (a *Agent) Status() constant.AgentStatus
func (*Agent) SubagentTypes ¶
SubagentTypes returns the agent names that the AGENT tool's subagent_type enum should accept. Pulls from the registry's ListSubagent (so disk subagents become wire-callable as soon as the registry sees them). Falls back to the built-in pair when no registry is installed.
func (*Agent) SwitchLLM ¶
SwitchLLM rebuilds a.llm with a new (provider, model) pair, updates a.profile so subagents inherit the new provider, and clears the session — provider-specific in-flight state (Anthropic ThinkingSignature, DeepSeek reasoning_content) is provider-locked, so keeping history across a swap would 400 on the next request.
MUST be called while no Run is in flight. Returns ErrRunInProgress when the running guard is set, so the caller can refuse the swap instead of racing a.llm reads on the agent loop's goroutine.
func (*Agent) SwitchProfile ¶
SwitchProfile rebuilds the agent for a new persona — different system prompt, different active/deferred tool lists, fresh session. Mirrors SwitchLLM's running-guard discipline.
The toolState is preserved so observable subscriptions (the TUI panels) keep working across the swap; only the TodoStore is cleared since its entries belong to a single session. The LLM client is rebuilt because the new profile carries its own WithSystem option.
MUST be called while no Run is in flight. Returns ErrRunInProgress when the running guard is set. Persists the new persona name to evva-config.yml so the next launch boots into it.
func (*Agent) Tool ¶
Tool returns the runnable instance for an already-built tool. Returns ok=false for deferred names that have not been resolved yet — call ResolveTool when you intend to execute.
type AgentRegistry ¶
type AgentRegistry struct {
// contains filtered or unexported fields
}
AgentRegistry holds every agent definition known to the runtime — Go-defined built-ins (sysprompt.MainAgent, ExploreAgent, GeneralAgent) merged with disk-loaded definitions from <EVVA_HOME>/agents/{name}/.
Phase 6 will consume this registry from two sides:
- The /profile slash command picker lists agents with ListMain().
- The Agent tool's subagent_type schema enum becomes the union of every agent in ListSubagent().
Phase 2 plants the registry and routes subagent resolution through it, but the Agent tool's schema enum stays hardcoded — disk-loaded subagents will load into the registry but won't be wire-callable until Phase 6 flips the schema.
func BuildAgentRegistry ¶
func BuildAgentRegistry(evvaHome string) (*AgentRegistry, []loader.Warning)
BuildAgentRegistry assembles the runtime registry: built-ins first, then disk agents from <evvaHome>/agents/. Disk agents that collide with a built-in name are skipped with a warning — built-ins always win so a typo in a disk agent's directory name can't silently replace `explore`.
Returns the registry and any warnings the host should log. Never returns an error: a missing or malformed disk catalog degrades gracefully.
func NewAgentRegistry ¶
func NewAgentRegistry() *AgentRegistry
NewAgentRegistry returns an empty registry. Most callers want BuildAgentRegistry, which pre-populates built-ins + disk agents.
func (*AgentRegistry) All ¶
func (r *AgentRegistry) All() []sysprompt.AgentDefinition
All returns every definition sorted by name. Useful for diagnostics and the Phase 6 picker enumeration paths.
func (*AgentRegistry) Get ¶
func (r *AgentRegistry) Get(name string) (sysprompt.AgentDefinition, bool)
Get returns the definition for name. Lookup is case-insensitive to match the AGENT tool's subagent_type behavior — "Explore", "explore", "EXPLORE" all resolve to the same agent.
func (*AgentRegistry) ListMain ¶
func (r *AgentRegistry) ListMain() []sysprompt.AgentDefinition
ListMain returns every definition whose `as:` includes "main" — the candidates the Phase 6 /profile picker shows.
func (*AgentRegistry) ListSubagent ¶
func (r *AgentRegistry) ListSubagent() []sysprompt.AgentDefinition
ListSubagent returns every definition whose `as:` includes "subagent" — the candidates Phase 6 will surface in the Agent tool's dynamic enum.
func (*AgentRegistry) Register ¶
func (r *AgentRegistry) Register(def sysprompt.AgentDefinition) (sysprompt.AgentDefinition, bool)
Register adds (or overwrites) a definition. Returns the previous value and a bool indicating whether a definition with this name already existed — callers (the loader merge step) can warn on duplicates so a disk agent silently shadowing a built-in is visible at startup.
type AgentType ¶
type AgentType int
AgentType enumerates the kinds of agent we know how to bootstrap. Profiles in agent/profiles are keyed off these values; the value also appears in logs to identify which kind of agent emitted a record.
type Option ¶
type Option func(*Agent)
Option mutates an Agent during construction. Options are applied after the profile is materialized but before the LLM client is initialized so any option can influence either side without ordering surprises.
func WithAgentRegistry ¶
func WithAgentRegistry(r *AgentRegistry) Option
WithAgentRegistry installs the merged built-in + disk agent registry on the agent. Subagent spawn resolves through this registry: kinds the AGENT tool's schema enum accepts ("explore", "general-purpose") plus any disk-loaded subagent the registry surfaces once Phase 6 opens the schema.
Subagents inherit the same pointer when the spawner forwards it explicitly — see spawn.go where the parent's registry is threaded into child.New so a delegated query (Phase 6's evva → nono pattern) can still look up the disk catalog without rebuilding it.
nil clears the registry; in practice the root agent always installs one at startup and subagents inherit it, so nil only appears in tests.
func WithConfig ¶
WithConfig installs the runtime configuration the agent reads from. Subagents inherit the parent's config via spawn; downstream apps that run multiple agents with different home dirs pass distinct *config.Config pointers per agent.
Omitting WithConfig boots the agent against config.Get() — the historical singleton — so cmd/evva and existing callers don't need to change.
func WithCustomTool ¶
func WithCustomTool(name tools.ToolName, factory pubtoolset.ToolFactory) Option
WithCustomTool registers a downstream-authored tool on the pkg/toolset.DefaultRegistry and adds it to the agent's active list. The factory receives the agent's pkg/tools.State at build time so the tool can read Config() and Workdir().
Registration is idempotent across agents — calling WithCustomTool with the same name in two New calls registers the factory once and reuses it. Use this for tool factories that are private to the downstream app; tools authored as part of a shared library should be registered directly on pkg/toolset.DefaultRegistry at process startup instead.
The tool's name MUST be unique across all registered tools (built-ins and prior customs alike). Re-registering an existing name during agent construction does NOT error — the original factory keeps serving.
func WithMaxIterations ¶
WithMaxIterations overrides the agent's loop cap. Pass 0 to keep the cfg-derived default (applied after options run in agent.New). Values in (0, 2) are clamped to 2 (single-turn agents would never observe a tool result).
func WithMemorySnapshot ¶
WithMemorySnapshot stashes the EVVA.md + USER_PROFILE.md snapshot loaded at startup. Reused by SwitchProfile when constructing a new persona's system prompt — the on-disk files are read once at boot.
func WithPermissionBroker ¶
func WithPermissionBroker(b permission.Broker) Option
WithPermissionBroker installs the approval back-channel. Same pattern as WithPermissionStore: one Broker per process, shared by all agents. The TUI registers its onRequest callback on this Broker at startup.
func WithPermissionMode ¶
func WithPermissionMode(m permission.Mode) Option
WithPermissionMode sets the agent's initial permission stance. Subagents inherit the parent's mode at spawn time; the runtime cycle (Shift+Tab) uses Agent.SetPermissionMode.
func WithPermissionStore ¶
func WithPermissionStore(s *permission.Store) Option
WithPermissionStore installs the rule store. One process-wide Store is built in cmd/evva/main.go and threaded into the root agent and every subagent so session rules added in one place are visible everywhere.
func WithPersona ¶
WithPersona records the active persona's wire name on the agent. Callers set this from profile-resolution so ProfileName() and the TUI status bar render the right label. Empty leaves the field as-is (the bootstrap caller is expected to set it explicitly).
func WithQuestionBroker ¶
WithQuestionBroker installs the question back-channel. Same pattern as WithPermissionBroker: one Broker per process, shared by all agents. The TUI registers its OnRequest callback on this Broker at startup.
func WithSink ¶
WithSink installs the event consumer. nil sinks become event.Discard at emit-time; pass event.Multi{...} to fan out to several consumers.
func WithSkillRefs ¶
WithSkillRefs stashes the skill snapshot the agent was bootstrapped with so SwitchProfile can rebuild the system prompt with the same skill catalog. The snapshot is a flat slice the sysprompt builder consumes; the agent does not call into the skill package directly.
func WithSkillRegistry ¶
WithSkillRegistry installs the merged skill catalog on the agent's ToolState before the first turn. The SKILL tool reads through this registry at Execute time; passing nil leaves the SKILL tool with no skills available.
The same pointer is shared with subagents when the spawner forwards it explicitly — today subagent profiles omit SKILL, so this is primarily a root-agent concern.
func WithStream ¶
WithStream toggles streaming completions for this agent. Overrides the Profile's Stream field; useful for tests and one-off callers that want to force the buffered or chunked path without editing the profile.
type Profile ¶
type Profile struct {
Type AgentType
SystemPrompt string
// Tool policy
ActiveTools []tools.ToolName
DeferredTools []tools.ToolName
// LLM core
LLMProvider constant.LLMProvider
LLMModel constant.Model
LLMOptions []llm.Option
// Stream selects the streaming completion path. When true the agent
// calls llm.Client.Stream and forwards each delta to the event sink
// as KindTextChunk / KindThinkingChunk; when false it calls Complete
// and emits a single KindText / KindThinking after the turn assembles.
Stream bool
}
Profile is the configuration an Agent runs under: which kind of agent it is, what system prompt it presents, and which tool *names* are exposed to the model.
Tool policy is split into two lists — this split is purely an agent-level scheduling decision; the tool packages themselves know nothing about it:
ActiveTools are constructed at agent.New() and exposed to the LLM in every Complete call. The model can invoke them with no preamble.
DeferredTools are advertised to the model by name only. They are materialized on demand via agent.LoadDeferred (driven by TOOL_SEARCH). Listing a name here is the agent's allowlist for what may be lazily loaded; a profile that omits a name forbids it entirely.
Two agents with the same Profile behave identically — the loop, dispatch, and lifecycle are shared in the Agent type; only configuration varies.
func Explore ¶
func Explore(cfg *config.Config, provider constant.LLMProvider, model constant.Model, options []llm.Option) Profile
Explore returns a read-only profile: just READ_FILE / GREP / TREE, plus WEB_SEARCH for docs lookup. Useful for sub-agents whose job is to inspect without risk of modification.
The Explore prompt is self-contained (mirrors ref TS Explore agent) and does not include EVVA.md / USER_PROFILE.md — sysprompt.ExploreAgent declares OmitMemory: true.
func General ¶
func General(cfg *config.Config, provider constant.LLMProvider, model constant.Model, options []llm.Option, toolset ...tools.ToolName) Profile
General returns a minimal profile carrying only the tool names the caller supplies as active. No deferred tools. Useful for narrow-purpose sub-agents.
Like Explore, the General prompt does not include EVVA.md / USER_PROFILE.md.
func Main ¶
func Main(cfg *config.Config, provider constant.LLMProvider, model constant.Model, skills []sysprompt.SkillRef, mem memdir.Snapshot, options []llm.Option) Profile
Main returns the full-kit profile: fs/shell/meta/skill are active; the rest are deferred (loaded on demand via TOOL_SEARCH).
The system prompt is built via sysprompt.MainAgent. Skills are advertised (Main is the only agent that surfaces them), and the EVVA.md / USER_PROFILE.md memory snapshot is threaded into the prompt under labeled headings. Callers pass an empty memdir.Snapshot{} when memory injection is not desired.
Streaming is on by default — the user-facing UX win is large and the chunk adapter falls back cleanly for providers without native streaming. Callers who want the old buffered behavior can pass WithStream(false) at agent construction.
func Plan ¶
func Plan(cfg *config.Config, provider constant.LLMProvider, model constant.Model, options []llm.Option) Profile
Plan returns a read-only profile for design-phase planning work — same tool kit as Explore (read, web_search, glob, tree, grep, json_query) plus an architect-flavored system prompt that asks for a step-by-step plan and a critical-files list. Used by the main agent during plan-mode Phase 2 (Design) to delegate per-perspective design takes.
Plan deliberately does not get edit/write/enter_plan_mode/exit_plan_mode — its job is to explore and recommend, not modify state. Like Explore, the prompt does not include EVVA.md / USER_PROFILE.md (sysprompt.PlanAgent declares OmitMemory: true).
func ResolveMainProfile ¶
func ResolveMainProfile(cfg *config.Config, reg *AgentRegistry, name string, skills []sysprompt.SkillRef, mem memdir.Snapshot, options []llm.Option) (Profile, error)
ResolveMainProfile is the single entry point for picking a main-tier Profile by persona name. Used by both bootstrap (cmd/evva/main.go) and the runtime /profile switch (Agent.SwitchProfile).
Built-in "evva" routes through Main(...) verbatim — the same full-kit active/deferred tool lists, the same memdir + skills wiring. Disk-loaded main personas route through mainProfileFromDiskAgent which uses the def's own tool lists and BuildSystemPrompt body, gated by the def's OmitMemory / AdvertiseSkills flags from meta.yml.
Empty name defaults to "evva". Unknown or non-main names return an error so callers (bootstrap fallback, the /profile picker) can surface the failure.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package attachments computes per-turn <system-reminder>-wrapped messages the agent loop prepends to the user's incoming prompts.
|
Package attachments computes per-turn <system-reminder>-wrapped messages the agent loop prepends to the user's incoming prompts. |
|
Package loader reads user-authored agent definitions from <EVVA_HOME>/agents/{name}/ at startup and turns them into sysprompt.AgentDefinition values the agent.Registry can merge with Go-defined built-ins (sysprompt.MainAgent, ExploreAgent, GeneralAgent).
|
Package loader reads user-authored agent definitions from <EVVA_HOME>/agents/{name}/ at startup and turns them into sysprompt.AgentDefinition values the agent.Registry can merge with Go-defined built-ins (sysprompt.MainAgent, ExploreAgent, GeneralAgent). |
|
Package sysprompt builds the system prompt for each kind of agent evva runs.
|
Package sysprompt builds the system prompt for each kind of agent evva runs. |