@@ -8,6 +8,7 @@ import (
13 "github.com/charmbracelet/crush/internal/config"
14 "github.com/charmbracelet/crush/internal/config"
@@ -67,7 +68,9 @@ type agent struct {
67 sessions session.Service
68 sessions session.Service
68 messages message.Service
69 messages message.Service
71+ toolsDone atomic.Bool
70− tools []tools.BaseTool
72+ tools []tools.BaseTool
71 provider provider.Provider
74 provider provider.Provider
72 providerID string
75 providerID string
@@ -94,46 +97,7 @@ func NewAgent(
94) (Service, error) {
97) (Service, error) {
95 ctx := context.Background()
98 ctx := context.Background()
96 cfg := config.Get()
99 cfg := config.Get()
97− otherTools := GetMCPTools(ctx, permissions, cfg)
98− if len(lspClients) > 0 {
99− otherTools = append(otherTools, tools.NewDiagnosticsTool(lspClients))
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),
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")
121− taskAgent, err := NewAgent(taskAgentCfg, permissions, sessions, messages, history, lspClients)
123− return nil, fmt.Errorf("failed to create task agent: %w", err)
136− allTools = append(allTools, otherTools...)
137 providerCfg := config.Get().GetProviderForModel(agentCfg.Model)
101 providerCfg := config.Get().GetProviderForModel(agentCfg.Model)
138 if providerCfg == nil {
102 if providerCfg == nil {
139 return nil, fmt.Errorf("provider for agent %s not found in config", agentCfg.Name)
103 return nil, fmt.Errorf("provider for agent %s not found in config", agentCfg.Name)
@@ -190,15 +154,22 @@ func NewAgent(
190 return nil, err
154 return nil, err
193− agentTools := []tools.BaseTool{}
157+ var agentTool tools.BaseTool
194− if agentCfg.AllowedTools == nil {
158+ if agentCfg.ID == "coder" {
195− agentTools = allTools
159+ taskAgentCfg := config.Get().Agents["task"]
196− } else {
160+ if taskAgentCfg.ID == "" {
197− for _, tool := range allTools {
161+ return nil, fmt.Errorf("task agent not found in config")
198− if slices.Contains(agentCfg.AllowedTools, tool.Name()) {
199− agentTools = append(agentTools, tool)
163+ taskAgent, err := NewAgent(taskAgentCfg, permissions, sessions, messages, history, lspClients)
165+ return nil, fmt.Errorf("failed to create task agent: %w", err)
168+ agentTool = NewAgentTool(
204 agent := &agent{
175 agent := &agent{
@@ -208,13 +179,55 @@ func NewAgent(
208 providerID: string(providerCfg.ID),
179 providerID: string(providerCfg.ID),
209 messages: messages,
180 messages: messages,
210 sessions: sessions,
181 sessions: sessions,
212 titleProvider: titleProvider,
182 titleProvider: titleProvider,
213 summarizeProvider: summarizeProvider,
183 summarizeProvider: summarizeProvider,
214 summarizeProviderID: string(smallModelProviderCfg.ID),
184 summarizeProviderID: string(smallModelProviderCfg.ID),
215 activeRequests: sync.Map{},
185 activeRequests: sync.Map{},
189+ slog.Info("Initializing agent tools", "agent", agentCfg.ID)
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),
205+ mcpTools := GetMCPTools(ctx, permissions, cfg)
206+ if len(lspClients) > 0 {
207+ mcpTools = append(mcpTools, tools.NewDiagnosticsTool(lspClients))
209+ allTools = append(allTools, mcpTools...)
211+ if agentTool != nil {
212+ allTools = append(allTools, agentTool)
215+ agentTools := []tools.BaseTool{}
216+ if agentCfg.AllowedTools == nil {
217+ agentTools = allTools
219+ for _, tool := range allTools {
220+ if slices.Contains(agentCfg.AllowedTools, tool.Name()) {
221+ agentTools = append(agentTools, tool)
226+ slog.Info("Initialized agent tools", "agent", agentCfg.ID)
227+ agent.tools = agentTools
228+ agent.toolsDone.Store(true)
218 return agent, nil
231 return agent, nil
@@ -437,6 +450,9 @@ func (a *agent) createUserMessage(ctx context.Context, sessionID, content string
438func (a *agent) streamAndHandleEvents(ctx context.Context, sessionID string, msgHistory []message.Message) (message.Message, *message.Message, error) {
451func (a *agent) streamAndHandleEvents(ctx context.Context, sessionID string, msgHistory []message.Message) (message.Message, *message.Message, error) {
439 ctx = context.WithValue(ctx, tools.SessionIDContextKey, sessionID)
452 ctx = context.WithValue(ctx, tools.SessionIDContextKey, sessionID)
453+ if !a.toolsDone.Load() {
454+ return message.Message{}, nil, fmt.Errorf("tools not initialized yet")
440 eventChan := a.provider.StreamResponse(ctx, msgHistory, a.tools)
456 eventChan := a.provider.StreamResponse(ctx, msgHistory, a.tools)
442 assistantMsg, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{
458 assistantMsg, err := a.messages.Create(ctx, sessionID, message.CreateMessageParams{