From 2b6b2bdb5015308086971589cd829cccb3476194 Mon Sep 17 00:00:00 2001 From: Joshua Barrington Date: Mon, 20 Apr 2026 22:49:09 +0200 Subject: [PATCH 1/2] add docker-agent.yaml config autodiscovery --- pkg/config/resolve.go | 28 +++++++++++++ pkg/config/resolve_test.go | 84 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/pkg/config/resolve.go b/pkg/config/resolve.go index dd84bcc27..85e8c20a2 100644 --- a/pkg/config/resolve.go +++ b/pkg/config/resolve.go @@ -142,8 +142,36 @@ func singleSource(key string, source Source) Sources { return Sources{key: source} } +// autodiscoverConfigFile checks the current working directory for a +// docker-agent.yaml or docker-agent.yml file. It returns the absolute +// path of the first match found, or "" if neither file exists. +var autodiscoverConfigNames = []string{"docker-agent.yaml", "docker-agent.yml"} + +func autodiscoverConfigFile() string { + wd, err := os.Getwd() + if err != nil { + return "" + } + for _, name := range autodiscoverConfigNames { + path := filepath.Join(wd, name) + if fileExists(path) { + slog.Debug("Auto-discovered agent config", "path", path) + return path + } + } + return "" +} + // resolve resolves an agent reference, handling aliases and defaults func resolve(agentFilename string) (string, error) { + // When no agent file is specified, try to auto-discover a config file + // in the current directory before falling back to the embedded default. + if agentFilename == "" { + if discovered := autodiscoverConfigFile(); discovered != "" { + agentFilename = discovered + } + } + agentFilename = cmp.Or(agentFilename, "default") // Try to resolve as an alias first diff --git a/pkg/config/resolve_test.go b/pkg/config/resolve_test.go index 592b42810..21a2478da 100644 --- a/pkg/config/resolve_test.go +++ b/pkg/config/resolve_test.go @@ -89,12 +89,96 @@ func TestResolveAgentFile_EmptyIsDefault(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) + // Ensure no docker-agent.yaml in the working directory + t.Chdir(t.TempDir()) + + resolved, err := resolve("") + + require.NoError(t, err) + assert.Equal(t, "default", resolved) +} + +func TestResolveAgentFile_AutodiscoverYaml(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + + dir := t.TempDir() + configFile := filepath.Join(dir, "docker-agent.yaml") + require.NoError(t, os.WriteFile(configFile, []byte(`version: "1"`), 0o644)) + t.Chdir(dir) + + resolved, err := resolve("") + + require.NoError(t, err) + assert.Equal(t, configFile, resolved) +} + +func TestResolveAgentFile_AutodiscoverYml(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + + dir := t.TempDir() + configFile := filepath.Join(dir, "docker-agent.yml") + require.NoError(t, os.WriteFile(configFile, []byte(`version: "1"`), 0o644)) + t.Chdir(dir) + + resolved, err := resolve("") + + require.NoError(t, err) + assert.Equal(t, configFile, resolved) +} + +func TestResolveAgentFile_AutodiscoverYamlTakesPrecedenceOverYml(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + + dir := t.TempDir() + primaryConfig := filepath.Join(dir, "docker-agent.yaml") + secondaryConfig := filepath.Join(dir, "docker-agent.yml") + require.NoError(t, os.WriteFile(primaryConfig, []byte(`version: "1"`), 0o644)) + require.NoError(t, os.WriteFile(secondaryConfig, []byte(`version: "1"`), 0o644)) + t.Chdir(dir) + resolved, err := resolve("") + require.NoError(t, err) + assert.Equal(t, primaryConfig, resolved) +} + +func TestResolveAgentFile_AutodiscoverIgnoredWhenExplicitArg(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + + dir := t.TempDir() + // Place a docker-agent.yaml in cwd + require.NoError(t, os.WriteFile(filepath.Join(dir, "docker-agent.yaml"), []byte(`version: "1"`), 0o644)) + t.Chdir(dir) + + // Explicitly passing "default" should not trigger autodiscovery + resolved, err := resolve("default") + require.NoError(t, err) assert.Equal(t, "default", resolved) } +func TestResolveAgentFile_AutodiscoverIgnoredWhenExplicitFile(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + + dir := t.TempDir() + // Place a docker-agent.yaml in cwd + require.NoError(t, os.WriteFile(filepath.Join(dir, "docker-agent.yaml"), []byte(`version: "1"`), 0o644)) + // Place an explicit agent file + explicitFile := filepath.Join(dir, "my-agent.yaml") + require.NoError(t, os.WriteFile(explicitFile, []byte(`version: "1"`), 0o644)) + t.Chdir(dir) + + resolved, err := resolve(explicitFile) + + require.NoError(t, err) + assert.Equal(t, explicitFile, resolved) +} + func TestResolveAgentFile_DefaultIsDefault(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home) From e43f7e61113257fb3942f4718d3932f2d605ac0d Mon Sep 17 00:00:00 2001 From: Joshua Barrington Date: Mon, 27 Apr 2026 18:10:01 +0200 Subject: [PATCH 2/2] change default config file to docker-agent.yaml in creator instructions --- .gitignore | 2 ++ pkg/creator/instructions.txt | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index abfcf698c..0c579c6e7 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ evals # agents agent.yaml +docker-agent.yaml +docker-agent.yml vendor # Local environment files diff --git a/pkg/creator/instructions.txt b/pkg/creator/instructions.txt index be7574e1b..47b1b1967 100644 --- a/pkg/creator/instructions.txt +++ b/pkg/creator/instructions.txt @@ -1,6 +1,6 @@ You are an agent builder. Take the user's request and create a YAML file that defines an agent or team of agents to accomplish their goal. -Use the filesystem tool to write the agent YAML configuration to a file named after the agent's purpose (keep the filename short and descriptive). +Use the filesystem tool to write the agent YAML configuration to a file named `docker-agent.yaml` in the current directory. You MUST define at least one agent named "root" - this is the entrypoint. @@ -189,5 +189,5 @@ agents: After writing the YAML file, tell the user to run their agent with: ```console -docker agent run +docker agent ```