Repository navigation
feat: support structured output in JSON Schema over A2A DataPart - #2890
Conversation
This comment has been minimized.
This comment has been minimized.
| A2ADataPartMetadataIsLongRunningKey = "is_long_running" | ||
| A2ADataPartMetadataTypeFunctionCall = "function_call" | ||
| A2ADataPartMetadataTypeFunctionResponse = "function_response" | ||
| OutputSchemaSHA256MetadataKey = "kagent.dev/output-schema-sha256" |
There was a problem hiding this comment.
We used to have a KagentMetadata fn which prepended this key, do we still have that?
There was a problem hiding this comment.
That function uses the kagent_ prefix for ADK function metadata these are public A2A result metadata like kagent.dev/timeline-position
There was a problem hiding this comment.
Maybe we should still have functions to make sure they use the correct prefix. Also maybe the prefix should be kagent.dev/a2a?
There was a problem hiding this comment.
I agree, I'll add both. I also think it's worth doing a follow-up to review the metadata before we do a stable release so we can still centralize and change them (e.g. we will want to change the timeline position above as well, and some legacy ADK metadata are no longer necessary, and probably renaming the adk_ and kagent_ ones)
There was a problem hiding this comment.
I have a follow up for A2A metadata in #2902 if you want to take a quick look first, not fully ready for review yet
b36d743 to
5521dfa
Compare
Charlesthebird
left a comment
There was a problem hiding this comment.
This automated review is a first pass. A manual review will follow once the blockers are addressed.
Two things block merge, both in transformStructuredOutput. The finish-reason guard added this round rejects an empty reason, which is what ADK's set_model_response path produces — the Gemini-with-tools case in the third screenshot. Separately, a HITL approval request still reaches the transform, where it has no text to validate and fails the task.
⚠️ What I checked
- ✅
AfterEventCallbackfires only for a non-nil A2A event, and its error becomes a failed task —adk@v2.3.0 server/adka2a/v2/executor.go:366-375. - ✅ The CEL rule making
outputSchemaandoutputSchemaFrommutually exclusive is onAgentTemplateSpec. - ✅
outputSchemaFromis added to the provenance ConfigMap set, so editing the ConfigMap recompiles the revision. - ✅ Cycle detection uses pointer identity after
$refresolution, soA → B → Ais caught. - ✅ The canonical form re-marshals through
map[string]any, so the digest is stable across key order. ⚠️ IsFinalResponse()short-circuits to true onLongRunningToolIDsandSkipSummarization—adk@v2.3.0 session/session.go:225.⚠️ ADK builds theset_model_responsefinal event with no finish reason —adk@v2.3.0 internal/llminternal/outputschema_processor.go:67-76.
🤖 written by Claude
Charlesthebird
left a comment
There was a problem hiding this comment.
The UI changes here LGTM - thanks for the screenshots! I also kicked off an automated review.
And I added #2894 as a follow-up issue since the chat message part renderers might be a good place for extension points.
|
Thanks for the review @Charlesthebird and I've also verified now structured output works with HITL: Screen.Recording.2026-09-22.at.3.05.55.PM.mov |
| func NewKAgentExecutor(cfg KAgentExecutorConfig) *KAgentExecutor { | ||
| // NewKAgentExecutor creates a KAgentExecutor from config. It returns an error if | ||
| // the configured output schema cannot be prepared for runtime validation. | ||
| func NewKAgentExecutor(cfg KAgentExecutorConfig) (*KAgentExecutor, error) { |
There was a problem hiding this comment.
#2896 also rewrites this callback, conflicts on merge
There was a problem hiding this comment.
Hey @mesutoezdil can you avoid leaving this type of comments since they're not too constructive. Merge conflicts are natural and authors are expected to rebase on top, this simply adds more noise during reviews. Unless the changes across PRs are going in opposite directions, in which case it might be worthwhile to bring the author's attention to it and drive some discussion, otherwise this type of comment don't add any value, as in the case here and in a few other PRs that you left similar comments before.
There was a problem hiding this comment.
fair point, noted 👍🏽 thx for feedback
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
…ntent config and adk validation Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>
1dbd99c to
c1fb364
Compare
…-fail-task-on-max-tokens NewKAgentExecutor now returns an error too; the output-limit test checks it. Signed-off-by: Jose Armesto <github@armesto.net>
…ent-dev#2890) ## Summary > This feature is only supported in Kagent's own harness, not yet in Claude / Codex - Add inline and ConfigMap-backed output schemas to ADK agent templates. - Validate schemas against a portable provider-compatible JSON Schema profile. - Support structured output with tools across OpenAI, Anthropic, Bedrock, and Gemini through ADK. - Validate final responses and publish them as JSON A2A artifacts with schema metadata. - Add unit and E2E coverage for tool calls and partial streaming responses. - Document the structured-output design and provider behavior. - Relevant UI changes to configure output mode, display structured output, etc ## Testing - Unit and E2E tests - Manual testing on OpenAI (Chat completion + Responses), Gemini (API), Claude (Bedrock) - Tested with both tool using and structured output --------- Signed-off-by: Jet Chiang <pokyuen.jetchiang-ext@solo.io>



Summary
Testing