Skip to content

API: Add agentConfigRefs for composable multi-layer agent configuration #693

Description

@kelos-bot

🤖 Kelos Strategist Agent @gjkim42

Summary

The current API allows a Task or TaskTemplate to reference exactly one AgentConfig via agentConfigRef. In practice, multi-spawner deployments duplicate large blocks of shared instructions (environment, standards, project conventions) across every AgentConfig, with only role-specific sections differing. This proposal adds an agentConfigRefs (plural) field that references an ordered list of AgentConfig resources, merged at task creation time.

Problem

Duplicated instructions across AgentConfigs

The self-development workflow demonstrates this clearly. Every AgentConfig repeats the same boilerplate:

AgentConfig Environment Standards Project Conventions Role-specific
kelos-dev-agent ✅ duplicated ✅ duplicated ✅ duplicated 1 line
kelos-workers-agent ✅ duplicated ✅ duplicated ✅ duplicated ~5 lines
kelos-self-update-agent ✅ duplicated ✅ duplicated ✅ duplicated 0 lines
kelos-planner-agent ✅ duplicated ✅ duplicated ✅ duplicated 1 line

The ## Environment, ## Standards, and ## Project Conventions sections are nearly identical across all four configs (see self-development/agentconfig.yaml, kelos-workers.yaml, kelos-self-update.yaml, kelos-planner.yaml). Only the ## Identity agent name and role-specific additions differ.

Maintenance burden

When shared instructions change (e.g., a new Makefile target, a new logging convention, or a project convention update), every AgentConfig must be updated independently. The kelos-config-update spawner attempts to keep these in sync, but drift is inevitable — issue #601 documents exactly this problem ("AgentConfig co-location incomplete... agentsMD still drifted").

No composition model

Kubernetes itself solves this pattern with layered abstractions (PodDefaults, LimitRanges, admission webhooks that inject common config). Kelos's AgentConfig has no equivalent. You cannot say "use the base project config plus worker-specific additions."

Proposed API Change

New field: agentConfigRefs

Add an ordered list field alongside the existing singular agentConfigRef:

// TaskSpec (and TaskTemplate) changes:

// AgentConfigRef references a single AgentConfig resource.
// Deprecated: Use AgentConfigRefs for composable configuration.
// +optional
AgentConfigRef *AgentConfigReference `json:"agentConfigRef,omitempty"`

// AgentConfigRefs references an ordered list of AgentConfig resources.
// Configs are merged in order: agentsMD is concatenated (separated by
// newlines), plugins/skills/mcpServers lists are appended. Later entries
// can extend but not remove content from earlier entries.
// Mutually exclusive with AgentConfigRef.
// +optional
AgentConfigRefs []AgentConfigReference `json:"agentConfigRefs,omitempty"`

Merge semantics

When multiple AgentConfigs are referenced, they are merged in order (index 0 is the base):

Field Merge strategy
agentsMD Concatenate with \n\n separator
plugins Append (later plugins added after earlier ones)
skills Append
mcpServers Append; if two entries share the same name, the later one wins

This follows the principle of additive composition — each layer can only add to or override (by name) the configuration, never subtract from it.

Validation

  • agentConfigRef and agentConfigRefs are mutually exclusive (CEL validation rule)
  • agentConfigRefs must have at least 1 entry when set
  • All referenced AgentConfigs must exist in the same namespace

Example: Self-development refactored

Before (current — duplicated instructions):

# 4 separate AgentConfigs, each ~30 lines, with ~25 lines identical
apiVersion: kelos.dev/v1alpha1
kind: AgentConfig
metadata:
  name: kelos-workers-agent
spec:
  agentsMD: |
    # Kelos Worker Agent
    ## Environment
    You are running in an ephemeral container environment...  # DUPLICATED
    ## Identity
    - When commenting... "🤖 **Kelos Worker Agent** @gjkim42\n\n"
    ## Standards
    - Do not create duplicate issues...                      # DUPLICATED
    - Keep changes minimal and focused                       # DUPLICATED
    ## Project Conventions
    - Use Makefile targets...                                # DUPLICATED
    - Always try to add or improve tests...                  # DUPLICATED
    - Logging conventions...                                 # DUPLICATED
    - Commit messages...                                     # DUPLICATED

After (with composition):

# Shared base config — defined once
apiVersion: kelos.dev/v1alpha1
kind: AgentConfig
metadata:
  name: kelos-base
spec:
  agentsMD: |
    ## Environment
    You are running in an ephemeral container environment. Your file system
    changes disappear after the task completes. Persist work by creating PRs,
    issues, or comments.

    ## Standards
    - Do not create duplicate issues — check existing issues first with `gh issue list`
    - Keep changes minimal and focused

    ## Project Conventions
    - Use Makefile targets instead of discovering build/test commands yourself:
      - `make verify` — run all verification checks (lint, fmt, vet, etc.)
      - `make update` — update all generated files
      - `make test` — run all unit tests
      - `make test-integration` — run integration tests
      - `make build` — build binary
    - Always try to add or improve tests when modifying code
    - Logging conventions: start log messages with capital letters and do not end with punctuation
    - Commit messages: do not include PR links in commit messages
---
# Worker-specific config — only the delta
apiVersion: kelos.dev/v1alpha1
kind: AgentConfig
metadata:
  name: kelos-worker-role
spec:
  agentsMD: |
    ## Identity
    - When commenting on issues or PRs, always start with "🤖 **Kelos Worker Agent** @gjkim42\n\n"
---
# TaskSpawner references both
apiVersion: kelos.dev/v1alpha1
kind: TaskSpawner
metadata:
  name: kelos-workers
spec:
  taskTemplate:
    agentConfigRefs:
      - name: kelos-base        # shared project config
      - name: kelos-worker-role  # role-specific additions
    # ... rest of template

The resulting merged agentsMD injected into the agent would be:

## Environment
You are running in an ephemeral container environment...

## Standards
- Do not create duplicate issues...
...

## Identity
- When commenting... "🤖 **Kelos Worker Agent** @gjkim42\n\n"

Implementation approach

Controller changes (internal/controller/task_controller.go)

The current code at line 247 fetches a single AgentConfig:

if task.Spec.AgentConfigRef != nil {
    var ac kelosv1alpha1.AgentConfig
    // ... fetch and use
}

This would become:

refs := task.Spec.AgentConfigRefs
if task.Spec.AgentConfigRef != nil {
    // Backward compat: treat singular as single-element list
    refs = []AgentConfigReference{*task.Spec.AgentConfigRef}
}
if len(refs) > 0 {
    merged := mergeAgentConfigs(configs...)
    agentConfig = &merged
}

Spawner changes (cmd/kelos-spawner/main.go)

Line 342 forwards the singular ref — extend to forward the list.

CLI changes (internal/cli/run.go)

Support --agent-config accepting comma-separated names or repeated flags.

Scope

  • New files: None (merging logic is ~50 lines in task_controller.go)
  • Modified files: api/v1alpha1/task_types.go, api/v1alpha1/taskspawner_types.go, internal/controller/task_controller.go, cmd/kelos-spawner/main.go, internal/cli/run.go, internal/cli/printer.go
  • Generated files: zz_generated.deepcopy.go, CRD manifests (via make update)

Backward compatibility

  • agentConfigRef (singular) continues to work unchanged
  • agentConfigRefs is purely additive
  • CEL validation prevents using both simultaneously, with a clear error message
  • Existing TaskSpawners and Tasks require zero changes

Related issues

Issue Relationship
#601 AgentConfig drift problem — composition eliminates the root cause by centralizing shared config
#537 Conditional per-item overrides — complementary (overrides modify the template, composition builds the base config)
#335 Extract shared instructions from prompts — closed, but the underlying need for shared config persists

/kind feature

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions