feat: add declarative workflow subagents (Sequential, Parallel, Loop)#1743
feat: add declarative workflow subagents (Sequential, Parallel, Loop)#1743jsonmp-k8 wants to merge 7 commits intokagent-dev:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds first-class declarative workflow orchestration to the Agent CRD (Sequential / Parallel / Loop) and wires it through the translator and both runtimes so in-process sub-agents can be defined via YAML and executed deterministically.
Changes:
- Extend the v1alpha2 Agent CRD with
workflow(type + inlinesubAgents+ optionalmaxIterations) plus validations and codegen updates. - Update the Go translator to emit workflow-aware ADK config and add golden test fixtures for sequential + loop workflows.
- Add Python and Go runtime support to construct ADK workflow agents from the translated config, plus Python unit tests.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| python/packages/kagent-adk/tests/unittests/test_workflow_agents.py | Adds unit tests validating workflow agent construction (sequential/parallel/loop). |
| python/packages/kagent-adk/src/kagent/adk/types.py | Introduces workflow/sub-agent config types and builds ADK workflow agents/sub-agents. |
| go/core/internal/controller/translator/agent/testdata/outputs/agent_with_workflow_sequential.json | Golden output for sequential workflow translation. |
| go/core/internal/controller/translator/agent/testdata/outputs/agent_with_workflow_loop.json | Golden output for loop workflow translation (with max_iterations). |
| go/core/internal/controller/translator/agent/testdata/inputs/agent_with_workflow_sequential.yaml | Golden input YAML for sequential workflow Agent. |
| go/core/internal/controller/translator/agent/testdata/inputs/agent_with_workflow_loop.yaml | Golden input YAML for loop workflow Agent. |
| go/core/internal/controller/translator/agent/compiler.go | Adds workflow validation + translation path and sub-agent MCP tool translation. |
| go/core/internal/controller/translator/agent/adk_api_translator.go | Factors MCP server translation into a reusable helper returning tool configs. |
| go/api/v1alpha2/zz_generated.deepcopy.go | Generated deepcopy updates for new workflow-related types/fields. |
| go/api/v1alpha2/agent_types.go | CRD type additions: WorkflowSpec, InlineAgentSpec, WorkflowType, plus CEL validation. |
| go/api/config/crd/bases/kagent.dev_sandboxagents.yaml | Generated CRD schema update to include workflow. |
| go/api/config/crd/bases/kagent.dev_agents.yaml | Generated CRD schema update to include workflow. |
| go/api/adk/types.go | Adds workflow JSON config types and embeds them into AgentConfig. |
| go/adk/pkg/runner/adapter.go | Routes workflow configs to a workflow-agent creation path. |
| go/adk/pkg/agent/agent.go | Implements CreateWorkflowAgent and in-process sub-agent creation for Go runtime. |
| design/EP-991-workflow-subagents.md | Design/EP document describing the feature, constraints, and examples. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def to_agent(self, name: str, sts_integration: Optional[ADKTokenPropagationPlugin] = None) -> BaseAgent: | ||
| if self.workflow is not None: | ||
| return self._build_workflow_agent(name, sts_integration) | ||
| return self._build_llm_agent(name, sts_integration) | ||
|
|
||
| def _build_llm_agent(self, name: str, sts_integration: Optional[ADKTokenPropagationPlugin] = None) -> Agent: |
There was a problem hiding this comment.
When workflow is set, to_agent() returns _build_workflow_agent() and bypasses _build_llm_agent(), so memory configuration is never applied (no memory tools injected and no auto-save callback). Either explicitly disallow memory for workflow agents at the schema/validation layer, or propagate/apply memory configuration to workflow sub-agents.
jeffspahr
left a comment
There was a problem hiding this comment.
I found two workflow-agent issues that should be fixed before merge. I also noticed a Helm values-path regression in my fetched PR worktree, but GitHub's current PR diff does not include helm/kagent/Chart-template.yaml, so I could not attach that as an inline comment here.
Verification performed:
go test ./core/internal/controller/translator/agent ./adk/pkg/agent ./adk/pkg/runnerpassed.cd python && uv run --extra dev pytest packages/kagent-adk/tests/unittests/test_workflow_agents.py -qpassed.- Manual Python repro confirmed
content-writeris accepted by the CRD shape but rejected by ADK runtime as an invalid agent name.
Add support for declarative workflow patterns that deterministically orchestrate in-process sub-agents using Google ADK's SequentialAgent, ParallelAgent, and LoopAgent primitives. Sub-agents are defined inline within the parent Agent CRD and run in-process within the same pod, sharing session state. Each sub-agent can have its own system message, model config, and MCP tools. Changes: - CRD: Add WorkflowSpec, InlineAgentSpec types with CEL validation - ADK types: Add WorkflowAgentConfig, SubAgentConfig for runtime config - Translator: Add translateWorkflowAgent with model/tool resolution - Python runtime: Refactor to_agent() to dispatch workflow agents - Go runtime: Add CreateWorkflowAgent() with all three workflow types - Tests: Golden tests for sequential/loop, Python unit tests Closes kagent-dev#991 Signed-off-by: Jaison Paul <paul.jaison@gmail.com>
Import BaseAgent at module level instead of using deferred string annotations that ruff cannot resolve. Signed-off-by: Jaison Paul <paul.jaison@gmail.com>
- Add tool approval handling (before_tool_callback, before_model_callback) to workflow sub-agents so require_approval is enforced - Add AskUserTool() to workflow sub-agents so they can ask clarifying questions like regular agents - Add CEL validation making workflow mutually exclusive with memory, context, and executeCodeBlocks to prevent silent feature dropping - Fix maxIterations doc comment: when unset, loop runs indefinitely until a sub-agent escalates (not defaulting to 10) Signed-off-by: Jaison Paul <paul.jaison@gmail.com>
Signed-off-by: Jaison Paul <paul.jaison@gmail.com>
Signed-off-by: Jaison Paul <paul.jaison@gmail.com>
- Wire MakeApprovalCallback, tool logging callbacks, and MakeStripConfirmationPartsCallback into Go workflow sub-agents so requireApproval is enforced (matching regular agent behavior) - Add CRD pattern validation on InlineAgentSpec.Name requiring valid Python identifiers (^[A-Za-z_][A-Za-z0-9_]*$) to reject names like "content-writer" at admission time instead of runtime Signed-off-by: Jaison Paul <paul.jaison@gmail.com>
14eeb7d to
7a761e8
Compare
There was a problem hiding this comment.
First doing a high level review, but we should definitely discuss this (and the following points) during community meeting.
-
Workflow agents are fundamentally different type of agent from LLM agent, embedding its configuration inside
DeclarativeAgentCRD doesn't seem good to me. I personally prefer an API that provides a separate agent type likeWorkflowAgentSpec -
What is the expected UX when a user continues a chat session with a workflow agent after the initial invocation? kagent’s UI is primarily interactive/chat-oriented, but workflow agents seem closer to single-run pipelines. FYI this was something I noticed when adding CrewAI before, which is also workflow-oriented. Could be something to discuss next
-
I'm mildly surprised at how this will work since I don't see you setting things like
output_keyandexit_loopwhich is required for sequential and loop to work properly according to the docs? Subsequently, how to let users configure these (to share / pass state and to terminal execution) will be another point of discussion.
|
First thank you @jsonmp-k8 @jeffspahr - this is very relevant and important PR. I would like to see how we could cover all scenarios and patterns as described here: https://developers.googleblog.com/developers-guide-to-multi-agent-patterns-in-adk/ In addition I'd like to see how we could cover dynamic FanOut cases. Few comments:
|
|
I agree that we should allow for nested sub-agents, up to some sane default, maybe 10 levels. |
Summary
SequentialAgent,ParallelAgent, andLoopAgentExample
Changes
design/EP-991-workflow-subagents.mdgo/api/v1alpha2/agent_types.goWorkflowSpec,InlineAgentSpec,WorkflowType+ CEL validationzz_generated.deepcopy.go, CRD YAML basesgo/api/adk/types.goWorkflowAgentConfig,SubAgentConfigcompiler.go,adk_api_translator.gotranslateWorkflowAgent,translateMCPServerTool, validationtypes.py_build_workflow_agent(),_build_sub_agent()agent.go,adapter.goCreateWorkflowAgent(),createInProcessSubAgent()Closes #991
Test plan
golangci-lintpasses with 0 issuesgofmtclean on all changed files