You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TaskSpawner currently creates exactly one Task per discovered work item. Many real-world workflows need a coordinated sequence of specialized agent steps per work item — plan, then implement, then test, then open PR. Today this requires either cramming everything into one monolithic prompt (losing specialization) or setting up multiple independent TaskSpawners with fragile label-based gating conventions. This proposal adds taskTemplates (plural) to TaskSpawner so that each discovered work item spawns a pipeline of Tasks with automatic dependency wiring and result passing between steps.
Problem
1. TaskSpawner is limited to one Task per work item
The spawner binary (cmd/kelos-spawner/main.go:309-337) creates a single Task per discovered item:
The taskTemplate field is singular. There is no way to define multiple steps that should be created together for each work item.
2. The pipeline pattern already exists — but only as manual Task creation
Example 07 (examples/07-task-pipeline/) demonstrates multi-step workflows using dependsOn and result passing via {{.Deps}} templates. This works well for one-off pipelines, but cannot be triggered automatically by a TaskSpawner. There is a fundamental gap between "I can define a pipeline of Tasks" and "I can have that pipeline triggered automatically per work item."
3. Kelos's own self-development proves the need — and the workaround is complex
Kelos uses 7+ separate TaskSpawners (self-development/kelos-workers.yaml, kelos-reviewer.yaml, kelos-pr-responder.yaml, etc.) with label-based gating (/kelos pick-up, excludeComments) to achieve multi-step workflows. This works but requires:
Understanding undocumented label conventions
Setting up separate TaskSpawners that must agree on naming/gating patterns
No automatic result passing between stages (each stage re-discovers context from the GitHub issue)
No aggregate visibility into the full workflow for a single work item
The alternative — putting everything in one prompt — means the agent must be expert at planning, implementing, testing, AND reviewing. In practice, specialized prompts with different models (e.g., Opus for planning, Sonnet for implementation) produce better results. The pipeline example already demonstrates this principle, but TaskSpawner can't leverage it.
Proposed API Extension
Option A: taskTemplates on TaskSpawner (recommended — incremental, no new CRD)
Add a taskTemplates field to TaskSpawnerSpec as an alternative to the existing taskTemplate:
apiVersion: kelos.dev/v1alpha1kind: TaskSpawnermetadata:
name: issue-pipelinespec:
when:
githubIssues:
labels: ["agent-pipeline"]maxConcurrency: 2taskTemplates:
- name: plantype: claude-codemodel: opuscredentials:
type: oauthsecretRef:
name: claude-credentialsworkspaceRef:
name: my-workspacepromptTemplate: | You are a technical planner. Analyze this issue and create a detailed implementation plan. Issue #{{.Number}}: {{.Title}} {{.Body}} Output a structured plan. Do NOT write code.
- name: implementtype: claude-codemodel: sonnetdependsOn: [plan]credentials:
type: oauthsecretRef:
name: claude-credentialsworkspaceRef:
name: my-workspacebranch: "kelos-{{.Number}}"promptTemplate: | Implement the following plan from the planning agent: {{index .Deps "plan" "Outputs"}} Issue #{{.Number}}: {{.Title}} Create a branch, write code, commit, and push.
- name: testtype: claude-codemodel: sonnetdependsOn: [implement]credentials:
type: oauthsecretRef:
name: claude-credentialsworkspaceRef:
name: my-workspacebranch: "kelos-{{.Number}}"promptTemplate: | Write tests for the implementation on branch {{index .Deps "implement" "Results" "branch"}}. Run all tests and fix any failures. Commit and push.
- name: open-prtype: claude-codedependsOn: [test]credentials:
type: oauthsecretRef:
name: claude-credentialsworkspaceRef:
name: my-workspacebranch: "kelos-{{.Number}}"promptTemplate: | Open a pull request for branch {{index .Deps "test" "Results" "branch"}}. Reference issue #{{.Number}}.
Spawner behavior change
For each discovered work item, the spawner creates N tasks instead of 1:
Task name pattern: {spawner}-{itemID}-{stepName}
Example: issue-pipeline-42-plan
issue-pipeline-42-implement
issue-pipeline-42-test
issue-pipeline-42-open-pr
The dependsOn field in each template step references sibling step names within the same item's task set. The spawner translates relative step names to fully-qualified task names:
This approach is more reusable (multiple TaskSpawners can share a pipeline definition) but requires a new CRD and more implementation work.
Recommendation
Start with Option A (taskTemplates on TaskSpawner). It is incremental, requires no new CRD, and can be extended to Option B later if reuse demand emerges. Option A is also backward-compatible — existing TaskSpawners with taskTemplate (singular) continue to work unchanged.
Implementation sketch
API change (api/v1alpha1/taskspawner_types.go): Add TaskTemplates []NamedTaskTemplate field to TaskSpawnerSpec. The NamedTaskTemplate struct extends TaskTemplate with a Name field and makes DependsOn reference sibling step names.
Validation: At most one of taskTemplate or taskTemplates may be set. Step names must be unique. dependsOn references must form a DAG (existing cycle detection in the Task controller already handles this).
Spawner change (cmd/kelos-spawner/main.go): When taskTemplates is set, the createTasksForItem loop creates N tasks per item, translating relative dependsOn names to fully-qualified task names ({spawner}-{itemID}-{stepName}).
Concurrency accounting: maxConcurrency should count pipeline instances (not individual tasks within a pipeline), since one work item = one pipeline. Add a pipelineConcurrency or redefine the semantics clearly.
Status tracking: Add totalPipelinesCreated to TaskSpawnerStatus alongside totalTasksCreated for clear accounting.
Use cases enabled
Use case
Pipeline steps
Standard issue workflow
plan → implement → test → open PR
PR quality gate
lint-check → security-scan → review → approve
Dependency update
detect-changes → update-code → run-tests → open PR
🤖 Kelos Strategist Agent @gjkim42
Area: New CRDs & API Extensions
Summary
TaskSpawner currently creates exactly one Task per discovered work item. Many real-world workflows need a coordinated sequence of specialized agent steps per work item — plan, then implement, then test, then open PR. Today this requires either cramming everything into one monolithic prompt (losing specialization) or setting up multiple independent TaskSpawners with fragile label-based gating conventions. This proposal adds
taskTemplates(plural) to TaskSpawner so that each discovered work item spawns a pipeline of Tasks with automatic dependency wiring and result passing between steps.Problem
1. TaskSpawner is limited to one Task per work item
The spawner binary (
cmd/kelos-spawner/main.go:309-337) creates a single Task per discovered item:The
taskTemplatefield is singular. There is no way to define multiple steps that should be created together for each work item.2. The pipeline pattern already exists — but only as manual Task creation
Example 07 (
examples/07-task-pipeline/) demonstrates multi-step workflows usingdependsOnand result passing via{{.Deps}}templates. This works well for one-off pipelines, but cannot be triggered automatically by a TaskSpawner. There is a fundamental gap between "I can define a pipeline of Tasks" and "I can have that pipeline triggered automatically per work item."3. Kelos's own self-development proves the need — and the workaround is complex
Kelos uses 7+ separate TaskSpawners (
self-development/kelos-workers.yaml,kelos-reviewer.yaml,kelos-pr-responder.yaml, etc.) with label-based gating (/kelos pick-up,excludeComments) to achieve multi-step workflows. This works but requires:4. Single-prompt approach loses agent specialization
The alternative — putting everything in one prompt — means the agent must be expert at planning, implementing, testing, AND reviewing. In practice, specialized prompts with different models (e.g., Opus for planning, Sonnet for implementation) produce better results. The pipeline example already demonstrates this principle, but TaskSpawner can't leverage it.
Proposed API Extension
Option A:
taskTemplateson TaskSpawner (recommended — incremental, no new CRD)Add a
taskTemplatesfield toTaskSpawnerSpecas an alternative to the existingtaskTemplate:Spawner behavior change
For each discovered work item, the spawner creates N tasks instead of 1:
The
dependsOnfield in each template step references sibling step names within the same item's task set. The spawner translates relative step names to fully-qualified task names:Option B: New
TaskPipelineCRD (alternative — more reusable, larger scope)Define a reusable pipeline template as a separate CRD, referenced by TaskSpawner:
This approach is more reusable (multiple TaskSpawners can share a pipeline definition) but requires a new CRD and more implementation work.
Recommendation
Start with Option A (
taskTemplateson TaskSpawner). It is incremental, requires no new CRD, and can be extended to Option B later if reuse demand emerges. Option A is also backward-compatible — existing TaskSpawners withtaskTemplate(singular) continue to work unchanged.Implementation sketch
API change (
api/v1alpha1/taskspawner_types.go): AddTaskTemplates []NamedTaskTemplatefield toTaskSpawnerSpec. TheNamedTaskTemplatestruct extendsTaskTemplatewith aNamefield and makesDependsOnreference sibling step names.Validation: At most one of
taskTemplateortaskTemplatesmay be set. Step names must be unique.dependsOnreferences must form a DAG (existing cycle detection in the Task controller already handles this).Spawner change (
cmd/kelos-spawner/main.go): WhentaskTemplatesis set, thecreateTasksForItemloop creates N tasks per item, translating relativedependsOnnames to fully-qualified task names ({spawner}-{itemID}-{stepName}).Concurrency accounting:
maxConcurrencyshould count pipeline instances (not individual tasks within a pipeline), since one work item = one pipeline. Add apipelineConcurrencyor redefine the semantics clearly.Status tracking: Add
totalPipelinesCreatedtoTaskSpawnerStatusalongsidetotalTasksCreatedfor clear accounting.Use cases enabled
Compatibility
taskTemplate(singular) remains the default for simple one-step spawnerstaskTemplates(plural) is opt-in and additivetaskTemplatecould be deprecated in favor of always usingtaskTemplates(with single-step being a pipeline of length 1)Design questions
maxConcurrencycount individual tasks or pipeline instances?taskTemplatessupport conditional execution (e.g., "run step C only if step B's result contains 'needs-review'")?