Skip to content

[AI Bundle][Platform] Make the structured output validation groups configurable - #2527

Open
marco-jouwweb wants to merge 1 commit into
symfony:mainfrom
marco-jouwweb:platform-validator-subscriber-groups
Open

marco-jouwweb wants to merge 1 commit into
symfony:mainfrom
marco-jouwweb:platform-validator-subscriber-groups

Conversation

@marco-jouwweb

@marco-jouwweb marco-jouwweb commented Sep 14, 2026

Copy link
Copy Markdown
Contributor
Q A
Bug fix? no
New feature? yes
Docs? yes
Issues -
License MIT

ValidatorSubscriber always validates the populated structured output object in the Default validation group. When the target class is an existing domain object that already carries Default constraints for other purposes (forms, API input), the only ways out are decorating the subscriber or moving every existing constraint to custom groups. As discussed with @chr-hertel on Slack, this PR makes the groups configurable instead.

Platform

ValidatorSubscriber gets an optional groups argument accepting the same values as ValidatorInterface::validate() (a group name, a list of groups, or a GroupSequence). It is passed through ValidatorResultConverter to the buffered validation call and to PartialObjectStreamListener::setValidator(), so the final object of a streamed structured output is validated in the same groups.

$dispatcher->addSubscriber(new PlatformSubscriber());
$dispatcher->addSubscriber(new ValidatorSubscriber(groups: ['ai']));

A single call can override them with the validation_groups option. Like PlatformSubscriber does for response_format, the subscriber consumes the option on InvocationEvent so it is never merged into the provider request, and applies it on ResultEvent:

$platform->invoke('gpt-4o', $messages, [
    'response_format' => Invoice::class,
    'validation_groups' => ['ai', 'strict'],
]);

AI Bundle

New structured_output.validation_groups option, applied to the ai.platform.structured_output.validator_subscriber service as the default groups. It is a top-level node (not under platform, whose children are the bridge types). An empty list keeps the current behavior; configuring groups while symfony/validator is missing throws the same kind of "requires package" exception as the other optional integrations.

ai:
    structured_output:
        validation_groups: ['ai']
final class Invoice
{
    #[Assert\NotBlank(groups: ['ai'])]
    public string $customer = '';

    #[Assert\Positive] // "Default" group only, skipped for model output
    public int $total = 0;
}

Notes

  • All new parameters are optional and last, so there is no BC break; null keeps validating in the validator's default group.
  • Out of scope on purpose: ValidatorConstraintsDescriber still describes constraints of every group in the generated JSON schema.

🤖 Generated with Claude Code

@carsonbot carsonbot added AI Bundle Issues & PRs about the AI integration bundle Feature New feature Platform Issues & PRs about the AI Platform component Status: Needs Review labels Sep 14, 2026
@carsonbot carsonbot changed the title [Platform][AI Bundle] Make the structured output validation groups configurable [AI Bundle][Platform] Make the structured output validation groups configurable Sep 14, 2026
…nfigurable

`ValidatorSubscriber` always validated the populated structured output
object in the `Default` validation group, which collides with domain
objects that already carry `Default` constraints for other purposes.

Add an optional `groups` argument to `ValidatorSubscriber`, passed through
`ValidatorResultConverter` to the buffered validation call and to
`PartialObjectStreamListener` for the final object of a streamed result.
A `validation_groups` invocation option overrides them for a single call;
the subscriber consumes it so it is never forwarded to the provider.
The AI Bundle exposes the default as `ai.structured_output.validation_groups`.
@marco-jouwweb
marco-jouwweb force-pushed the platform-validator-subscriber-groups branch from c28d82f to 0dbe637 Compare September 14, 2026 11:45
private string|GroupSequence|array|null $invocationGroups = null;

/**
* @param string|GroupSequence|array<string|GroupSequence>|null $groups The validation groups to validate the structured output in unless the "validation_groups" option is passed, or null for the validator's default group

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not very happy with this union type.. WDYT?

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

Labels

AI Bundle Issues & PRs about the AI integration bundle Feature New feature Platform Issues & PRs about the AI Platform component Status: Needs Review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants