Skip to content

Python: Self-loop not displayed correctly in DevUI #2470

@tsuting

Description

@tsuting

Description

When creating a workflow with a self-loop, DevUI does not render the self-loop correctly. The expected behavior is that the self-loop should appear visually on the node, but currently it is either missing or displayed incorrectly. Is this by design?

The second executor should point to itself.

Image

In my real use case (the one I provided below is an example), the final step requires human approval or feedback before the agent can proceed:

  • If the human response is yes, the workflow ends.
  • If the response is anything else, the agent uses the feedback to run the LLM and then requests approval again.

This logic creates a need for a self-loop. However, the current DevUI does not visually support a node pointing to itself, which makes the representation a little bit confusing.

Script to Reproduce

from typing import Literal

from agent_framework import (
    Executor,
    WorkflowBuilder,
    WorkflowContext,
    handler,
    response_handler,
)
from pydantic import BaseModel, Field
from typing_extensions import Never
from agent_framework.devui import serve


class Request(BaseModel):
    prompt: str = Field(description="The prompt to process.",
                        default="Hello, World!")


class Decision(BaseModel):
    finish_workflow: Literal['yes', 'no'] = Field(
        description="Indicates if workflow should finish.")


class Start(Executor):

    @handler
    async def ingest_data(self, request: Request, ctx: WorkflowContext[str]) -> None:
        await ctx.send_message(request.prompt)


class Finish(Executor):

    @handler
    async def handle_processing_result(
        self,
        prompt: str,
        ctx: WorkflowContext[str],
    ) -> None:

        await ctx.request_info(request_data=prompt, response_type=Decision)

    @response_handler
    async def handle_human_response(
        self, original_request: str, response: Decision, ctx: WorkflowContext[Never | str, Never | str]
    ) -> None:

        if response.finish_workflow == 'no':
            await ctx.send_message(original_request)
        else:
            await ctx.yield_output('Workflow Finished')


start = Start(id='start_workflow')
finish = Finish(id='finish_workflow')
workflow = (
    WorkflowBuilder(
        name="Test",
    )
    .set_start_executor(start)
    .add_edge(start, finish)
    .add_edge(finish, finish)
    .build()
)


def main():

    serve(entities=[workflow], port=8092, auto_open=True)


if __name__ == "__main__":
    main()

Expected Behavior

The self loop should be clearly visible and correctly attached to the node in the UI.

Image

Actual Behavior

The self loop is not displayed correctly.

Image

Metadata

Metadata

Assignees

Labels

Type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions