Skip to content

Commit 1165a70

Browse files
committed
feature #936 [Platform][Anthropic] Add support for structured output on Claude API (chr-hertel)
This PR was merged into the main branch. Discussion ---------- [Platform][Anthropic] Add support for structured output on Claude API | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Docs? | no | Issues | | License | MIT Adding support for recently released beta feature of structured output on Anthropic API, see https://claude.com/blog/structured-outputs-on-the-claude-developer-platform Commits ------- e926440 Add support for structured output on Claude API
2 parents d434d70 + e926440 commit 1165a70

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\AI\Agent\Agent;
13+
use Symfony\AI\Agent\Toolbox\AgentProcessor;
14+
use Symfony\AI\Agent\Toolbox\Tool\Clock;
15+
use Symfony\AI\Agent\Toolbox\Toolbox;
16+
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
17+
use Symfony\AI\Platform\Message\Message;
18+
use Symfony\AI\Platform\Message\MessageBag;
19+
use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber;
20+
use Symfony\Component\Clock\Clock as SymfonyClock;
21+
use Symfony\Component\EventDispatcher\EventDispatcher;
22+
23+
require_once dirname(__DIR__).'/bootstrap.php';
24+
25+
$dispatcher = new EventDispatcher();
26+
$dispatcher->addSubscriber(new PlatformSubscriber());
27+
28+
$platform = PlatformFactory::create(env('ANTHROPIC_API_KEY'), http_client(), eventDispatcher: $dispatcher);
29+
30+
$clock = new Clock(new SymfonyClock());
31+
$toolbox = new Toolbox([$clock], logger: logger());
32+
$toolProcessor = new AgentProcessor($toolbox);
33+
$agent = new Agent($platform, 'claude-sonnet-4-5-20250929', [$toolProcessor], [$toolProcessor]);
34+
35+
$messages = new MessageBag(Message::ofUser('What date and time is it?'));
36+
$result = $agent->call($messages, ['response_format' => [
37+
'type' => 'json_schema',
38+
'json_schema' => [
39+
'name' => 'clock',
40+
'strict' => true,
41+
'schema' => [
42+
'type' => 'object',
43+
'properties' => [
44+
'date' => ['type' => 'string', 'description' => 'The current date in the format YYYY-MM-DD.'],
45+
'time' => ['type' => 'string', 'description' => 'The current time in the format HH:MM:SS.'],
46+
],
47+
'required' => ['date', 'time'],
48+
'additionalProperties' => false,
49+
],
50+
],
51+
]]);
52+
53+
dump($result->getContent());
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\AI\Fixtures\StructuredOutput\MathReasoning;
13+
use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory;
14+
use Symfony\AI\Platform\Message\Message;
15+
use Symfony\AI\Platform\Message\MessageBag;
16+
use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber;
17+
use Symfony\Component\EventDispatcher\EventDispatcher;
18+
19+
require_once dirname(__DIR__).'/bootstrap.php';
20+
21+
$dispatcher = new EventDispatcher();
22+
$dispatcher->addSubscriber(new PlatformSubscriber());
23+
24+
$platform = PlatformFactory::create(env('ANTHROPIC_API_KEY'), http_client(), eventDispatcher: $dispatcher);
25+
$messages = new MessageBag(
26+
Message::forSystem('You are a helpful math tutor. Guide the user through the solution step by step.'),
27+
Message::ofUser('how can I solve 8x + 7 = -23'),
28+
);
29+
30+
$result = $platform->invoke('claude-sonnet-4-5-20250929', $messages, ['response_format' => MathReasoning::class]);
31+
32+
dump($result->asObject());

src/platform/src/Bridge/Anthropic/ModelClient.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ public function request(Model $model, array|string $payload, array $options = []
4747
$options['tool_choice'] = ['type' => 'auto'];
4848
}
4949

50+
if (isset($options['response_format'])) {
51+
$options['beta_features'][] = 'structured-outputs-2025-11-13';
52+
$options['output_format'] = [
53+
'type' => 'json_schema',
54+
'schema' => $options['response_format']['json_schema']['schema'] ?? [],
55+
];
56+
unset($options['response_format']);
57+
}
58+
5059
if (isset($options['beta_features']) && \is_array($options['beta_features']) && \count($options['beta_features']) > 0) {
5160
$headers['anthropic-beta'] = implode(',', $options['beta_features']);
5261
unset($options['beta_features']);

0 commit comments

Comments
 (0)