Skip to content

A2A-Samples Demo stuck on “task submitted” status even after FastA2A task completion #19

@dsaad68

Description

@dsaad68

Description:

When running the Demo UI as host (from A2A-Samples repo), and simultaneously launching the FastA2A sample agent (per the FastA2A README), the agent is discovered, and the task is submitted successfully, but the UI never updates past the “task submitted” status, even though the FastA2A worker finishes the task.

Reproduction steps:

  1. Clone and launch the Demo UI as the host:
git clone https://github.com/a2aproject/a2a-samples.git
cd a2a-samples/demo
uv run main.py
  1. In parallel, start the FastA2A sample agent (from the FastA2A README), for example:
uvicorn main:app --reload

In the Demo UI:

  • Navigate to Agents; Add the sample agents and the sample agent appears.
  • Starts a chat
  • Follow the progress in the Task and Event Section

Actual behavior:

  • The agent is discovered and registered in the Demo UI.
  • The Tasks panel shows “Task submitted” with no errors.
  • The FastA2A worker processes the task, updates its state to completed, and writes new messages/artifacts to storage.
  • The Events panel in the Demo UI logs the request and response messages.
  • However, the UI’s Tasks panel remains at “Task submitted” and does not transition to “completed” (or any further state).
  • And nothing appears in the chat.

image

image

Expected behavior:

After task completion in FastA2A, the demo should reflect the task status and proceed accordingly and messages appears in the chat.

FastA2A sample agent:

import uuid
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from typing import Any

from fasta2a import FastA2A, Worker
from fasta2a.broker import InMemoryBroker
from fasta2a.schema import Artifact, Message, TaskIdParams, TaskSendParams, TextPart
from fasta2a.storage import InMemoryStorage

Context = list[Message]
"""The shape of the context you store in the storage."""


class InMemoryWorker(Worker[Context]):
    async def run_task(self, params: TaskSendParams) -> None:
        task = await self.storage.load_task(params['id'])
        assert task is not None

        await self.storage.update_task(task['id'], state='working')

        context = await self.storage.load_context(task['context_id']) or []
        context.extend(task.get('history', []))

        # Call your agent here...
        message = Message(
            role='agent',
            parts=[TextPart(text=f'Your context is {len(context) + 1} messages long.', kind='text')],
            kind='message',
            message_id=str(uuid.uuid4()),
        )

        # Update the new message to the context.
        context.append(message)

        artifacts = self.build_artifacts(123)
        await self.storage.update_context(task['context_id'], context)
        await self.storage.update_task(task['id'], state='completed', new_messages=[message], new_artifacts=artifacts)

    async def cancel_task(self, params: TaskIdParams) -> None: ...

    def build_message_history(self, history: list[Message]) -> list[Any]: ...

    def build_artifacts(self, result: Any) -> list[Artifact]: ...


storage = InMemoryStorage()
broker = InMemoryBroker()
worker = InMemoryWorker(storage=storage, broker=broker)


@asynccontextmanager
async def lifespan(app: FastA2A) -> AsyncIterator[None]:
    async with app.task_manager:
        async with worker.run():
            yield


app = FastA2A(storage=storage, broker=broker, lifespan=lifespan)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions