Skip to content

Commit 3a3e75e

Browse files
committed
feat: make maxOldToolCallTokens configurable in agent YAML
Add max_tool_call_tokens configuration option to control how much historical tool call content is retained in the context. This helps manage context size in long-running sessions. Changes: - Add maxOldToolCallTokens field to AgentConfig (pkg/config/latest/types.go) - Update JSON schema with new max_old_tool_call_tokens property - Add maxOldToolCallTokens field and getter to Agent struct - Add maxOldToolCallTokens field to Session struct - Update GetMessages() to use configured value or fall back to DefaultMaxOldToolCallTokens (40000) - Propagate maxOldToolCallTokens through all session creation points: - A2A adapter - ACP agent - MCP server - Runtime agent delegation (transfer_task, sub-sessions) - HTTP/API server session manager Configuration semantics: - Not set or 0: Use default (40000 tokens) - Positive value: Use that specific limit - -1: Unlimited (no truncation) When max_old_tool_call_tokens is exceeded, older tool calls have their content replaced with "[content truncated]" to keep context size manageable. Tokens are approximated as string_length/4. Assisted-By: docker-agent Signed-off-by: Guillaume Tardif <guillaume.tardif@gmail.com>
1 parent b729670 commit 3a3e75e

File tree

12 files changed

+62
-7
lines changed

12 files changed

+62
-7
lines changed

agent-schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@
187187
"description": "Maximum consecutive identical tool calls before the agent is terminated. Prevents degenerate loops. 0 uses the default of 5.",
188188
"minimum": 0
189189
},
190+
"max_old_tool_call_tokens": {
191+
"type": "integer",
192+
"description": "Maximum number of tokens to keep from old tool call arguments and results. Older tool calls beyond this budget will have their content replaced with a placeholder. Tokens are approximated as len/4. Set to -1 to disable truncation (unlimited tool content). Default: 40000.",
193+
"minimum": -1
194+
},
190195
"num_history_items": {
191196
"type": "integer",
192197
"description": "Number of history items to keep",

cmd/root/run.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/spf13/cobra"
1818
"go.opentelemetry.io/otel"
1919

20+
"github.com/docker/docker-agent/pkg/agent"
2021
"github.com/docker/docker-agent/pkg/app"
2122
"github.com/docker/docker-agent/pkg/cli"
2223
"github.com/docker/docker-agent/pkg/config"
@@ -404,7 +405,7 @@ func (f *runExecFlags) createLocalRuntimeAndSession(ctx context.Context, loadRes
404405
slog.Debug("Loaded existing session", "session_id", resolvedID, "session_ref", f.sessionID, "agent", f.agentName)
405406
} else {
406407
wd, _ := os.Getwd()
407-
sess = session.New(f.buildSessionOpts(agent.MaxIterations(), wd)...)
408+
sess = session.New(f.buildSessionOpts(agent, wd)...)
408409
// Session is stored lazily on first UpdateSession call (when content is added)
409410
// This avoids creating empty sessions in the database
410411
slog.Debug("Using local runtime", "agent", f.agentName)
@@ -494,9 +495,11 @@ func (f *runExecFlags) buildAppOpts(args []string) ([]app.Opt, error) {
494495
// buildSessionOpts returns the canonical set of session options derived from
495496
// CLI flags and agent configuration. Both the initial session and spawned
496497
// sessions use this method so their options never drift apart.
497-
func (f *runExecFlags) buildSessionOpts(maxIterations int, workingDir string) []session.Opt {
498+
func (f *runExecFlags) buildSessionOpts(agent *agent.Agent, workingDir string) []session.Opt {
498499
return []session.Opt{
499-
session.WithMaxIterations(maxIterations),
500+
session.WithMaxIterations(agent.MaxIterations()),
501+
session.WithMaxConsecutiveToolCalls(agent.MaxConsecutiveToolCalls()),
502+
session.WithMaxOldToolCallTokens(agent.MaxOldToolCallTokens()),
500503
session.WithToolsApproved(f.autoApprove),
501504
session.WithHideToolResults(f.hideToolResults),
502505
session.WithWorkingDir(workingDir),
@@ -543,7 +546,7 @@ func (f *runExecFlags) createSessionSpawner(agentSource config.Source, sessStore
543546
}
544547

545548
// Create a new session
546-
newSess := session.New(f.buildSessionOpts(agent.MaxIterations(), workingDir)...)
549+
newSess := session.New(f.buildSessionOpts(agent, workingDir)...)
547550

548551
// Create cleanup function
549552
cleanup := func() {

pkg/a2a/adapter.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ func runDockerAgent(ctx agent.InvocationContext, t *team.Team, agentName string,
4747
session.WithUserMessage(message),
4848
session.WithMaxIterations(a.MaxIterations()),
4949
session.WithMaxConsecutiveToolCalls(a.MaxConsecutiveToolCalls()),
50+
session.WithMaxOldToolCallTokens(a.MaxOldToolCallTokens()),
5051
session.WithToolsApproved(true),
5152
)
5253

pkg/acp/agent.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func (a *Agent) NewSession(ctx context.Context, params acp.NewSessionRequest) (a
154154
sessOpts := []session.Opt{
155155
session.WithMaxIterations(rootAgent.MaxIterations()),
156156
session.WithMaxConsecutiveToolCalls(rootAgent.MaxConsecutiveToolCalls()),
157+
session.WithMaxOldToolCallTokens(rootAgent.MaxOldToolCallTokens()),
157158
}
158159
if workingDir != "" {
159160
sessOpts = append(sessOpts, session.WithWorkingDir(workingDir))

pkg/agent/agent.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type Agent struct {
3434
addDescriptionParameter bool
3535
maxIterations int
3636
maxConsecutiveToolCalls int
37+
maxOldToolCallTokens int
3738
numHistoryItems int
3839
addPromptFiles []string
3940
tools []tools.Tool
@@ -81,6 +82,10 @@ func (a *Agent) MaxConsecutiveToolCalls() int {
8182
return a.maxConsecutiveToolCalls
8283
}
8384

85+
func (a *Agent) MaxOldToolCallTokens() int {
86+
return a.maxOldToolCallTokens
87+
}
88+
8489
func (a *Agent) NumHistoryItems() int {
8590
return a.numHistoryItems
8691
}

pkg/agent/opts.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ func WithMaxConsecutiveToolCalls(n int) Opt {
138138
}
139139
}
140140

141+
// WithMaxOldToolCallTokens sets the maximum token budget for old tool call content.
142+
// Set to -1 to disable truncation (unlimited tool content).
143+
// Set to 0 to use the default (40000).
144+
func WithMaxOldToolCallTokens(n int) Opt {
145+
return func(a *Agent) {
146+
a.maxOldToolCallTokens = n
147+
}
148+
}
149+
141150
func WithNumHistoryItems(numHistoryItems int) Opt {
142151
return func(a *Agent) {
143152
a.numHistoryItems = numHistoryItems

pkg/config/latest/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ type AgentConfig struct {
252252
AddDescriptionParameter bool `json:"add_description_parameter,omitempty"`
253253
MaxIterations int `json:"max_iterations,omitempty"`
254254
MaxConsecutiveToolCalls int `json:"max_consecutive_tool_calls,omitempty"`
255+
MaxOldToolCallTokens int `json:"max_old_tool_call_tokens,omitempty"`
255256
NumHistoryItems int `json:"num_history_items,omitempty"`
256257
AddPromptFiles []string `json:"add_prompt_files,omitempty" yaml:"add_prompt_files,omitempty"`
257258
Commands types.Commands `json:"commands,omitempty"`

pkg/mcp/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ func CreateToolHandler(t *team.Team, agentName string) func(context.Context, *mc
161161
session.WithTitle("MCP tool call"),
162162
session.WithMaxIterations(ag.MaxIterations()),
163163
session.WithMaxConsecutiveToolCalls(ag.MaxConsecutiveToolCalls()),
164+
session.WithMaxOldToolCallTokens(ag.MaxOldToolCallTokens()),
164165
session.WithUserMessage(input.Message),
165166
session.WithToolsApproved(true),
166167
)

pkg/runtime/agent_delegation.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ func newSubSession(parent *session.Session, cfg SubSessionConfig, childAgent *ag
106106
session.WithImplicitUserMessage(userMsg),
107107
session.WithMaxIterations(childAgent.MaxIterations()),
108108
session.WithMaxConsecutiveToolCalls(childAgent.MaxConsecutiveToolCalls()),
109+
session.WithMaxOldToolCallTokens(childAgent.MaxOldToolCallTokens()),
109110
session.WithTitle(cfg.Title),
110111
session.WithToolsApproved(cfg.ToolsApproved),
111112
session.WithSendUserMessage(false),

pkg/server/session_manager.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ func (sm *SessionManager) CreateSession(ctx context.Context, sessionTemplate *se
7777
opts = append(opts,
7878
session.WithMaxIterations(sessionTemplate.MaxIterations),
7979
session.WithMaxConsecutiveToolCalls(sessionTemplate.MaxConsecutiveToolCalls),
80+
session.WithMaxOldToolCallTokens(sessionTemplate.MaxOldToolCallTokens),
8081
session.WithToolsApproved(sessionTemplate.ToolsApproved),
8182
)
8283

@@ -347,6 +348,7 @@ func (sm *SessionManager) runtimeForSession(ctx context.Context, sess *session.S
347348
}
348349
sess.MaxIterations = agent.MaxIterations()
349350
sess.MaxConsecutiveToolCalls = agent.MaxConsecutiveToolCalls()
351+
sess.MaxOldToolCallTokens = agent.MaxOldToolCallTokens()
350352

351353
opts := []runtime.Opt{
352354
runtime.WithCurrentAgent(currentAgent),

0 commit comments

Comments
 (0)