google / google/adk-python

Add `response_json_schema` support to `RunConfig` for per-request structured output

Đang mở
#3,866 5 bình luận 0 reaction 2 người được giao Được @wuliang229 nhận Xem trên GitHub
a2a needs review
Ngôn ngữ chính
Python
Star
21.5k
Fork
4k
Merge trung bình
1 ngày 14 giờ
Pull request đã merge (30 ngày)
37

Mô tả

**Is your feature request related to a problem? Please describe.**

When building A2A (Agent-to-Agent) servers using ADK, the calling agent can request structured output by including a JSON schema in the message metadata, per the [A2A Structured Data Exchange
spec](https://google.github.io/A2A/#/documentation?id=structured-data-exchange):

```json
{
"message": {
"parts": [{
"text": "Show me a list of my open IT tickets",
"metadata": {
"mediaType": "application/json",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"ticketNumber": { "type": "string" },
"description": { "type": "string" }
}
}
}
}
}]
}
}
```

The schema is per-request, not per-agent. Different requests to the same agent may request different output schemas (or no schema at all).

Currently, there's no direct way to pass a response schema through `Runner.run_async()`. The available options are:
1. `LlmAgent.output_schema` - Set at agent creation time, not per-request
2. `LlmAgent.generate_content_config` - Also set at agent creation time
3. `before_model_callback` / Plugin - Works, but requires storing the schema in session state and reading it back in a callback, which is indirect

**Describe the solution you'd like**

Add optional fields to `RunConfig`:

```python
class RunConfig(BaseModel):
# ...

response_json_schema: Optional[dict[str, Any]] = None
"""JSON Schema for structured output. When set, configures the LLM
to return responses conforming to this schema."""

response_mime_type: Optional[str] = None
"""MIME type for the response. Defaults to 'application/json' when
response_json_schema is set."""
```

Then in `BaseLlmFlow`, apply these to the `LlmRequest.config` before calling the LLM:

```python
if invocation_context.run_config and invocation_context.run_config.response_json_schema:
llm_request.config = llm_request.config or types.GenerateContentConfig()
llm_request.config.response_json_schema = invocation_context.run_config.response_json_schema
llm_request.config.response_mime_type = (
invocation_context.run_config.response_mime_type or "application/json"
)
```

Example Usage

```python
schema = {
"type": "object",
"properties": {
"answer": {"type": "string"},
"confidence": {"type": "number"}
}
}

async for event in runner.run_async(
user_id="user-123",
session_id="session-456",
new_message=content,
run_config=RunConfig(response_json_schema=schema),
):
# LLM responses will conform to the schema
...
```

**Describe alternatives you've considered**

Using a plugin/callback. This works but requires:
1. Storing the schema in session state before calling `run_async()`
2. Creating a plugin that reads from session state in `before_model_callback`
3. Setting it on `llm_request.config.response_json_schema`

This is indirect and couples the schema to session state rather than the request itself.

**Additional context**

This started with me trying to send A2A requests to [kagent](https://kagent.dev/) (which uses ADK under the hood) including as the documentation says. But the schema information is dropped by ADK.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.