feat: add userPrompts config field for active global rules

- Add UserPrompts Prompt field to AgentConfig (same JSON format as prompt).
- Resolve userPrompts via resolvePrompt() in BuildRuntime, store in Runtime.UserPrompt.
- Prepend resolved user prompts to every user message at executeTurn start.
- Document userPrompts in data/agents/README.md.
This commit is contained in:
Ollie Agent 2026-08-15 11:52:21 +02:00
parent 80d398dd88
commit 93f021f068
3 changed files with 23 additions and 9 deletions

View File

@ -24,6 +24,7 @@ func (p *Prompt) UnmarshalJSON(data []byte) error {
type AgentConfig struct {
Prompt Prompt `json:"prompt,omitempty"`
UserPrompts Prompt `json:"userPrompts,omitempty"`
Backend string `json:"backend,omitempty"`
Model string `json:"model,omitempty"`
Tools *bool `json:"tools,omitempty"`

View File

@ -129,16 +129,17 @@ func RenderTools(infos []toolsrv.ToolInfo) string {
// agent. The agent struct stores a pointer to the active Runtime; switching
// agents replaces it atomically.
type Runtime struct {
Backend backend.Backend
ToolServer *toolsrv.Conn
Preamble *Preamble
Tools []backend.Tool
ToolMeta map[string]toolsrv.ToolInfo
Exec toolExecutor
GenParams backend.GenerationParams
MaxSteps int
Backend backend.Backend
ToolServer *toolsrv.Conn
Preamble *Preamble
Tools []backend.Tool
ToolMeta map[string]toolsrv.ToolInfo
Exec toolExecutor
GenParams backend.GenerationParams
MaxSteps int
CompactionModel string
Messages []string
UserPrompt string // resolved user prompts, prepended to each turn's input
Messages []string
}
// PreambleString returns the fully rendered system prompt.
@ -167,6 +168,7 @@ func BuildRuntime(cfg *AgentConfig, srv *toolsrv.Conn, cwd string, env []string,
}
var agentPrompt string
var userPrompt string
var genParams backend.GenerationParams
var maxSteps int
if cfg != nil {
@ -175,6 +177,11 @@ func BuildRuntime(cfg *AgentConfig, srv *toolsrv.Conn, cwd string, env []string,
} else {
agentPrompt = resolved
}
if resolved, err := resolvePrompt(cfg.UserPrompts, cwd, env); err != nil {
fmt.Fprintf(os.Stderr, "resolve user prompts: %v\n", err)
} else {
userPrompt = resolved
}
genParams = cfg.GenerationParams
maxSteps = cfg.MaxSteps
}
@ -221,6 +228,7 @@ func BuildRuntime(cfg *AgentConfig, srv *toolsrv.Conn, cwd string, env []string,
GenParams: genParams,
MaxSteps: maxSteps,
CompactionModel: compactionModel,
UserPrompt: userPrompt,
Messages: messages,
}
}

View File

@ -84,6 +84,11 @@ func (ag *Agent) Submit(ctx context.Context, input string) {
// executeTurn runs a single agent turn and returns the next prompt to execute,
// or "" if there is nothing more to do.
func (ag *Agent) executeTurn(ctx context.Context, input string) string {
// Prepend resolved user prompts (active global rules) to the user input.
if ag.runtime.UserPrompt != "" {
input = ag.runtime.UserPrompt + "\n\n" + input
}
ag.emit(Event{Role: "user", Content: input})
// Snapshot messages before this turn modifies them. Restored on context