on main help sign in
fix(tools): drastically reduce tool call description lengths
f78baedChristian Rocha
internal/agent/agent_tool.go+1−1
@@ -39,7 +39,7 @@ func (c *coordinator) agentTool(ctx context.Context) (fantasy.AgentTool, error)
39 }
39 }
40 return fantasy.NewParallelAgentTool(
40 return fantasy.NewParallelAgentTool(
41 AgentToolName,
41 AgentToolName,
42− string(agentToolDescription),
42+ tools.FirstLineDescription(agentToolDescription),
43 func(ctx context.Context, params AgentParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
43 func(ctx context.Context, params AgentParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
44 if params.Prompt == "" {
44 if params.Prompt == "" {
45 return fantasy.NewTextErrorResponse("prompt is required"), nil
45 return fantasy.NewTextErrorResponse("prompt is required"), nil
internal/agent/agentic_fetch_tool.go+1−1
@@ -65,7 +65,7 @@ func (c *coordinator) agenticFetchTool(_ context.Context, client *http.Client) (
65
65
66 return fantasy.NewParallelAgentTool(
66 return fantasy.NewParallelAgentTool(
67 tools.AgenticFetchToolName,
67 tools.AgenticFetchToolName,
68− string(agenticFetchToolDescription),
68+ tools.FirstLineDescription(agenticFetchToolDescription),
69 func(ctx context.Context, params tools.AgenticFetchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
69 func(ctx context.Context, params tools.AgenticFetchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
70 validationResult, err := validateAgenticFetchParams(ctx, params)
70 validationResult, err := validateAgenticFetchParams(ctx, params)
71 if err != nil {
71 if err != nil {
internal/agent/tools/diagnostics.go+1−1
@@ -27,7 +27,7 @@ var diagnosticsDescription []byte
27func NewDiagnosticsTool(lspManager *lsp.Manager) fantasy.AgentTool {
27func NewDiagnosticsTool(lspManager *lsp.Manager) fantasy.AgentTool {
28 return fantasy.NewAgentTool(
28 return fantasy.NewAgentTool(
29 DiagnosticsToolName,
29 DiagnosticsToolName,
30− string(diagnosticsDescription),
30+ FirstLineDescription(diagnosticsDescription),
31 func(ctx context.Context, params DiagnosticsParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
31 func(ctx context.Context, params DiagnosticsParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
32 if lspManager.Clients().Len() == 0 {
32 if lspManager.Clients().Len() == 0 {
33 return fantasy.NewTextErrorResponse("no LSP clients available"), nil
33 return fantasy.NewTextErrorResponse("no LSP clients available"), nil
internal/agent/tools/download.go+1−1
@@ -48,7 +48,7 @@ func NewDownloadTool(permissions permission.Service, workingDir string, client *
48 }
48 }
49 return fantasy.NewParallelAgentTool(
49 return fantasy.NewParallelAgentTool(
50 DownloadToolName,
50 DownloadToolName,
51− string(downloadDescription),
51+ FirstLineDescription(downloadDescription),
52 func(ctx context.Context, params DownloadParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
52 func(ctx context.Context, params DownloadParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
53 if params.URL == "" {
53 if params.URL == "" {
54 return fantasy.NewTextErrorResponse("URL parameter is required"), nil
54 return fantasy.NewTextErrorResponse("URL parameter is required"), nil
internal/agent/tools/edit.go+1−1
@@ -68,7 +68,7 @@ func NewEditTool(
68) fantasy.AgentTool {
68) fantasy.AgentTool {
69 return fantasy.NewAgentTool(
69 return fantasy.NewAgentTool(
70 EditToolName,
70 EditToolName,
71− string(editDescription),
71+ FirstLineDescription(editDescription),
72 func(ctx context.Context, params EditParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
72 func(ctx context.Context, params EditParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
73 if params.FilePath == "" {
73 if params.FilePath == "" {
74 return fantasy.NewTextErrorResponse("file_path is required"), nil
74 return fantasy.NewTextErrorResponse("file_path is required"), nil
internal/agent/tools/fetch.go+1−1
@@ -39,7 +39,7 @@ func NewFetchTool(permissions permission.Service, workingDir string, client *htt
39
39
40 return fantasy.NewParallelAgentTool(
40 return fantasy.NewParallelAgentTool(
41 FetchToolName,
41 FetchToolName,
42− string(fetchDescription),
42+ FirstLineDescription(fetchDescription),
43 func(ctx context.Context, params FetchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
43 func(ctx context.Context, params FetchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
44 if params.URL == "" {
44 if params.URL == "" {
45 return fantasy.NewTextErrorResponse("URL parameter is required"), nil
45 return fantasy.NewTextErrorResponse("URL parameter is required"), nil
internal/agent/tools/glob.go+1−1
@@ -34,7 +34,7 @@ type GlobResponseMetadata struct {
34func NewGlobTool(workingDir string) fantasy.AgentTool {
34func NewGlobTool(workingDir string) fantasy.AgentTool {
35 return fantasy.NewAgentTool(
35 return fantasy.NewAgentTool(
36 GlobToolName,
36 GlobToolName,
37− string(globDescription),
37+ FirstLineDescription(globDescription),
38 func(ctx context.Context, params GlobParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
38 func(ctx context.Context, params GlobParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
39 if params.Pattern == "" {
39 if params.Pattern == "" {
40 return fantasy.NewTextErrorResponse("pattern is required"), nil
40 return fantasy.NewTextErrorResponse("pattern is required"), nil
internal/agent/tools/grep.go+1−1
@@ -105,7 +105,7 @@ func escapeRegexPattern(pattern string) string {
105func NewGrepTool(workingDir string, config config.ToolGrep) fantasy.AgentTool {
105func NewGrepTool(workingDir string, config config.ToolGrep) fantasy.AgentTool {
106 return fantasy.NewAgentTool(
106 return fantasy.NewAgentTool(
107 GrepToolName,
107 GrepToolName,
108− string(grepDescription),
108+ FirstLineDescription(grepDescription),
109 func(ctx context.Context, params GrepParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
109 func(ctx context.Context, params GrepParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
110 if params.Pattern == "" {
110 if params.Pattern == "" {
111 return fantasy.NewTextErrorResponse("pattern is required"), nil
111 return fantasy.NewTextErrorResponse("pattern is required"), nil
internal/agent/tools/job_kill.go+1−1
@@ -29,7 +29,7 @@ type JobKillResponseMetadata struct {
29func NewJobKillTool() fantasy.AgentTool {
29func NewJobKillTool() fantasy.AgentTool {
30 return fantasy.NewAgentTool(
30 return fantasy.NewAgentTool(
31 JobKillToolName,
31 JobKillToolName,
32− string(jobKillDescription),
32+ FirstLineDescription(jobKillDescription),
33 func(ctx context.Context, params JobKillParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
33 func(ctx context.Context, params JobKillParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
34 if params.ShellID == "" {
34 if params.ShellID == "" {
35 return fantasy.NewTextErrorResponse("missing shell_id"), nil
35 return fantasy.NewTextErrorResponse("missing shell_id"), nil
internal/agent/tools/job_output.go+1−1
@@ -33,7 +33,7 @@ type JobOutputResponseMetadata struct {
33func NewJobOutputTool() fantasy.AgentTool {
33func NewJobOutputTool() fantasy.AgentTool {
34 return fantasy.NewAgentTool(
34 return fantasy.NewAgentTool(
35 JobOutputToolName,
35 JobOutputToolName,
36− string(jobOutputDescription),
36+ FirstLineDescription(jobOutputDescription),
37 func(ctx context.Context, params JobOutputParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
37 func(ctx context.Context, params JobOutputParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
38 if params.ShellID == "" {
38 if params.ShellID == "" {
39 return fantasy.NewTextErrorResponse("missing shell_id"), nil
39 return fantasy.NewTextErrorResponse("missing shell_id"), nil
internal/agent/tools/list_mcp_resources.go+1−1
@@ -31,7 +31,7 @@ var listMCPResourcesDescription []byte
31func NewListMCPResourcesTool(cfg *config.ConfigStore, permissions permission.Service) fantasy.AgentTool {
31func NewListMCPResourcesTool(cfg *config.ConfigStore, permissions permission.Service) fantasy.AgentTool {
32 return fantasy.NewParallelAgentTool(
32 return fantasy.NewParallelAgentTool(
33 ListMCPResourcesToolName,
33 ListMCPResourcesToolName,
34− string(listMCPResourcesDescription),
34+ FirstLineDescription(listMCPResourcesDescription),
35 func(ctx context.Context, params ListMCPResourcesParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
35 func(ctx context.Context, params ListMCPResourcesParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
36 params.MCPName = strings.TrimSpace(params.MCPName)
36 params.MCPName = strings.TrimSpace(params.MCPName)
37 if params.MCPName == "" {
37 if params.MCPName == "" {
internal/agent/tools/ls.go+1−1
@@ -58,7 +58,7 @@ var lsDescription []byte
58func NewLsTool(permissions permission.Service, workingDir string, lsConfig config.ToolLs) fantasy.AgentTool {
58func NewLsTool(permissions permission.Service, workingDir string, lsConfig config.ToolLs) fantasy.AgentTool {
59 return fantasy.NewAgentTool(
59 return fantasy.NewAgentTool(
60 LSToolName,
60 LSToolName,
61− string(lsDescription),
61+ FirstLineDescription(lsDescription),
62 func(ctx context.Context, params LSParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
62 func(ctx context.Context, params LSParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
63 searchPath, err := fsext.Expand(cmp.Or(params.Path, workingDir))
63 searchPath, err := fsext.Expand(cmp.Or(params.Path, workingDir))
64 if err != nil {
64 if err != nil {
internal/agent/tools/lsp_restart.go+1−1
@@ -27,7 +27,7 @@ type LSPRestartParams struct {
27func NewLSPRestartTool(lspManager *lsp.Manager) fantasy.AgentTool {
27func NewLSPRestartTool(lspManager *lsp.Manager) fantasy.AgentTool {
28 return fantasy.NewAgentTool(
28 return fantasy.NewAgentTool(
29 LSPRestartToolName,
29 LSPRestartToolName,
30− string(lspRestartDescription),
30+ FirstLineDescription(lspRestartDescription),
31 func(ctx context.Context, params LSPRestartParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
31 func(ctx context.Context, params LSPRestartParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
32 if lspManager.Clients().Len() == 0 {
32 if lspManager.Clients().Len() == 0 {
33 return fantasy.NewTextErrorResponse("no LSP clients available to restart"), nil
33 return fantasy.NewTextErrorResponse("no LSP clients available to restart"), nil
internal/agent/tools/multiedit.go+1−1
@@ -66,7 +66,7 @@ func NewMultiEditTool(
66) fantasy.AgentTool {
66) fantasy.AgentTool {
67 return fantasy.NewAgentTool(
67 return fantasy.NewAgentTool(
68 MultiEditToolName,
68 MultiEditToolName,
69− string(multieditDescription),
69+ FirstLineDescription(multieditDescription),
70 func(ctx context.Context, params MultiEditParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
70 func(ctx context.Context, params MultiEditParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
71 if params.FilePath == "" {
71 if params.FilePath == "" {
72 return fantasy.NewTextErrorResponse("file_path is required"), nil
72 return fantasy.NewTextErrorResponse("file_path is required"), nil
internal/agent/tools/read_mcp_resource.go+1−1
@@ -33,7 +33,7 @@ var readMCPResourceDescription []byte
33func NewReadMCPResourceTool(cfg *config.ConfigStore, permissions permission.Service) fantasy.AgentTool {
33func NewReadMCPResourceTool(cfg *config.ConfigStore, permissions permission.Service) fantasy.AgentTool {
34 return fantasy.NewParallelAgentTool(
34 return fantasy.NewParallelAgentTool(
35 ReadMCPResourceToolName,
35 ReadMCPResourceToolName,
36− string(readMCPResourceDescription),
36+ FirstLineDescription(readMCPResourceDescription),
37 func(ctx context.Context, params ReadMCPResourceParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
37 func(ctx context.Context, params ReadMCPResourceParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
38 params.MCPName = strings.TrimSpace(params.MCPName)
38 params.MCPName = strings.TrimSpace(params.MCPName)
39 params.URI = strings.TrimSpace(params.URI)
39 params.URI = strings.TrimSpace(params.URI)
internal/agent/tools/references.go+1−1
@@ -36,7 +36,7 @@ var referencesDescription []byte
36func NewReferencesTool(lspManager *lsp.Manager) fantasy.AgentTool {
36func NewReferencesTool(lspManager *lsp.Manager) fantasy.AgentTool {
37 return fantasy.NewAgentTool(
37 return fantasy.NewAgentTool(
38 ReferencesToolName,
38 ReferencesToolName,
39− string(referencesDescription),
39+ FirstLineDescription(referencesDescription),
40 func(ctx context.Context, params ReferencesParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
40 func(ctx context.Context, params ReferencesParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
41 if params.Symbol == "" {
41 if params.Symbol == "" {
42 return fantasy.NewTextErrorResponse("symbol is required"), nil
42 return fantasy.NewTextErrorResponse("symbol is required"), nil
internal/agent/tools/sourcegraph.go+1−1
@@ -45,7 +45,7 @@ func NewSourcegraphTool(client *http.Client) fantasy.AgentTool {
45 }
45 }
46 return fantasy.NewParallelAgentTool(
46 return fantasy.NewParallelAgentTool(
47 SourcegraphToolName,
47 SourcegraphToolName,
48− string(sourcegraphDescription),
48+ FirstLineDescription(sourcegraphDescription),
49 func(ctx context.Context, params SourcegraphParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
49 func(ctx context.Context, params SourcegraphParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
50 if params.Query == "" {
50 if params.Query == "" {
51 return fantasy.NewTextErrorResponse("Query parameter is required"), nil
51 return fantasy.NewTextErrorResponse("Query parameter is required"), nil
internal/agent/tools/todos.go+1−1
@@ -36,7 +36,7 @@ type TodosResponseMetadata struct {
36func NewTodosTool(sessions session.Service) fantasy.AgentTool {
36func NewTodosTool(sessions session.Service) fantasy.AgentTool {
37 return fantasy.NewAgentTool(
37 return fantasy.NewAgentTool(
38 TodosToolName,
38 TodosToolName,
39− string(todosDescription),
39+ FirstLineDescription(todosDescription),
40 func(ctx context.Context, params TodosParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
40 func(ctx context.Context, params TodosParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
41 sessionID := GetSessionFromContext(ctx)
41 sessionID := GetSessionFromContext(ctx)
42 if sessionID == "" {
42 if sessionID == "" {
internal/agent/tools/tools.go+15
@@ -2,6 +2,7 @@ package tools
2
2
3import (
3import (
4 "context"
4 "context"
5+ "strings"
5)
6)
6
7
7type (
8type (
@@ -54,3 +55,17 @@ func GetSupportsImagesFromContext(ctx context.Context) bool {
54func GetModelNameFromContext(ctx context.Context) string {
55func GetModelNameFromContext(ctx context.Context) string {
55 return getContextValue(ctx, ModelNameContextKey, "")
56 return getContextValue(ctx, ModelNameContextKey, "")
56}
57}
58+
59+// FirstLineDescription returns the first non-empty line from the embedded
60+// markdown description. This extracts just the concise summary line,
61+// significantly reducing token usage while preserving essential tool context.
62+func FirstLineDescription(content []byte) string {
63+ lines := strings.Split(string(content), "\n")
64+ for _, line := range lines {
65+ line = strings.TrimSpace(line)
66+ if line != "" {
67+ return line
68+ }
69+ }
70+ return ""
71+}
internal/agent/tools/view.go+1−1
@@ -69,7 +69,7 @@ func NewViewTool(
69) fantasy.AgentTool {
69) fantasy.AgentTool {
70 return fantasy.NewAgentTool(
70 return fantasy.NewAgentTool(
71 ViewToolName,
71 ViewToolName,
72− string(viewDescription),
72+ FirstLineDescription(viewDescription),
73 func(ctx context.Context, params ViewParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
73 func(ctx context.Context, params ViewParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
74 if params.FilePath == "" {
74 if params.FilePath == "" {
75 return fantasy.NewTextErrorResponse("file_path is required"), nil
75 return fantasy.NewTextErrorResponse("file_path is required"), nil
internal/agent/tools/web_fetch.go+1−1
@@ -31,7 +31,7 @@ func NewWebFetchTool(workingDir string, client *http.Client) fantasy.AgentTool {
31
31
32 return fantasy.NewParallelAgentTool(
32 return fantasy.NewParallelAgentTool(
33 WebFetchToolName,
33 WebFetchToolName,
34− string(webFetchToolDescription),
34+ FirstLineDescription(webFetchToolDescription),
35 func(ctx context.Context, params WebFetchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
35 func(ctx context.Context, params WebFetchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
36 if params.URL == "" {
36 if params.URL == "" {
37 return fantasy.NewTextErrorResponse("url is required"), nil
37 return fantasy.NewTextErrorResponse("url is required"), nil
internal/agent/tools/web_search.go+1−1
@@ -29,7 +29,7 @@ func NewWebSearchTool(client *http.Client) fantasy.AgentTool {
29
29
30 return fantasy.NewParallelAgentTool(
30 return fantasy.NewParallelAgentTool(
31 WebSearchToolName,
31 WebSearchToolName,
32− string(webSearchToolDescription),
32+ FirstLineDescription(webSearchToolDescription),
33 func(ctx context.Context, params WebSearchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
33 func(ctx context.Context, params WebSearchParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
34 if params.Query == "" {
34 if params.Query == "" {
35 return fantasy.NewTextErrorResponse("query is required"), nil
35 return fantasy.NewTextErrorResponse("query is required"), nil
internal/agent/tools/write.go+1−1
@@ -52,7 +52,7 @@ func NewWriteTool(
52) fantasy.AgentTool {
52) fantasy.AgentTool {
53 return fantasy.NewAgentTool(
53 return fantasy.NewAgentTool(
54 WriteToolName,
54 WriteToolName,
55− string(writeDescription),
55+ FirstLineDescription(writeDescription),
56 func(ctx context.Context, params WriteParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
56 func(ctx context.Context, params WriteParams, call fantasy.ToolCall) (fantasy.ToolResponse, error) {
57 if params.FilePath == "" {
57 if params.FilePath == "" {
58 return fantasy.NewTextErrorResponse("file_path is required"), nil
58 return fantasy.NewTextErrorResponse("file_path is required"), nil