@@ -8,6 +8,7 @@ import (
88 "slices"
99 "strings"
1010 "sync"
11+ "sync/atomic"
1112 "time"
1213
1314 "github.com/charmbracelet/crush/internal/config"
@@ -67,7 +68,9 @@ type agent struct {
6768 sessions session.Service
6869 messages message.Service
6970
70− tools []tools.BaseTool
71+ toolsDone atomic.Bool
72+ tools []tools.BaseTool
73+
7174 provider provider.Provider
7275 providerID string
7376
@@ -94,46 +97,7 @@ func NewAgent(
9497) (Service, error) {
9598 ctx := context.Background()
9699 cfg := config.Get()
97− otherTools := GetMCPTools(ctx, permissions, cfg)
98− if len(lspClients) > 0 {
99− otherTools = append(otherTools, tools.NewDiagnosticsTool(lspClients))
100− }
101100
102− cwd := cfg.WorkingDir()
103− allTools := []tools.BaseTool{
104− tools.NewBashTool(permissions, cwd),
105− tools.NewDownloadTool(permissions, cwd),
106− tools.NewEditTool(lspClients, permissions, history, cwd),
107− tools.NewFetchTool(permissions, cwd),
108− tools.NewGlobTool(cwd),
109− tools.NewGrepTool(cwd),
110− tools.NewLsTool(cwd),
111− tools.NewSourcegraphTool(),
112− tools.NewViewTool(lspClients, cwd),
113− tools.NewWriteTool(lspClients, permissions, history, cwd),
114− }
115−
116− if agentCfg.ID == "coder" {
117− taskAgentCfg := config.Get().Agents["task"]
118− if taskAgentCfg.ID == "" {
119− return nil, fmt.Errorf("task agent not found in config")
120− }
121− taskAgent, err := NewAgent(taskAgentCfg, permissions, sessions, messages, history, lspClients)
122− if err != nil {
123− return nil, fmt.Errorf("failed to create task agent: %w", err)
124− }
125−
126− allTools = append(
127− allTools,
128− NewAgentTool(
129− taskAgent,
130− sessions,
131− messages,
132− ),
133− )
134− }
135−
136− allTools = append(allTools, otherTools...)
137101 providerCfg := config.Get().GetProviderForModel(agentCfg.Model)
138102 if providerCfg == nil {
139103 return nil, fmt.Errorf("provider for agent %s not found in config", agentCfg.Name)
@@ -190,15 +154,22 @@ func NewAgent(
190154 return nil, err
191155 }
192156
193− agentTools := []tools.BaseTool{}
194− if agentCfg.AllowedTools == nil {
195− agentTools = allTools
196− } else {
197− for _, tool := range allTools {
198− if slices.Contains(agentCfg.AllowedTools, tool.Name()) {
199− agentTools = append(agentTools, tool)
200− }
157+ var agentTool tools.BaseTool
158+ if agentCfg.ID == "coder" {
159+ taskAgentCfg := config.Get().Agents["task"]
160+ if taskAgentCfg.ID == "" {
161+ return nil, fmt.Errorf("task agent not found in config")
201162 }
163+ taskAgent, err := NewAgent(taskAgentCfg, permissions, sessions, messages, history, lspClients)
164+ if err != nil {
165+ return nil, fmt.Errorf("failed to create task agent: %w", err)
166+ }
167+
168+ agentTool = NewAgentTool(
169+ taskAgent,
170+ sessions,
171+ messages,
172+ )
202173 }
203174
204175 agent := &agent{
@@ -208,13 +179,55 @@ func NewAgent(
208179 providerID: string(providerCfg.ID),
209180 messages: messages,
210181 sessions: sessions,
211− tools: agentTools,
212182 titleProvider: titleProvider,
213183 summarizeProvider: summarizeProvider,
214184 summarizeProviderID: string(smallModelProviderCfg.ID),
215185 activeRequests: sync.Map{},
216186 }
217187
188+ go func() {
189+ slog.Info("Initializing agent tools", "agent", agentCfg.ID)
190+
191+ cwd := cfg.WorkingDir()
192+ allTools := []tools.BaseTool{
193+ tools.NewBashTool(permissions, cwd),
194+ tools.NewDownloadTool(permissions, cwd),
195+ tools.NewEditTool(lspClients, permissions, history, cwd),
196+ tools.NewFetchTool(permissions, cwd),
197+ tools.NewGlobTool(cwd),
198+ tools.NewGrepTool(cwd),
199+ tools.NewLsTool(cwd),
200+ tools.NewSourcegraphTool(),
201+ tools.NewViewTool(lspClients, cwd),
202+ tools.NewWriteTool(lspClients, permissions, history, cwd),
203+ }
204+
205+ mcpTools := GetMCPTools(ctx, permissions, cfg)
206+ if len(lspClients) > 0 {
207+ mcpTools = append(mcpTools, tools.NewDiagnosticsTool(lspClients))
208+ }
209+ allTools = append(allTools, mcpTools...)
210+
211+ if agentTool != nil {
212+ allTools = append(allTools, agentTool)
213+ }
214+
215+ agentTools := []tools.BaseTool{}
216+ if agentCfg.AllowedTools == nil {
217+ agentTools = allTools
218+ } else {
219+ for _, tool := range allTools {
220+ if slices.Contains(agentCfg.AllowedTools, tool.Name()) {
221+ agentTools = append(agentTools, tool)
222+ }
223+ }
224+ }
225+
226+ slog.Info("Initialized agent tools", "agent", agentCfg.ID)
227+ agent.tools = agentTools
228+ agent.toolsDone.Store(true)
229+ }()
230+
218231 return agent, nil
219232}
220233
@@ -437,6 +450,9 @@ func (a *agent) createUserMessage(ctx context.Context, sessionID, content string
437450
438451func (a *agent) streamAndHandleEvents(ctx context.Context, sessionID string, msgHistory []message.Message) (message.Message, *message.Message, error) {
439452 ctx = context.WithValue(ctx, tools.SessionIDContextKey, sessionID)
453+ if !a.toolsDone.Load() {
454+ return message.Message{}, nil, fmt.Errorf("tools not initialized yet")
455+ }
440456 eventChan := a.provider.StreamResponse(ctx, msgHistory, a.tools)
441457
442458 assistantMsg, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{