@@ -23,20 +23,43 @@ async def execute(
2323 return once the agent's execution for this request is complete or
2424 yields control (e.g., enters an input-required state).
2525
26- TODO: Document request lifecycle and AgentExecutor responsibilities:
27- - Should not close the event_queue.
28- - Guarantee single execution per request (no concurrent execution).
29- - Throwing exception will result in TaskState.TASK_STATE_ERROR (CHECK!)
30- - Once call is completed it should not access context or event_queue
31- - Before completing the call it SHOULD update task status to terminal or interrupted state.
32- - Explain AUTH_REQUIRED workflow.
33- - Explain INPUT_REQUIRED workflow.
34- - Explain how cancelation work (executor task will be canceled, cancel() is called, order of calls, etc)
35- - Explain if execute can wait for cancel and if cancel can wait for execute.
36- - Explain behaviour of streaming / not-immediate when execute() returns in active state.
37- - Possible workflows:
38- - Enqueue a SINGLE Message object
39- - Enqueue TaskStatusUpdateEvent (TASK_STATE_SUBMITTED or TASK_STATE_REJECTED) and continue with TaskStatusUpdateEvent / TaskArtifactUpdateEvent.
26+ Request Lifecycle & AgentExecutor Responsibilities:
27+ - **Concurrency**: The framework guarantees single execution per request;
28+ `execute()` will not be called concurrently for the same request context.
29+ - **Exception Handling**: Unhandled exceptions raised by `execute()` will be
30+ caught by the framework and result in the task transitioning to
31+ `TaskState.TASK_STATE_ERROR`.
32+ - **Post-Completion**: Once `execute()` completes (returns or raises), the
33+ executor must not access the `context` or `event_queue` anymore.
34+ - **Terminal States**: Before completing the call normally, the executor
35+ SHOULD publish a `TaskStatusUpdateEvent` to transition the task to a
36+ terminal state (e.g., `TASK_STATE_COMPLETED`) or an interrupted state
37+ (`TASK_STATE_INPUT_REQUIRED` or `TASK_STATE_AUTH_REQUIRED`).
38+ - **Interrupted Workflows**:
39+ - `TASK_STATE_INPUT_REQUIRED`: The executor publishes a `TaskStatusUpdateEvent` with
40+ `TaskState.TASK_STATE_INPUT_REQUIRED` and returns to yield control.
41+ The request will resume once user input is provided.
42+ - `TASK_STATE_AUTH_REQUIRED`: There are in-bound and out-of-bound auth models.
43+ In both scenarios, the agent publishes a `TaskStatusUpdateEvent` with
44+ `TaskState.TASK_STATE_AUTH_REQUIRED`.
45+ - In-bound: The agent should return from `execute()`. The framework will
46+ call `execute()` again once the user response is received.
47+ - Out-of-bound: The agent should not return from `execute()`. It should wait
48+ for the out-of-band auth provider to complete the authentication and then
49+ continue execution.
50+
51+ - **Cancellation Workflow**: When a cancellation request is received, the
52+ async task running `execute()` is cancelled (raising an `asyncio.CancelledError`),
53+ and `cancel()` is explicitly called by the framework.
54+
55+ Allowed Workflows:
56+ - Immediate response: Enqueue a SINGLE `Message` object.
57+ - Asynchronous/Long-running: Enqueue a `Task` object, perform work, and emit
58+ multiple `TaskStatusUpdateEvent` / `TaskArtifactUpdateEvent` objects over time.
59+
60+ Note that the framework waits with response to the send_message request with
61+ `return_immediately=True` parameter until the first event (Message or Task)
62+ is enqueued by AgentExecutor.
4063
4164 Args:
4265 context: The request context containing the message, task ID, etc.
@@ -53,9 +76,12 @@ async def cancel(
5376 in the context and publish a `TaskStatusUpdateEvent` with state
5477 `TaskState.TASK_STATE_CANCELED` to the `event_queue`.
5578
56- TODO: Document cancelation workflow.
57- - What if TaskState.TASK_STATE_CANCELED is not set by cancel() ?
58- - How it can interact with execute() ?
79+ Cancellation Workflow & Interactions:
80+ - **Framework Interaction**: The framework issues a cancellation to the asyncio Task
81+ running `execute()` (which will raise `asyncio.CancelledError` inside `execute()`),
82+ and awaits this `cancel()` method.
83+ - **State Transition**: The `cancel()` method MUST publish a `TaskStatusUpdateEvent`
84+ with `TaskState.TASK_STATE_CANCELED` to definitively end the task.
5985
6086 Args:
6187 context: The request context containing the task ID to cancel.
0 commit comments