Skip to content

Python: [Bug]: WorkflowAgent drops response metadata when forwarding AgentResponseUpdate #7952

Description

@junnhwan

Description

When a workflow executor emits an AgentResponseUpdate, wrapping the workflow with WorkflowAgent and consuming it through run(stream=True) silently drops several response metadata fields.

WorkflowAgent._convert_workflow_event_to_agent_response_updates() creates a new AgentResponseUpdate instance, but currently only copies the content, role, author, IDs, timestamp, and raw representation. The following fields are not forwarded:

  • finish_reason
  • continuation_token
  • additional_properties

The method documentation says that output and intermediate updates are forwarded "as-is", so this appears to be an unintended loss of streaming response semantics.

This is distinct from #1331 / #3146, which addressed author_name, and from #4261, which concerns user-role messages being emitted as agent output.

Actual Result

The metadata fields are returned as None even though they were present on the executor's original AgentResponseUpdate.

Expected Result

WorkflowAgent should preserve these fields when forwarding an AgentResponseUpdate, just as it preserves the content, role, author, response ID, message ID, and timestamp.

Code Sample

Tested on main at commit edfe115ea06bca57ae5a123d0fac5b3fdda13603.

import asyncio

from agent_framework import (
    AgentResponseUpdate,
    Content,
    Executor,
    Message,
    WorkflowAgent,
    WorkflowBuilder,
    WorkflowContext,
    handler,
)


class MetadataExecutor(Executor):
    @handler
    async def handle(
        self,
        messages: list[Message],
        ctx: WorkflowContext[list[Message], AgentResponseUpdate],
    ) -> None:
        await ctx.yield_output(
            AgentResponseUpdate(
                contents=[Content.from_text(text="payload")],
                role="assistant",
                author_name="source-agent",
                response_id="source-response",
                message_id="source-message",
                finish_reason="stop",
                continuation_token="resume-token",
                additional_properties={
                    "provider_marker": "preserve-me",
                },
            )
        )


async def main() -> None:
    source = MetadataExecutor(id="metadata-executor")
    workflow = WorkflowBuilder(start_executor=source).build()
    agent = WorkflowAgent(workflow=workflow, name="wrapped-agent")

    updates = [update async for update in agent.run("input", stream=True)]
    update = updates[0]

    print(
        {
            "finish_reason": update.finish_reason,
            "continuation_token": update.continuation_token,
            "additional_properties": update.additional_properties,
        }
    )


asyncio.run(main())

Run with:

uv run --no-sync python -

Error Messages / Stack Traces

No exception is raised. The metadata is silently dropped during the WorkflowAgent streaming conversion.

Package Versions

  • agent-framework-core: 1.16.0 (local source from main at commit edfe115ea06bca57ae5a123d0fac5b3fdda13603)

Python Version

  • Python 3.13.1

Additional Context

  • OS: Windows
  • The current implementation loses the metadata before final response construction, so downstream consumers cannot recover it from AgentResponse.from_updates().
  • Long-running operations can lose their continuation_token and become impossible to resume.
  • Consumers cannot observe the provider/runtime finish reason.
  • Provider-specific metadata in additional_properties is lost.
  • Streaming behavior differs between a direct agent and the same agent executed through a workflow wrapper.
  • The existing test suite does not currently cover metadata preservation for this conversion path.

A focused implementation would preserve the missing fields when reconstructing the AgentResponseUpdate in _convert_workflow_event_to_agent_response_updates() and add regression coverage in python/packages/core/tests/workflow/test_workflow_agent.py.

I would like to work on this issue if the proposed behavior aligns with the project's expectations. I already have a deterministic reproduction and can prepare a focused fix with regression coverage. Please let me know whether this issue can be assigned to me.

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflowworkflowsUsage: [Issues, PRs], Target: Workflows

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions