@@ -23,20 +23,42 @@ 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()`. The framework
48+ will allow the agent to wait for user response on a separate channel.
49+
50+ - **Cancellation Workflow**: When a cancellation request is received, the
51+ async task running `execute()` is cancelled (raising an `asyncio.CancelledError`),
52+ and `cancel()` is explicitly called by the framework. `cancel()`.
53+
54+ Allowed Workflows:
55+ - Immediate response: Enqueue a SINGLE `Message` object.
56+ - Asynchronous/Long-running: Enqueue a `Task` object, perform work, and emit
57+ multiple `TaskStatusUpdateEvent` / `TaskArtifactUpdateEvent` objects over time.
58+
59+ Note that the framework waits with response to the request with
60+ `return_immediately=True` parameter until the first event
61+ (Message or Task) is enqueued by AgentExecutor.
4062
4163 Args:
4264 context: The request context containing the message, task ID, etc.
@@ -53,9 +75,12 @@ async def cancel(
5375 in the context and publish a `TaskStatusUpdateEvent` with state
5476 `TaskState.TASK_STATE_CANCELED` to the `event_queue`.
5577
56- TODO: Document cancelation workflow.
57- - What if TaskState.TASK_STATE_CANCELED is not set by cancel() ?
58- - How it can interact with execute() ?
78+ Cancellation Workflow & Interactions:
79+ - **Framework Interaction**: The framework issues a cancellation to the asyncio Task
80+ running `execute()` (which will raise `asyncio.CancelledError` inside `execute()`),
81+ and awaits this `cancel()` method.
82+ - **State Transition**: The `cancel()` method MUST publish a `TaskStatusUpdateEvent`
83+ with `TaskState.TASK_STATE_CANCELED` to definitively end the task.
5984
6085 Args:
6186 context: The request context containing the task ID to cancel.
0 commit comments