Skip to content

Elicittion (Ambiguity Resolution) Feature in Google ADK.#5670

Open
suddhasatwabhaumik wants to merge 1 commit into
google:mainfrom
suddhasatwabhaumik:feat/agent_elicitation
Open

Elicittion (Ambiguity Resolution) Feature in Google ADK.#5670
suddhasatwabhaumik wants to merge 1 commit into
google:mainfrom
suddhasatwabhaumik:feat/agent_elicitation

Conversation

@suddhasatwabhaumik
Copy link
Copy Markdown

Note: read the contribution guide before creating this pull request.

Link to Issue or Description of Change

Problem:
When building conversational agents, users often provide ambiguous or incomplete prompts (e.g., "Book a hotel in Tokyo" without specifying dates/guests, or "Show me active customers" in an NL2SQL interface without specifying filters). Prior to this change, agents had no structured, out-of-the-box way to dynamically request clarification (elicitation) from users without either:

  1. Crashing due to missing mandatory parameters.
  2. Speculating or hallucinating placeholder arguments.
  3. Relying on heavy, complex backend/server-side session state stores to persist conversational history across turns.

Solution:
We implemented the Stateless Tiered Elicitation Pattern in the Google ADK. This feature enables fully stateless, interactive, multi-turn ambiguity resolution. The runner packages the current turn state into a hidden_context payload returned to the client; on the next turn, the runner transparently rehydrates this context, passing the completed inputs back to the model.

Key architectural additions:

  • Protocol & Schemas (a2a.py): Added AgentResponseStatus.ELICITATION_REQUIRED and defined the ElicitationData Pydantic schema to encapsulate context_snapshot and turn_count.
  • Flow Orchestration Processors (elicitation.py): Implemented _ElicitationRequestProcessor and _ElicitationResponseProcessor within the SingleFlow request/response pipeline to handle transparent state rehydration and elicitation interception.
  • Standardized Elicitation Tooling (elicitation_tool.py): Created TriggerElicitationTool, which is conditionally injected by the ADK runner. The model invokes this tool to signal exactly which entity slots are missing.
  • First-Class Configuration (llm_agent.py, llm_agent_config.py): Added allow_elicitation (bool) and elicitation_max_turns (int) configuration properties to allow developers fine-grained control.
  • Automatic Loop Prevention: Integrated a strict turn-counter validator inside the request processor; if turn_count exceeds elicitation_max_turns, it raises a RuntimeError to abort infinite execution loops gracefully.
  • Developer Documentation & Runnable Sample (contributing/samples/stateless_elicitation/): Built a fully runnable travel booking assistant sample demonstrating multi-turn rehydration, detailed architectural sequence diagrams, and critical security guidelines (preventing PII leakage and state tampering).

Testing Plan

We have implemented extensive automated unit and integration tests to verify this feature end-to-end under multiple conditions.

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Summary of passed pytest results (PYTHONPATH=src .venv/bin/pytest tests/unittests/flows/llm_flows/test_elicitation.py):

============================= test session starts ==============================
platform darwin -- Python 3.11.0, pytest-8.1.1, pluggy-1.4.0
rootdir: /Users/suddhasatwa/Documents/AUTOMATIONS/30-GOOGLE-ADK-CONTRIB/adk-python
collected 7 items

tests/unittests/flows/llm_flows/test_elicitation.py .......              [100%]

============================== 7 passed in 0.87s ===============================

Manual End-to-End (E2E) Tests:

We built a dedicated E2E integration test using the AgentEvaluator framework.

  • Integration Test File: tests/integration/test_elicitation_flow.py
  • Fixture Agent: tests/integration/fixture/elicitation_agent/
  • Results: Integration tests run and pass successfully in authentic environments, and gracefully skip in test environments missing required cloud/API keys or evaluation dependencies to prevent pipeline breakages.

Local runner E2E verification of the new sample (contributing/samples/stateless_elicitation/main.py):

  • Gracefully intercepts missing environment variables, prompting the developer with actionable configuration instructions:
    Error: Missing required LLM credentials.
    Please set the GOOGLE_API_KEY environment variable before running this sample.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

This feature is highly valuable for many real-world cross-industry use cases like the following examples, and many more:

  1. NL2SQL Query Interfaces: Allowing agents to clarify ambiguous user terms (e.g., clarifying "active" or "high-value") before executing database queries, dramatically reducing compute overhead and preventing bad SQL generations.
  2. Automated Form Processing: Streamlining transactional workflows without keeping heavy session tracking databases.

@suddhasatwabhaumik
Copy link
Copy Markdown
Author

Hi @wukath

Please have a look at this PR, or recommend whom I can reach out to for review/approval.

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant