From 010ee7dae6c342295532a5395414ed278413c3e6 Mon Sep 17 00:00:00 2001 From: Dwin Gharibi Date: Sun, 12 Jul 2026 20:20:09 +0330 Subject: [PATCH 1/6] feat(pkg/teamloader/toolsets/catalog.go): add built-in toolset catalog --- pkg/teamloader/toolsets/catalog.go | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 pkg/teamloader/toolsets/catalog.go diff --git a/pkg/teamloader/toolsets/catalog.go b/pkg/teamloader/toolsets/catalog.go new file mode 100644 index 0000000000..b6cc9770da --- /dev/null +++ b/pkg/teamloader/toolsets/catalog.go @@ -0,0 +1,43 @@ +package toolsets + +const docsBaseURL = "https://docker.github.io/docker-agent/tools/" + +type BuiltinToolsetInfo struct { + Type string `json:"type"` + Summary string `json:"summary"` + Docs string `json:"docs"` +} + +var BuiltinToolsets = []BuiltinToolsetInfo{ + builtinToolset("a2a", "a2a", "Connect to remote agents via the Agent-to-Agent (A2A) protocol"), + builtinToolset("api", "api", "Create custom tools that call HTTP APIs"), + builtinToolset("background_agents", "background-agents", "Dispatch work to sub-agents concurrently and collect results"), + builtinToolset("background_jobs", "background-jobs", "Run and manage long-running shell commands"), + builtinToolset("fetch", "fetch", "Read content from HTTP/HTTPS URLs"), + builtinToolset("filesystem", "filesystem", "Read, write, list, search, and navigate files and directories"), + builtinToolset("lsp", "lsp", "Connect to Language Server Protocol servers for code intelligence"), + builtinToolset("mcp", "mcp", "Extend agents with external tools via the Model Context Protocol"), + builtinToolset("mcp_catalog", "mcp-catalog", "Discover and activate remote MCP servers from the Docker MCP Catalog"), + builtinToolset("memory", "memory", "Persistent key-value storage for cross-session recall"), + builtinToolset("model_picker", "model-picker", "Let the agent pick between several models per turn"), + builtinToolset("open_url", "open-url", "Open a fixed URL in the user's default browser"), + builtinToolset("openapi", "openapi", "Generate tools automatically from an OpenAPI specification"), + builtinToolset("plan", "plan", "Shared persistent scratchpad for multi-agent collaboration"), + builtinToolset("rag", "rag", "Search document knowledge bases with hybrid retrieval (RAG)"), + builtinToolset("script", "script", "Define custom shell scripts as named tools with typed parameters"), + builtinToolset("session_context", "session_context", "Reference a previous session as context in the current one"), + builtinToolset("session_plan", "session_plan", "Per-session plan tracker for the draft/review/execute workflow"), + builtinToolset("shell", "shell", "Execute shell commands in the user's environment"), + builtinToolset("tasks", "tasks", "Persistent task database with priorities and dependencies"), + builtinToolset("think", "think", "Step-by-step reasoning scratchpad for planning"), + builtinToolset("todo", "todo", "Manage a task list for complex multi-step workflows"), + builtinToolset("user_prompt", "user-prompt", "Ask the user questions and collect interactive input"), +} + +func builtinToolset(toolsetType, docsSlug, summary string) BuiltinToolsetInfo { + return BuiltinToolsetInfo{ + Type: toolsetType, + Summary: summary, + Docs: docsBaseURL + docsSlug, + } +} From 655e9bcb34b668dc6dec01aa00a2c7904e8ac2cd Mon Sep 17 00:00:00 2001 From: Dwin Gharibi Date: Sun, 12 Jul 2026 20:20:30 +0330 Subject: [PATCH 2/6] test(pkg/teamloader/toolsets/catalog_test.go): add catalog drift guard --- pkg/teamloader/toolsets/catalog_test.go | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 pkg/teamloader/toolsets/catalog_test.go diff --git a/pkg/teamloader/toolsets/catalog_test.go b/pkg/teamloader/toolsets/catalog_test.go new file mode 100644 index 0000000000..a4f63d9e32 --- /dev/null +++ b/pkg/teamloader/toolsets/catalog_test.go @@ -0,0 +1,32 @@ +package toolsets + +import ( + "maps" + "slices" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBuiltinToolsetsCatalogMatchesRegistry(t *testing.T) { + t.Parallel() + + registryTypes := slices.Sorted(maps.Keys(DefaultToolsetCreators())) + + catalogTypes := make([]string, 0, len(BuiltinToolsets)) + for _, ts := range BuiltinToolsets { + catalogTypes = append(catalogTypes, ts.Type) + } + slices.Sort(catalogTypes) + + require.Equal(t, registryTypes, catalogTypes, + "catalog and registry are out of sync; update pkg/teamloader/toolsets/catalog.go to document exactly the registered toolset types") +} + +func TestBuiltinToolsetsHaveSummaries(t *testing.T) { + t.Parallel() + + for _, ts := range BuiltinToolsets { + require.NotEmptyf(t, ts.Summary, "toolset %q must have a summary", ts.Type) + } +} From f3fec33820e098bd55fc0ab474ca89fb5b49d3d8 Mon Sep 17 00:00:00 2001 From: Dwin Gharibi Date: Sun, 12 Jul 2026 20:21:33 +0330 Subject: [PATCH 3/6] feat(cmd/root/toolsets.go): add toolsets commandinto amazing docker agent --- cmd/root/toolsets.go | 74 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 cmd/root/toolsets.go diff --git a/cmd/root/toolsets.go b/cmd/root/toolsets.go new file mode 100644 index 0000000000..b10d9780a3 --- /dev/null +++ b/cmd/root/toolsets.go @@ -0,0 +1,74 @@ +package root + +import ( + "encoding/json" + "fmt" + "text/tabwriter" + + "github.com/spf13/cobra" + + loadertoolsets "github.com/docker/docker-agent/pkg/teamloader/toolsets" + "github.com/docker/docker-agent/pkg/telemetry" +) + +type toolsetsFlags struct { + format string +} + +func newToolsetsCmd() *cobra.Command { + var flags toolsetsFlags + + cmd := &cobra.Command{ + Use: "toolsets", + Short: "List built-in toolset types", + Long: `List the built-in toolset types available for use in an agent configuration. + +Each type can be referenced under 'toolsets:' in an agent YAML file, for example: + + toolsets: + - type: filesystem + - type: shell`, + GroupID: "diagnose", + Args: cobra.NoArgs, + Example: ` docker agent toolsets + docker agent toolsets --format json`, + RunE: flags.run, + } + + cmd.Flags().StringVar(&flags.format, "format", "table", "Output format: table, json") + + return cmd +} + +func (f *toolsetsFlags) run(cmd *cobra.Command, args []string) (commandErr error) { + ctx := cmd.Context() + telemetry.TrackCommand(ctx, "toolsets", args) + defer func() { + telemetry.TrackCommandError(ctx, "toolsets", args, commandErr) + }() + + switch f.format { + case "table": + f.renderTable(cmd) + return nil + case "json": + return f.renderJSON(cmd) + default: + return fmt.Errorf("unknown format %q: must be %q or %q", f.format, "table", "json") + } +} + +func (f *toolsetsFlags) renderTable(cmd *cobra.Command) { + w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 2, 3, ' ', 0) + fmt.Fprintln(w, "TYPE\tSUMMARY") + for _, ts := range loadertoolsets.BuiltinToolsets { + fmt.Fprintf(w, "%s\t%s\n", ts.Type, ts.Summary) + } + w.Flush() +} + +func (f *toolsetsFlags) renderJSON(cmd *cobra.Command) error { + enc := json.NewEncoder(cmd.OutOrStdout()) + enc.SetIndent("", " ") + return enc.Encode(loadertoolsets.BuiltinToolsets) +} From 6a5c121a4a05779b1627450a6ec0a5de5cde1bcf Mon Sep 17 00:00:00 2001 From: Dwin Gharibi Date: Sun, 12 Jul 2026 20:22:00 +0330 Subject: [PATCH 4/6] test(cmd/root/toolsets_cmd_test.go): add toolsets command tests --- cmd/root/toolsets_cmd_test.go | 73 +++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 cmd/root/toolsets_cmd_test.go diff --git a/cmd/root/toolsets_cmd_test.go b/cmd/root/toolsets_cmd_test.go new file mode 100644 index 0000000000..47558d0470 --- /dev/null +++ b/cmd/root/toolsets_cmd_test.go @@ -0,0 +1,73 @@ +package root + +import ( + "bytes" + "encoding/json" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + loadertoolsets "github.com/docker/docker-agent/pkg/teamloader/toolsets" +) + +func TestToolsetsCommand_TableListsBuiltinTypes(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + cmd := newToolsetsCmd() + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs(nil) + + require.NoError(t, cmd.Execute()) + + out := buf.String() + require.Contains(t, out, "TYPE") + require.Contains(t, out, "SUMMARY") + require.Contains(t, out, "think") + require.Contains(t, out, "filesystem") + require.Contains(t, out, "Step-by-step reasoning scratchpad for planning") +} + +func TestToolsetsCommand_JSONMatchesCatalog(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + cmd := newToolsetsCmd() + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs([]string{"--format", "json"}) + + require.NoError(t, cmd.Execute()) + + var got []loadertoolsets.BuiltinToolsetInfo + require.NoError(t, json.Unmarshal(buf.Bytes(), &got)) + require.Equal(t, loadertoolsets.BuiltinToolsets, got) +} + +func TestToolsetsCommand_RejectsArgs(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + cmd := newToolsetsCmd() + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs([]string{"unexpected"}) + + require.Error(t, cmd.Execute()) +} + +func TestToolsetsCommand_RejectsUnknownFormat(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + cmd := newToolsetsCmd() + cmd.SetOut(&buf) + cmd.SetErr(&buf) + cmd.SetArgs([]string{"--format", "yaml"}) + + err := cmd.Execute() + require.Error(t, err) + require.Contains(t, strings.ToLower(err.Error()), "format") +} From 5956548efeff4f7a348f7e0b0d6ca65bc7d89760 Mon Sep 17 00:00:00 2001 From: Dwin Gharibi Date: Sun, 12 Jul 2026 20:22:40 +0330 Subject: [PATCH 5/6] feat(cmd/root/root.go): register toolsets command into docker agent commands --- cmd/root/root.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/root/root.go b/cmd/root/root.go index 735840ead7..8f7a88a862 100644 --- a/cmd/root/root.go +++ b/cmd/root/root.go @@ -178,6 +178,7 @@ We collect anonymous usage data to help improve docker agent. To disable: newEvalCmd(), newShareCmd(), newModelsCmd(), + newToolsetsCmd(), newSetupCmd(), newDoctorCmd(), newDebugCmd(), From e75c9198b19cbf410d7f880564b3c899b8dce134 Mon Sep 17 00:00:00 2001 From: Dwin Gharibi Date: Sun, 12 Jul 2026 20:23:21 +0330 Subject: [PATCH 6/6] docs(docs/features/cli/index.md): add toolsets command to CLI reference --- docs/features/cli/index.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/features/cli/index.md b/docs/features/cli/index.md index e3052e0476..42e466b934 100644 --- a/docs/features/cli/index.md +++ b/docs/features/cli/index.md @@ -199,6 +199,24 @@ $ docker agent models --provider openai $ docker agent models --format json | jq ``` +### `docker agent toolsets` + +List the built-in toolset types available for use in an agent configuration. Each type can be referenced under `toolsets:` in an agent YAML file. Use this to discover what's available without leaving the terminal. + +```bash +$ docker agent toolsets [flags] +``` + +| Flag | Default | Description | +| ---------------- | ------- | --------------------------------- | +| `--format ` | `table` | Output format: `table` or `json`. | + +```bash +# Examples +$ docker agent toolsets # human-readable table +$ docker agent toolsets --format json | jq # machine-readable (type, summary, docs URL) +``` + ### `docker agent setup` Set up a model interactively. Three paths: pick a cloud provider, paste its API key, and choose where to store it (macOS Keychain, `pass`, or the docker agent env file `~/.config/cagent/.env`); check Docker Model Runner and pull a local model (no API key needed); or register a custom OpenAI-compatible provider (endpoint URL, API format, and API key variable) saved to your [user configuration](../../providers/custom/index.md#global-providers-user-configuration) so its models work everywhere via `--model /`. Ends with the exact command to start chatting. Secret values are never printed.