Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions pkg/config/latest/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,26 @@ type ProviderConfig struct {

// AgentConfig represents a single agent configuration
type AgentConfig struct {
Name string
Model string `json:"model,omitempty"`
Description string `json:"description,omitempty"`
WelcomeMessage string `json:"welcome_message,omitempty"`
Toolsets []Toolset `json:"toolsets,omitempty"`
Instruction string `json:"instruction,omitempty"`
SubAgents []string `json:"sub_agents,omitempty"`
Handoffs []string `json:"handoffs,omitempty"`
RAG []string `json:"rag,omitempty"`
AddDate bool `json:"add_date,omitempty"`
AddEnvironmentInfo bool `json:"add_environment_info,omitempty"`
CodeModeTools bool `json:"code_mode_tools,omitempty"`
MaxIterations int `json:"max_iterations,omitempty"`
NumHistoryItems int `json:"num_history_items,omitempty"`
AddPromptFiles []string `json:"add_prompt_files,omitempty" yaml:"add_prompt_files,omitempty"`
Commands types.Commands `json:"commands,omitempty"`
StructuredOutput *StructuredOutput `json:"structured_output,omitempty"`
Skills *bool `json:"skills,omitempty"`
Hooks *HooksConfig `json:"hooks,omitempty"`
Name string
Model string `json:"model,omitempty"`
Description string `json:"description,omitempty"`
WelcomeMessage string `json:"welcome_message,omitempty"`
Toolsets []Toolset `json:"toolsets,omitempty"`
Instruction string `json:"instruction,omitempty"`
SubAgents []string `json:"sub_agents,omitempty"`
Handoffs []string `json:"handoffs,omitempty"`
RAG []string `json:"rag,omitempty"`
AddDate bool `json:"add_date,omitempty"`
AddEnvironmentInfo bool `json:"add_environment_info,omitempty"`
CodeModeTools bool `json:"code_mode_tools,omitempty"`
AddDescriptionParameter bool `json:"add_description_parameter,omitempty"`
MaxIterations int `json:"max_iterations,omitempty"`
NumHistoryItems int `json:"num_history_items,omitempty"`
AddPromptFiles []string `json:"add_prompt_files,omitempty" yaml:"add_prompt_files,omitempty"`
Commands types.Commands `json:"commands,omitempty"`
StructuredOutput *StructuredOutput `json:"structured_output,omitempty"`
Skills *bool `json:"skills,omitempty"`
Hooks *HooksConfig `json:"hooks,omitempty"`
}

// ModelConfig represents the configuration for a model
Expand Down
6 changes: 6 additions & 0 deletions pkg/teamloader/teamloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ func getToolsForAgent(ctx context.Context, a *latest.AgentConfig, parentDir stri
}
}

// Apply friendly tools wrapper if enabled
if a.AddDescriptionParameter {
wrapped = tools.NewDescriptionToolSet(wrapped)
}

toolSets = append(toolSets, wrapped)
}

Expand Down Expand Up @@ -351,6 +356,7 @@ func createRAGToolsForAgent(agentConfig *latest.AgentConfig, allManagers map[str

// Create a separate tool for this RAG source
ragTool := builtin.NewRAGTool(mgr, toolName)

ragTools = append(ragTools, ragTool)

slog.Debug("Created RAG tool for agent",
Expand Down
4 changes: 4 additions & 0 deletions pkg/tools/builtin/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ func (t *FilesystemTool) Tools(context.Context) ([]tools.Tool, error) {
Annotations: tools.ToolAnnotations{
Title: "Edit",
},
AddDescriptionParameter: true,
},
{
Name: ToolNameListDirectory,
Expand All @@ -219,6 +220,7 @@ func (t *FilesystemTool) Tools(context.Context) ([]tools.Tool, error) {
ReadOnlyHint: true,
Title: "List Directory",
},
AddDescriptionParameter: true,
},
{
Name: ToolNameReadFile,
Expand Down Expand Up @@ -256,6 +258,7 @@ func (t *FilesystemTool) Tools(context.Context) ([]tools.Tool, error) {
ReadOnlyHint: true,
Title: "Search Files Content",
},
AddDescriptionParameter: true,
},
{
Name: ToolNameWriteFile,
Expand All @@ -267,6 +270,7 @@ func (t *FilesystemTool) Tools(context.Context) ([]tools.Tool, error) {
Annotations: tools.ToolAnnotations{
Title: "Write",
},
AddDescriptionParameter: true,
},
}, nil
}
Expand Down
73 changes: 39 additions & 34 deletions pkg/tools/builtin/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,48 +422,53 @@ func (t *ShellTool) Tools(context.Context) ([]tools.Tool, error) {

return []tools.Tool{
{
Name: ToolNameShell,
Category: "shell",
Description: shellDesc,
Parameters: tools.MustSchemaFor[RunShellArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.RunShell),
Annotations: tools.ToolAnnotations{Title: "Shell"},
Name: ToolNameShell,
Category: "shell",
Description: shellDesc,
Parameters: tools.MustSchemaFor[RunShellArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.RunShell),
Annotations: tools.ToolAnnotations{Title: "Shell"},
AddDescriptionParameter: true,
},
{
Name: ToolNameRunShellBackground,
Category: "shell",
Description: `Starts a shell command in the background and returns immediately with a job ID. Use this for long-running processes like servers, watches, or any command that should run while other tasks are performed.`,
Parameters: tools.MustSchemaFor[RunShellBackgroundArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.RunShellBackground),
Annotations: tools.ToolAnnotations{Title: "Background Job"},
Name: ToolNameRunShellBackground,
Category: "shell",
Description: `Starts a shell command in the background and returns immediately with a job ID. Use this for long-running processes like servers, watches, or any command that should run while other tasks are performed.`,
Parameters: tools.MustSchemaFor[RunShellBackgroundArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.RunShellBackground),
Annotations: tools.ToolAnnotations{Title: "Background Job"},
AddDescriptionParameter: true,
},
{
Name: ToolNameListBackgroundJobs,
Category: "shell",
Description: `Lists all background jobs with their status, runtime, and other information.`,
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.ListBackgroundJobs),
Annotations: tools.ToolAnnotations{Title: "List Background Jobs", ReadOnlyHint: true},
Name: ToolNameListBackgroundJobs,
Category: "shell",
Description: `Lists all background jobs with their status, runtime, and other information.`,
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.ListBackgroundJobs),
Annotations: tools.ToolAnnotations{Title: "List Background Jobs", ReadOnlyHint: true},
AddDescriptionParameter: true,
},
{
Name: ToolNameViewBackgroundJob,
Category: "shell",
Description: `Views the output and status of a specific background job by job ID.`,
Parameters: tools.MustSchemaFor[ViewBackgroundJobArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.ViewBackgroundJob),
Annotations: tools.ToolAnnotations{Title: "View Background Job Output", ReadOnlyHint: true},
Name: ToolNameViewBackgroundJob,
Category: "shell",
Description: `Views the output and status of a specific background job by job ID.`,
Parameters: tools.MustSchemaFor[ViewBackgroundJobArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.ViewBackgroundJob),
Annotations: tools.ToolAnnotations{Title: "View Background Job Output", ReadOnlyHint: true},
AddDescriptionParameter: true,
},
{
Name: ToolNameStopBackgroundJob,
Category: "shell",
Description: `Stops a running background job by job ID. The process and all its child processes will be terminated.`,
Parameters: tools.MustSchemaFor[StopBackgroundJobArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.StopBackgroundJob),
Annotations: tools.ToolAnnotations{Title: "Stop Background Job"},
Name: ToolNameStopBackgroundJob,
Category: "shell",
Description: `Stops a running background job by job ID. The process and all its child processes will be terminated.`,
Parameters: tools.MustSchemaFor[StopBackgroundJobArgs](),
OutputSchema: tools.MustSchemaFor[string](),
Handler: tools.NewHandler(t.handler.StopBackgroundJob),
Annotations: tools.ToolAnnotations{Title: "Stop Background Job"},
AddDescriptionParameter: true,
},
}, nil
}
Expand Down
97 changes: 97 additions & 0 deletions pkg/tools/description.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package tools

import (
"context"
"encoding/json"
)

const (
// DescriptionParam is the parameter name for the description
DescriptionParam = "description"
)

// DescriptionToolSet wraps a ToolSet and adds a "description" parameter to all tools.
// This allows the LLM to provide context about what it's doing with each tool call.
type DescriptionToolSet struct {
inner ToolSet
}

// NewDescriptionToolSet creates a new DescriptionToolSet wrapping the given ToolSet.
func NewDescriptionToolSet(inner ToolSet) *DescriptionToolSet {
return &DescriptionToolSet{inner: inner}
}

func (f *DescriptionToolSet) Tools(ctx context.Context) ([]Tool, error) {
tools, err := f.inner.Tools(ctx)
if err != nil {
return nil, err
}

result := make([]Tool, len(tools))
for i, tool := range tools {
result[i] = f.addDescriptionParam(tool)
}
return result, nil
}

func (f *DescriptionToolSet) Instructions() string {
return f.inner.Instructions()
}

func (f *DescriptionToolSet) Start(ctx context.Context) error {
return f.inner.Start(ctx)
}

func (f *DescriptionToolSet) Stop(ctx context.Context) error {
return f.inner.Stop(ctx)
}

func (f *DescriptionToolSet) SetElicitationHandler(handler ElicitationHandler) {
f.inner.SetElicitationHandler(handler)
}

func (f *DescriptionToolSet) SetOAuthSuccessHandler(handler func()) {
f.inner.SetOAuthSuccessHandler(handler)
}

func (f *DescriptionToolSet) SetManagedOAuth(managed bool) {
f.inner.SetManagedOAuth(managed)
}

func (f *DescriptionToolSet) addDescriptionParam(tool Tool) Tool {
if !tool.AddDescriptionParameter {
return tool
}

schema, err := SchemaToMap(tool.Parameters)
if err != nil {
return tool
}

properties, ok := schema["properties"].(map[string]any)
if !ok {
properties = make(map[string]any)
schema["properties"] = properties
}

properties[DescriptionParam] = map[string]any{
"type": "string",
"description": "A brief, human-readable description of what this tool call is doing",
}

tool.Parameters = schema
return tool
}

// ExtractDescription extracts the description from tool call arguments.
func ExtractDescription(arguments string) string {
var args map[string]any
if err := json.Unmarshal([]byte(arguments), &args); err != nil {
return ""
}

if desc, ok := args[DescriptionParam].(string); ok {
return desc
}
return ""
}
Loading