Repository navigation
[dotnet-code] Clarify router type handling internals #438
Description
Summary
Clarifies the internal workflow message router metadata path by extracting the runtime-type substitution into typeHandlingInfo.forRuntimeType, matching the corresponding .NET TypeHandlingInfo shape more closely. This makes future .NET-to-Go routing ports easier to compare while preserving the existing cached interface-handler behavior.
.NET Reference
dotnet/src/Microsoft.Agents.AI.Workflows/Execution/MessageRouter.cs-TypeHandlingInfo.ForDerviedTypecreates derived runtime-type metadata when caching assignable handler matches.
Public API and Behavior
No public Go API changed. No intentional behavior change was made.
Tests
- Added
TestMessageRouterCachedInterfaceHandlerPreservesAutoOutputto lock existing cached interface-handler metadata behavior. - Ran
go test ./workflow. - Ran
go test ./....
Notes
Rejected candidates from the random .NET sample:
dotnet/src/Shared/Workflows/Execution/WorkflowFactory.cs- sample/shared factory code with no small production Go SDK counterpart cleanup.dotnet/src/Microsoft.Agents.AI.Workflows/Execution/StateScope.cs- Goworkflow/internal/execution/state.gois already structurally close for the sampled methods; no safer internal cleanup found.dotnet/src/Microsoft.Agents.AI.Workflows/Execution/ConcurrentEventSink.cs- Goworkflow/internal/execution/execution.goalready has the minimal sink shape plus Go-specific concurrency handling, so refactoring risk outweighed portability value.
Generated by .NET-to-Go Code Portability Refactoring Agent · 315.5 AIC · ⌖ 31 AIC · ⊞ 20.8K · ◷
Note
This was originally intended as a pull request, but GitHub Actions is not permitted to create or approve pull requests in this repository.
The changes have been pushed to branch dotnet-code-router-type-info-fcdf0e56f4c7648f.
To fix the permissions issue, go to Settings → Actions → General and enable Allow GitHub Actions to create and approve pull requests. See also: gh-aw FAQ
Show patch preview (80 of 80 lines)
From e9cc3e18f6290358f833d482b5393e6b350d55ab Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" <github-actions[bot]@users.noreply.github.com>
Date: Mon, 6 Jul 2026 22:50:59 +0000
Subject: [PATCH] Clarify router type handling internals
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
workflow/route.go | 7 ++++++-
workflow/route_test.go | 32 ++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/workflow/route.go b/workflow/route.go
index ca235e975..fa89736fe 100644
--- a/workflow/route.go
+++ b/workflow/route.go
@@ -183,6 +183,11 @@ type typeHandlingInfo struct {
autoOutput bool
}
+func (info typeHandlingInfo) forRuntimeType(runtimeType reflect.Type) typeHandlingInfo {
+ info.runtimeType = runtimeType
+ return info
+}
+
// newMessageRouter creates a router and indexes typed handlers by TypeID.
func newMessageRouter(handlers map[reflect.Type]MessageHandlerFunc, handlerOutputTypes map[reflect.Type]reflect.Type, catchAll CatchAllFunc) *messageRouter {
outputTypes := make(map[reflect.Type]struct{}, len(handlerOutputTypes))
@@ -309,7 +314,7 @@ func (mr *messageRouter) findHandler(messageType reflect.Type) (typeHandlingInfo
for _, interfaceType := range mr.interfaceHandlers {
if messageType.AssignableTo(interfaceType) {
info := mr.typedHandlers[interfaceType]
- info.runtimeType = messageType
+ info = info.forRuntimeType(messageType)
mr.typeInfos.Store(typeID, info)
return info, true
}
diff --git a/workflow/route_test.go b/workflow/route_test.go
index 6377f512b..6ac0aa7b4 100644
--- a/workflow/route_test.go
+++ b/workflow/route_test.go
@@ -110,3 +110,35 @@ func TestMessageRouterRoutesPortableValueAfterInterfaceMatchIsCached(t *testing.
t.Fatalf("RouteMessage portable result = %v, want portable", result.result)
}
}
+
+func TestMessageRouterCachedInterfaceHandlerPreservesAutoOutput(t *testing.T) {
+ var rb RouteBuilder
+ rb.AddHandlerRaw(reflect.TypeFor[route
... (truncated)
Activity