@@ -5,20 +5,35 @@ import (
55 "fmt"
66 "log/slog"
77 "math/rand"
8- "sync/atomic "
8+ "sync"
99
1010 "github.com/docker/cagent/pkg/memorymanager"
1111 "github.com/docker/cagent/pkg/model/provider"
1212 "github.com/docker/cagent/pkg/tools"
1313)
1414
15+ // ToolSetStartupError wraps toolset startup failures with context
16+ type ToolSetStartupError struct {
17+ Err error
18+ Index int
19+ }
20+
21+ func (e * ToolSetStartupError ) Error () string {
22+ return fmt .Sprintf ("failed to start toolset: %v" , e .Err )
23+ }
24+
25+ func (e * ToolSetStartupError ) Unwrap () error {
26+ return e .Err
27+ }
28+
1529// Agent represents an AI agent
1630type Agent struct {
1731 name string
1832 description string
1933 instruction string
2034 toolsets []tools.ToolSet
21- toolsetsStarted atomic.Bool
35+ startedToolsets map [tools.ToolSet ]bool
36+ toolsetsMutex sync.RWMutex
2237 models []provider.Provider
2338 subAgents []* Agent
2439 parents []* Agent
@@ -31,8 +46,9 @@ type Agent struct {
3146// New creates a new agent
3247func New (name , prompt string , opts ... Opt ) * Agent {
3348 agent := & Agent {
34- name : name ,
35- instruction : prompt ,
49+ name : name ,
50+ instruction : prompt ,
51+ startedToolsets : make (map [tools.ToolSet ]bool ),
3652 }
3753
3854 for _ , opt := range opts {
@@ -129,31 +145,46 @@ func (a *Agent) ToolSets() []tools.ToolSet {
129145}
130146
131147func (a * Agent ) ensureToolSetsAreStarted (ctx context.Context ) error {
132- if a .toolsetsStarted .Load () {
133- return nil
134- }
148+ a .toolsetsMutex .Lock ()
149+ defer a .toolsetsMutex .Unlock ()
150+
151+ for i , toolSet := range a .toolsets {
152+ // Skip if toolset is already started
153+ if a .startedToolsets [toolSet ] {
154+ continue
155+ }
135156
136- for _ , toolSet := range a .toolsets {
137157 if err := toolSet .Start (ctx ); err != nil {
138- return fmt .Errorf ("failed to start toolset: %w" , err )
158+ return & ToolSetStartupError {
159+ Err : err ,
160+ Index : i ,
161+ }
139162 }
163+
164+ // Mark toolset as started
165+ a .startedToolsets [toolSet ] = true
140166 }
141167
142- a .toolsetsStarted .Store (true )
143168 return nil
144169}
145170
146171func (a * Agent ) StopToolSets () error {
147- if ! a .toolsetsStarted .Load () {
148- return nil
149- }
172+ a .toolsetsMutex .Lock ()
173+ defer a .toolsetsMutex .Unlock ()
150174
151175 for _ , toolSet := range a .toolsets {
176+ // Only stop toolsets that are marked as started
177+ if ! a .startedToolsets [toolSet ] {
178+ continue
179+ }
180+
152181 if err := toolSet .Stop (); err != nil {
153182 return fmt .Errorf ("failed to stop toolset: %w" , err )
154183 }
184+
185+ // Mark toolset as stopped
186+ a .startedToolsets [toolSet ] = false
155187 }
156188
157- a .toolsetsStarted .Store (false )
158189 return nil
159190}
0 commit comments