[dotnet-port] Add BuildSequential and BuildConcurrent agent workflow builder helpers - #196
Conversation
Port .NET's AgentWorkflowBuilder.BuildSequential and AgentWorkflowBuilder.BuildConcurrent convenience functions to Go. BuildSequential chains agents in order using the default Config (message forwarding and role reassignment enabled), matching .NET's pipeline behavior. BuildConcurrent fans the input to all agents simultaneously using a lightweight forwarding executor at the start, with each agent configured to not re-forward the shared input. Tests cover single-agent and multi-agent cases for both builders, plus error cases for empty input. Closes the "sequential/concurrent can be composed manually" gap in the feature comparison doc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by Go API Consistency Review Agent for issue #196 · ● 3.2M
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by Go API Consistency Review Agent for issue #196 · ● 5.1M
There was a problem hiding this comment.
Pull request overview
This PR ports .NET’s AgentWorkflowBuilder.BuildSequential / BuildConcurrent conveniences into Go by adding workflowhosting builder helpers, plus a small message-forwarding executor spec helper used by the concurrent fan-out path. It also adjusts workflow context handling for observability/tracing and syncs a workflow patterns example + feature comparison docs.
Changes:
- Add
workflowhosting.BuildSequential,BuildConcurrent, andBuildConcurrentWithAggregatorhelpers (with transcript-style output for sequential and fan-out/fan-in aggregation for concurrent). - Introduce
messageworkflow.ConfigureForwardingand accompanying tests to forward chat messages / turn tokens (and optionally strings). - Update workflow context/telemetry plumbing, refresh tests accordingly, and sync example + feature-comparison documentation.
Show a summary per file
| File | Description |
|---|---|
| workflow/workflow.go | Removes GetContext() and changes telemetry lookup to use the workflow context directly. |
| workflow/executor.go | Passes *workflow.Context into telemetry span creation (instead of GetContext()). |
| workflow/executor_test.go | Updates tests to populate workflow.Context.Context so executor execution has a real context. |
| message/messageworkflow/messageworkflow_test.go | Sets workflow.Context.Context in tests to avoid nil embedded contexts. |
| message/messageworkflow/messageforwarding.go | Adds ConfigureForwarding helper for forwarding messages/turn tokens (optional string support). |
| message/messageworkflow/messageforwarding_test.go | Adds coverage for forwarding behavior and protocol description. |
| agent/hosting/workflowhosting/builders.go | Adds sequential/concurrent workflow builder helpers + internal executors (start forwarder, per-agent batchers, end aggregator, transcript sink). |
| agent/hosting/workflowhosting/builders_test.go | Adds comprehensive tests for sequential/concurrent builders, custom aggregation, and multi-turn reset behavior. |
| examples/03-workflows/_start-here/03_agent_workflow_patterns/main.go | Updates sample to use new builders and newer OpenAI agent provider package. |
| docs/dotnet-go-sdk-feature-comparison.md | Updates feature comparison to reflect new sequential/concurrent builders. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
workflow/executor.go:285
telemetry.StartExecutorProcessis now invoked withctx(a*workflow.Context) as thecontext.Contextargument. This will panic ifctx.Context(the embedded context) is nil becausectx.Valuewill dispatch to a nil embedded interface. Either ensure*workflow.Contextsafely implementscontext.Contextwith a non-nil fallback (e.g., background) or pass a guaranteed-non-nil context here.
telemetry := ctx.telemetry()
messageType := NewTypeID(reflect.TypeOf(message))
spanCtx, span := telemetry.StartExecutorProcess(
ctx,
e.ID,
observability.TypeName(e.ExecutorType),
messageType.TypeName,
message,
ctx.traceContextStrings(),
)
- Files reviewed: 10/10 changed files
- Comments generated: 5
| const ( | ||
| aggregateTurnMessagesStateKey = "AggregateTurnMessagesExecutor.State" | ||
| concurrentEndExecutorID = "ConcurrentEnd" | ||
| outputMessagesExecutorID = "OutputMessages" | ||
| outputMessagesStateKey = "OutputMessagesExecutor.State" | ||
| ) |
Cross-repo parity review ✅This PR is a faithful port of .NET's Verified alignment with .NET upstream:
Python: No equivalent No cross-repo consistency issues found.
|
Port .NET's AgentWorkflowBuilder.BuildSequential and AgentWorkflowBuilder.BuildConcurrent convenience functions to Go, including the concurrent aggregation path.
BuildSequential chains agents in order using the default Config (message forwarding and role reassignment enabled), matching .NET's pipeline behavior. It now terminates with an OutputMessages-style executor so the workflow output contains the full turn transcript.
BuildConcurrent fans the input to all agents simultaneously using a lightweight forwarding executor at the start, per-agent turn-message batchers, and a fan-in end executor. BuildConcurrentWithAggregator supports custom, context-aware aggregation and defaults to returning the last message from each non-empty agent batch.
Tests cover single-agent and multi-agent cases for both builders, invalid inputs, custom aggregation, multi-turn concurrent aggregation reset behavior, and the message forwarding executor spec helper.
The agent workflow patterns StartHere sample is synced with the .NET sample's sequential/concurrent builder usage while keeping Azure OpenAI agent construction in the translation agent factory.
Closes the "sequential/concurrent can be composed manually" gap in the feature comparison doc.