remove maxSteps and ResetsCounter entirely

The step budget mechanism is gone. Agents run until they finish,
are interrupted by the user, or (for sub-agents) hit the timeout.

No replacement. The human is the kill switch.
This commit is contained in:
Levi Neely 2026-08-17 09:48:58 +02:00
parent da0ee4456f
commit 74ba5ae7ac
16 changed files with 27 additions and 79 deletions

View File

@ -30,8 +30,6 @@ type AgentConfig struct {
Tools *bool `json:"tools,omitempty"`
AutoLoad []string `json:"autoLoad,omitempty"`
// MaxSteps caps the number of tool-call rounds per turn. 0 means unlimited.
MaxSteps int `json:"maxSteps,omitempty"`
CompactionModel string `json:"compactionModel,omitempty"`
// SystemPrompt overrides the embedded system prompt with a file path.
SystemPrompt string `json:"systemPrompt,omitempty"`

View File

@ -179,34 +179,6 @@ func (ag *Agent) run(ctx context.Context) error {
return abort
}
// Reset step counter when an action-oriented tool succeeds.
if rt.ToolMeta != nil {
for _, r := range results {
if !r.IsError && rt.ToolMeta[r.Name].ResetsCounter {
step = 0
break
}
}
}
// Step budget warnings.
if rt.MaxSteps > 0 {
halfBudget := rt.MaxSteps / 2
if step == halfBudget {
h.update(backend.Message{
Role: "user",
Content: fmt.Sprintf("<system-step-budget-warning>\nYou have used %d/%d research steps without taking action. Consider making progress — write code, edit files, or run commands. Action tools reset this counter.\n</system-step-budget-warning>", step, rt.MaxSteps),
}, nil)
} else if step >= rt.MaxSteps-1 {
ag.emit(Event{Role: "maxsteps", Content: fmt.Sprintf("%d", step+1)})
h.update(backend.Message{
Role: "user",
Content: fmt.Sprintf("<system-step-budget-stop>\nStep budget exhausted (%d/%d steps used). Stop calling tools. Summarize what you have done and what remains, then stop.\n</system-step-budget-stop>", step+1, rt.MaxSteps),
}, nil)
break
}
}
_, compactErr := ag.autoCompact(ctx)
if compactErr != nil {
ag.emit(Event{Role: "error", Content: compactErr.Error()})

View File

@ -145,7 +145,6 @@ type Runtime struct {
ToolMeta map[string]protocol.ToolInfo
Exec toolExecutor
GenParams backend.GenerationParams
MaxSteps int
CompactionModel string
UserPrompt string // resolved user prompts, prepended to each turn's input
Messages []string
@ -179,7 +178,6 @@ func BuildRuntime(cfg *AgentConfig, srv *toolclient.ToolsrvConn, cwd string, env
var agentPrompt string
var userPrompt string
var genParams backend.GenerationParams
var maxSteps int
if cfg != nil {
if resolved, err := resolvePrompt(cfg.Prompt, cwd, env); err != nil {
fmt.Fprintf(os.Stderr, "resolve prompt: %v\n", err)
@ -192,7 +190,6 @@ func BuildRuntime(cfg *AgentConfig, srv *toolclient.ToolsrvConn, cwd string, env
userPrompt = resolved
}
genParams = cfg.GenerationParams
maxSteps = cfg.MaxSteps
}
genParams.CWD = cwd
@ -235,7 +232,6 @@ func BuildRuntime(cfg *AgentConfig, srv *toolclient.ToolsrvConn, cwd string, env
Exec: exec,
Preamble: preamble,
GenParams: genParams,
MaxSteps: maxSteps,
CompactionModel: compactionModel,
UserPrompt: userPrompt,
Messages: messages,

View File

@ -27,7 +27,6 @@
"lsp_rename",
"lsp_completion"
],
"maxSteps": 25,
"temperature": 0.5,
"maxTokens": 16384
}

View File

@ -41,7 +41,6 @@
],
"backend": "openrouter",
"model": "deepseek/deepseek-v4-flash",
"maxSteps": 25,
"temperature": 0.4,
"maxTokens": 16384
}

View File

@ -26,7 +26,6 @@
"code_rewrite",
"code_dependencies"
],
"maxSteps": 40,
"temperature": 0.3,
"maxTokens": 16384
}

View File

@ -15,7 +15,6 @@
"memory_recall",
"memory_remember"
],
"maxSteps": 20,
"temperature": 0.3,
"maxTokens": 16384
}

View File

@ -28,6 +28,5 @@
"code_dependencies"
],
"temperature": 0.3,
"maxTokens": 8192,
"maxSteps": 30
"maxTokens": 8192
}

View File

@ -23,7 +23,6 @@
"lsp_rename",
"lsp_completion"
],
"maxSteps": 5,
"temperature": 0.3,
"maxTokens": 4096
}

View File

@ -17,7 +17,6 @@
"memory_recall",
"memory_remember"
],
"maxSteps": 20,
"temperature": 0.3,
"maxTokens": 8192
}

View File

@ -17,7 +17,6 @@
"file_grep",
"file_write"
],
"maxSteps": 30,
"temperature": 0.3,
"maxTokens": 8192
}

View File

@ -1,7 +1,6 @@
{
"description": "Replace text in a file. Has fuzzy matching (whitespace/indent flexible).",
"outputFormat": "diff",
"resetsCounter": true,
"prompt": "## file_edit\n\nReplace text in a file. Has fuzzy matching (whitespace/indent flexible).\n\n**Args**: `path`, `old_string`, `new_string` (required); `replace_all` (optional)\n\n```\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\")\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\", replace_all=\"true\")\n```\n\n**Constraints**: Absolute paths only. Errors if `old_string` matches multiple locations \u2014 add surrounding context to disambiguate, or use `replace_all=true`.",
"args": {
"type": "object",

View File

@ -1,7 +1,6 @@
{
"description": "Create or overwrite a file. Produces a unified diff.",
"outputFormat": "diff",
"resetsCounter": true,
"prompt": "## file_write\n\nCreate or overwrite a file. Produces a unified diff.\n\n**Args**: `[path, content]`\n\n```\nfile_write(path=\"<ABSOLUTE_PATH_FROM_PWD>\", content=\"file content here\")\n```\n\n**Constraints**: Absolute paths only. Parent directory must exist.",
"args": {
"type": "object",

View File

@ -1,6 +1,5 @@
{
"description": "Execute a single bash command in a sandboxed environment.",
"resetsCounter": true,
"prompt": "Execute a single bash command in a sandboxed environment.\n\nUsage: {\"cmd\": \"your command here\"}\n\nSandbox prevents dangerous operations. Use for computation, builds, scripting.\ntimeout applies to each call (default: 30s). A non-zero exit is an error.",
"args": {
"type": "object",

View File

@ -19,7 +19,6 @@ type MetaFile struct {
Scope string `json:"scope,omitempty"`
OutputFormat string `json:"outputFormat,omitempty"`
Cmd string `json:"cmd,omitempty"`
ResetsCounter bool `json:"resetsCounter,omitempty"`
Variants []Variant `json:"variants,omitempty"`
}
@ -35,7 +34,6 @@ type Variant struct {
Scope string `json:"scope,omitempty"`
OutputFormat string `json:"outputFormat,omitempty"`
Cmd string `json:"cmd,omitempty"`
ResetsCounter bool `json:"resetsCounter,omitempty"`
}
// LoadMetaFile reads and parses a .meta sidecar file for the given tool name.
@ -86,9 +84,6 @@ func (m *MetaFile) Resolve() *MetaFile {
if v.Scope != "" {
resolved.Scope = v.Scope
}
if v.ResetsCounter {
resolved.ResetsCounter = true
}
if v.Cmd != "" {
resolved.Cmd = v.Cmd
}
@ -184,7 +179,6 @@ func ToolInfoFromMeta(name string, m *MetaFile) protocol.ToolInfo {
Tier: tier,
Scope: resolved.Scope,
OutputFormat: resolved.OutputFormat,
ResetsCounter: resolved.ResetsCounter,
}
}

View File

@ -13,7 +13,6 @@ type ToolInfo struct {
Tier string
Scope string
OutputFormat string
ResetsCounter bool
}
// ToolResult is the structured result from a tool execution.