Files
adk-python/contributing/samples/human_in_loop
Krishna vamsi Dhulipalla 4111f85b61 docs(adk): fix run_async example and correct ticketId payload key
Merge https://github.com/google/adk-python/pull/3875

# Problem
The example in `contributing/samples/human_in_loop/README.md` shows:

```python
await runner.run_async(...)
```

However, `run_async` returns an **async generator**, so awaiting it raises:

```
TypeError: object async_generator can't be used in 'await' expression
```

Additionally, the example payload uses `"ticket-id"` while ADK tools and other examples use `"ticketId"`, creating a mismatch that breaks copy/paste usage.

# Solution
- Updated the snippet to consume the async generator correctly:

```python
async for event in runner.run_async(...):
    ...
```

- Aligned the payload key from `"ticket-id"` → `"ticketId"` for consistency with ADK schema and other examples.

These changes make the example runnable and consistent with the API’s actual behavior.

# Testing Plan
This PR is a **small documentation correction**, so no unit tests are required per contribution guidelines.

- Verified the corrected snippet manually to ensure it no longer raises `TypeError`.

# Checklist
- [x] I have read the CONTRIBUTING.md document.
- [x] I have performed a self-review of my own code.
- [ ] I have commented my code, particularly in hard-to-understand areas. *(N/A – docs only)*
- [ ] I have added tests that prove my fix is effective or that my feature works. *(N/A – docs only)*
- [ ] New and existing unit tests pass locally with my changes. *(N/A – docs only)*
- [x] I have manually tested my changes end-to-end.
- [ ] Any dependent changes have been merged and published in downstream modules. *(N/A)*

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3875 from krishna-dhulipalla:docs/fix-adk-run_async-example 83fc5b430690b63b8b7bf1025ef03b0761264751
PiperOrigin-RevId: 842952362
2025-12-10 17:24:58 -08:00
..

Agent with Long-Running Tools

This example demonstrates an agent using a long-running tool (ask_for_approval).

Key Flow for Long-Running Tools

  1. Initial Call: The agent calls the long-running tool (e.g., ask_for_approval).

  2. Initial Tool Response: The tool immediately returns an initial response, typically indicating a "pending" status and a way to track the request (e.g., a ticket-id). This is sent back to the agent as a types.FunctionResponse (usually processed internally by the runner and then influencing the agent's next turn).

  3. Agent Acknowledges: The agent processes this initial response and usually informs the user about the pending status.

  4. External Process/Update: The long-running task progresses externally (e.g., a human approves the request).

  5. Crucial Step: Provide Updated Tool Response:

    • Once the external process completes or updates, your application must construct a new types.FunctionResponse.
    • This response should use the same id and name as the original FunctionCall to the long-running tool.
    • The response field within this types.FunctionResponse should contain the updated data (e.g., {'status': 'approved', ...}).
    • Send this types.FunctionResponse back to the agent as a part within a new message using role="user".
    # Example: After external approval
    updated_tool_output_data = {
        "status": "approved",
        "ticketId": ticket_id, # from original call
        # ... other relevant updated data
    }
    
    updated_function_response_part = types.Part(
        function_response=types.FunctionResponse(
            id=long_running_function_call.id,   # Original call ID
            name=long_running_function_call.name, # Original call name
            response=updated_tool_output_data,
        )
    )
    
    # Send this back to the agent
    async for _ in runner.run_async(
        # ... session_id, user_id ...
        new_message=types.Content(
            parts=[updated_function_response_part], role="user"
        ),
    ):
        pass  # exhaust generator (or handle events)
    
  6. Agent Acts on Update: The agent receives this message containing the types.FunctionResponse and, based on its instructions, proceeds with the next steps (e.g., calling another tool like reimburse).

Why is this important? The agent relies on receiving this subsequent types.FunctionResponse (provided in a message with role="user" containing the specific Part) to understand that the long-running task has concluded or its state has changed. Without it, the agent will remain unaware of the outcome of the pending task.