From fac67f634f1558a54080ba0a9aead9917b70afd1 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 15:33:48 +0200 Subject: [PATCH 01/15] [Agent] Add Platform tool wrapper for using platforms as tools Introduces a new Platform tool that wraps any PlatformInterface instance, allowing agents to use specialized platforms as tools. This enables scenarios like an OpenAI agent using ElevenLabs for speech-to-text. - Add Platform tool class with support for Text, Audio, and Image results - Add OpenAI example demonstrating ElevenLabs platform as tool - Add documentation explaining the concept and usage - Update demo AI Bundle configuration with platform tool examples --- demo/config/packages/ai.yaml | 20 ++++++ examples/openai/README-platform-as-tool.md | 80 ++++++++++++++++++++++ examples/openai/platform-as-tool.php | 54 +++++++++++++++ src/agent/src/Toolbox/Tool/Platform.php | 57 +++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 examples/openai/README-platform-as-tool.md create mode 100644 examples/openai/platform-as-tool.php create mode 100644 src/agent/src/Toolbox/Tool/Platform.php diff --git a/demo/config/packages/ai.yaml b/demo/config/packages/ai.yaml index d7117a68f..b2a0cf29d 100644 --- a/demo/config/packages/ai.yaml +++ b/demo/config/packages/ai.yaml @@ -2,6 +2,8 @@ ai: platform: openai: api_key: '%env(OPENAI_API_KEY)%' + elevenlabs: + api_key: '%env(ELEVEN_LABS_API_KEY)%' agent: blog: model: 'gpt-4o-mini' @@ -50,6 +52,15 @@ ai: model: 'gpt-4o-mini' prompt: 'You are a helpful general assistant. Assist users with any questions or tasks they may have.' tools: false + elevenlabs_audio: + model: 'gpt-4o-mini' + prompt: 'You are a helpful assistant with access to speech-to-text capabilities via ElevenLabs.' + tools: + # Platform as tool 🚀 + - platform: 'elevenlabs' + model: 'scribe_v1' + name: 'transcribe_audio' + description: 'Transcribes audio files to text using ElevenLabs.' multi_agent: support: orchestrator: 'orchestrator' @@ -91,6 +102,15 @@ services: Symfony\AI\Store\Document\Loader\RssFeedLoader: ~ Symfony\AI\Store\Document\Transformer\TextTrimTransformer: ~ + # Example: Using a Platform as a Tool + # This demonstrates how to wrap any platform as a tool that can be used by agents + app.tool.elevenlabs_transcription: + class: 'Symfony\AI\Agent\Toolbox\Tool\Platform' + arguments: + $platform: '@ai.platform.elevenlabs' + $model: 'scribe_v1' + $options: [] + app.filter.week_of_symfony: class: 'Symfony\AI\Store\Document\Filter\TextContainsFilter' arguments: diff --git a/examples/openai/README-platform-as-tool.md b/examples/openai/README-platform-as-tool.md new file mode 100644 index 000000000..05fbb9bfc --- /dev/null +++ b/examples/openai/README-platform-as-tool.md @@ -0,0 +1,80 @@ +# Platform as Tool + +This example demonstrates how to use one AI platform as a tool within an agent powered by another platform. + +## Concept + +Just like agents can use other agents as tools, platforms can also be wrapped as tools. This enables powerful compositions where: + +- An OpenAI-based agent can use ElevenLabs for speech-to-text +- An Anthropic-based agent can use OpenAI's DALL-E for image generation +- Any platform's specialized capabilities can be leveraged by agents using different platforms + +## Example: Speech-to-Text with ElevenLabs + +The `platform-as-tool.php` example shows an OpenAI agent that uses ElevenLabs' speech-to-text capabilities: + +```php +use Symfony\AI\Agent\Toolbox\Tool\Platform; + +// Create ElevenLabs platform +$elevenLabsPlatform = ElevenLabsPlatformFactory::create( + apiKey: env('ELEVEN_LABS_API_KEY'), + httpClient: http_client() +); + +// Wrap it as a tool +$speechToText = new Platform($elevenLabsPlatform, 'scribe_v1'); + +// Add to agent's toolbox +$toolbox = new Toolbox([$speechToText]); +``` + +## AI Bundle Configuration + +In a Symfony application using the AI Bundle, you can configure platforms as tools: + +```yaml +ai: + platform: + openai: + api_key: '%env(OPENAI_API_KEY)%' + elevenlabs: + api_key: '%env(ELEVEN_LABS_API_KEY)%' + + agent: + my_agent: + model: 'gpt-4o-mini' + tools: + # Use platform as tool via configuration + - platform: 'elevenlabs' + model: 'scribe_v1' + name: 'transcribe_audio' + description: 'Transcribes audio files to text' +``` + +Or define it as a service: + +```yaml +services: + app.tool.elevenlabs_transcription: + class: 'Symfony\AI\Agent\Toolbox\Tool\Platform' + arguments: + $platform: '@ai.platform.elevenlabs' + $model: 'scribe_v1' + $options: [] +``` + +## Use Cases + +1. **Speech-to-Text**: Use ElevenLabs or Whisper for transcription while using another platform for reasoning +2. **Image Generation**: Use DALL-E or Stable Diffusion for images while using another platform for chat +3. **Specialized Models**: Leverage platform-specific models (e.g., code generation, embeddings) from any agent +4. **Multi-Modal Workflows**: Combine different platforms' strengths in a single agent workflow + +## Benefits + +- **Best Tool for the Job**: Choose the best platform for each specific task +- **Flexibility**: Mix and match platforms based on cost, performance, or features +- **Composability**: Build complex AI systems by combining multiple platforms +- **Simplicity**: Use the same tool interface whether wrapping agents or platforms diff --git a/examples/openai/platform-as-tool.php b/examples/openai/platform-as-tool.php new file mode 100644 index 000000000..0abc97cc4 --- /dev/null +++ b/examples/openai/platform-as-tool.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\AI\Agent\Agent; +use Symfony\AI\Agent\Toolbox\AgentProcessor; +use Symfony\AI\Agent\Toolbox\Tool\Platform; +use Symfony\AI\Agent\Toolbox\Toolbox; +use Symfony\AI\Platform\Bridge\ElevenLabs\PlatformFactory as ElevenLabsPlatformFactory; +use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; +use Symfony\AI\Platform\Message\Content\Audio; +use Symfony\AI\Platform\Message\Message; +use Symfony\AI\Platform\Message\MessageBag; + +require_once dirname(__DIR__).'/bootstrap.php'; + +// Create the main OpenAI platform +$openAiPlatform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client()); + +// Create ElevenLabs platform as a tool for speech-to-text +$elevenLabsPlatform = ElevenLabsPlatformFactory::create( + apiKey: env('ELEVEN_LABS_API_KEY'), + httpClient: http_client() +); + +// Wrap ElevenLabs platform as a tool +$speechToText = new Platform($elevenLabsPlatform, 'scribe_v1'); + +// Create toolbox with the platform tool +$toolbox = new Toolbox([$speechToText], logger: logger()); +$processor = new AgentProcessor($toolbox); + +// Create agent with OpenAI platform but with ElevenLabs tool available +$agent = new Agent($openAiPlatform, 'gpt-4o-mini', [$processor], [$processor], logger: logger()); + +// The agent can now use ElevenLabs for speech-to-text while using OpenAI for reasoning +$audioPath = dirname(__DIR__, 2).'/fixtures/audio.mp3'; +$messages = new MessageBag( + Message::ofUser(sprintf( + 'I have an audio file. Please transcribe it and tell me what it says. Audio: %s', + Audio::fromFile($audioPath) + )) +); + +$result = $agent->call($messages); + +echo $result->getContent().\PHP_EOL; diff --git a/src/agent/src/Toolbox/Tool/Platform.php b/src/agent/src/Toolbox/Tool/Platform.php new file mode 100644 index 000000000..011d896a2 --- /dev/null +++ b/src/agent/src/Toolbox/Tool/Platform.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\AI\Agent\Toolbox\Tool; + +use Symfony\AI\Platform\PlatformInterface; +use Symfony\AI\Platform\Result\AudioResult; +use Symfony\AI\Platform\Result\ImageResult; +use Symfony\AI\Platform\Result\TextResult; + +/** + * Wraps a Platform instance as a tool, allowing agents to use specialized platforms for specific tasks. + * + * This enables scenarios where an agent using one platform (e.g., OpenAI) can leverage + * another platform (e.g., ElevenLabs for speech-to-text) as a tool. + * + * @author Oskar Stark + */ +final readonly class Platform +{ + /** + * @param array $options + */ + public function __construct( + private PlatformInterface $platform, + private string $model, + private array $options = [], + ) { + } + + /** + * @param array|string|object $input the input to pass to the platform + */ + public function __invoke(array|string|object $input): string + { + $result = $this->platform->invoke( + $this->model, + $input, + $this->options, + )->await(); + + return match (true) { + $result instanceof TextResult => $result->getContent(), + $result instanceof AudioResult => $result->getText() ?? base64_encode($result->getAudio()), + $result instanceof ImageResult => $result->getText() ?? base64_encode($result->getImage()), + default => throw new \LogicException(\sprintf('Unsupported result type "%s".', $result::class)), + }; + } +} From 9a47a8af83757bdac497ead3cf302006fd2bb0d3 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 15:34:16 +0200 Subject: [PATCH 02/15] [Agent] Remove README-platform-as-tool.md --- examples/openai/README-platform-as-tool.md | 80 ---------------------- 1 file changed, 80 deletions(-) delete mode 100644 examples/openai/README-platform-as-tool.md diff --git a/examples/openai/README-platform-as-tool.md b/examples/openai/README-platform-as-tool.md deleted file mode 100644 index 05fbb9bfc..000000000 --- a/examples/openai/README-platform-as-tool.md +++ /dev/null @@ -1,80 +0,0 @@ -# Platform as Tool - -This example demonstrates how to use one AI platform as a tool within an agent powered by another platform. - -## Concept - -Just like agents can use other agents as tools, platforms can also be wrapped as tools. This enables powerful compositions where: - -- An OpenAI-based agent can use ElevenLabs for speech-to-text -- An Anthropic-based agent can use OpenAI's DALL-E for image generation -- Any platform's specialized capabilities can be leveraged by agents using different platforms - -## Example: Speech-to-Text with ElevenLabs - -The `platform-as-tool.php` example shows an OpenAI agent that uses ElevenLabs' speech-to-text capabilities: - -```php -use Symfony\AI\Agent\Toolbox\Tool\Platform; - -// Create ElevenLabs platform -$elevenLabsPlatform = ElevenLabsPlatformFactory::create( - apiKey: env('ELEVEN_LABS_API_KEY'), - httpClient: http_client() -); - -// Wrap it as a tool -$speechToText = new Platform($elevenLabsPlatform, 'scribe_v1'); - -// Add to agent's toolbox -$toolbox = new Toolbox([$speechToText]); -``` - -## AI Bundle Configuration - -In a Symfony application using the AI Bundle, you can configure platforms as tools: - -```yaml -ai: - platform: - openai: - api_key: '%env(OPENAI_API_KEY)%' - elevenlabs: - api_key: '%env(ELEVEN_LABS_API_KEY)%' - - agent: - my_agent: - model: 'gpt-4o-mini' - tools: - # Use platform as tool via configuration - - platform: 'elevenlabs' - model: 'scribe_v1' - name: 'transcribe_audio' - description: 'Transcribes audio files to text' -``` - -Or define it as a service: - -```yaml -services: - app.tool.elevenlabs_transcription: - class: 'Symfony\AI\Agent\Toolbox\Tool\Platform' - arguments: - $platform: '@ai.platform.elevenlabs' - $model: 'scribe_v1' - $options: [] -``` - -## Use Cases - -1. **Speech-to-Text**: Use ElevenLabs or Whisper for transcription while using another platform for reasoning -2. **Image Generation**: Use DALL-E or Stable Diffusion for images while using another platform for chat -3. **Specialized Models**: Leverage platform-specific models (e.g., code generation, embeddings) from any agent -4. **Multi-Modal Workflows**: Combine different platforms' strengths in a single agent workflow - -## Benefits - -- **Best Tool for the Job**: Choose the best platform for each specific task -- **Flexibility**: Mix and match platforms based on cost, performance, or features -- **Composability**: Build complex AI systems by combining multiple platforms -- **Simplicity**: Use the same tool interface whether wrapping agents or platforms From 02fb8e37a7f093a772c1bd47a1c68e84b30a2535 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 15:36:29 +0200 Subject: [PATCH 03/15] [AiBundle] Add configuration support for platform tools Platforms can now be configured as tools in agent definitions: ai: agent: my_agent: tools: - platform: 'elevenlabs' model: 'scribe_v1' name: 'transcribe_audio' description: 'Transcribes audio files to text' options: [] This allows agents to use specialized platforms as tools, enabling scenarios like an OpenAI agent using ElevenLabs for speech-to-text. --- src/ai-bundle/config/options.php | 29 +++++++++++++++++++++++++++-- src/ai-bundle/src/AiBundle.php | 12 ++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/ai-bundle/config/options.php b/src/ai-bundle/config/options.php index 74322d79c..16035cf8b 100644 --- a/src/ai-bundle/config/options.php +++ b/src/ai-bundle/config/options.php @@ -391,6 +391,12 @@ ->children() ->stringNode('service')->cannotBeEmpty()->end() ->stringNode('agent')->cannotBeEmpty()->end() + ->stringNode('platform')->cannotBeEmpty()->end() + ->stringNode('model')->cannotBeEmpty()->end() + ->arrayNode('options') + ->info('Options to pass to the platform') + ->scalarPrototype()->end() + ->end() ->stringNode('name')->end() ->stringNode('description')->end() ->stringNode('method')->end() @@ -402,8 +408,27 @@ }) ->end() ->validate() - ->ifTrue(static fn ($v) => !(empty($v['agent']) xor empty($v['service']))) - ->thenInvalid('Either "agent" or "service" must be configured, and never both.') + ->ifTrue(static function ($v) { + $count = 0; + if (!empty($v['agent'])) { + ++$count; + } + if (!empty($v['service'])) { + ++$count; + } + if (!empty($v['platform'])) { + ++$count; + } + + return 1 !== $count; + }) + ->thenInvalid('Exactly one of "agent", "service", or "platform" must be configured.') + ->end() + ->validate() + ->ifTrue(static function ($v) { + return !empty($v['platform']) && empty($v['model']); + }) + ->thenInvalid('When "platform" is configured, "model" must also be provided.') ->end() ->end() ->end() diff --git a/src/ai-bundle/src/AiBundle.php b/src/ai-bundle/src/AiBundle.php index 71e948f46..3df69fe31 100644 --- a/src/ai-bundle/src/AiBundle.php +++ b/src/ai-bundle/src/AiBundle.php @@ -27,6 +27,7 @@ use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Agent\Toolbox\FaultTolerantToolbox; use Symfony\AI\Agent\Toolbox\Tool\Agent as AgentTool; +use Symfony\AI\Agent\Toolbox\Tool\Platform as PlatformTool; use Symfony\AI\Agent\Toolbox\ToolFactory\ChainFactory; use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory; use Symfony\AI\AiBundle\DependencyInjection\ProcessorCompilerPass; @@ -637,6 +638,17 @@ private function processAgentConfig(string $name, array $config, ContainerBuilde if (isset($tool['agent'])) { $tool['name'] ??= $tool['agent']; $tool['service'] = \sprintf('ai.agent.%s', $tool['agent']); + } elseif (isset($tool['platform'])) { + $tool['name'] ??= $tool['platform'].'_'.$tool['model']; + $platformReference = new Reference(\sprintf('ai.platform.%s', $tool['platform'])); + $platformWrapperDefinition = new Definition(PlatformTool::class, [ + $platformReference, + $tool['model'], + $tool['options'] ?? [], + ]); + $wrapperServiceId = 'ai.toolbox.'.$name.'.platform_wrapper.'.$tool['name']; + $container->setDefinition($wrapperServiceId, $platformWrapperDefinition); + $tool['service'] = $wrapperServiceId; } $reference = new Reference($tool['service']); // We use the memory factory in case method, description and name are set From 6763b5203731cbffb12bffa39310fc7eb37d8ed0 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 15:39:25 +0200 Subject: [PATCH 04/15] [Agent] Simplify Platform tool by using asText() method Removed explicit await() and result type matching by using the ResultPromise::asText() convenience method which handles the await internally and extracts text content directly. --- src/agent/src/Toolbox/Tool/Platform.php | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/agent/src/Toolbox/Tool/Platform.php b/src/agent/src/Toolbox/Tool/Platform.php index 011d896a2..be565fef1 100644 --- a/src/agent/src/Toolbox/Tool/Platform.php +++ b/src/agent/src/Toolbox/Tool/Platform.php @@ -12,9 +12,6 @@ namespace Symfony\AI\Agent\Toolbox\Tool; use Symfony\AI\Platform\PlatformInterface; -use Symfony\AI\Platform\Result\AudioResult; -use Symfony\AI\Platform\Result\ImageResult; -use Symfony\AI\Platform\Result\TextResult; /** * Wraps a Platform instance as a tool, allowing agents to use specialized platforms for specific tasks. @@ -41,17 +38,10 @@ public function __construct( */ public function __invoke(array|string|object $input): string { - $result = $this->platform->invoke( + return $this->platform->invoke( $this->model, $input, $this->options, - )->await(); - - return match (true) { - $result instanceof TextResult => $result->getContent(), - $result instanceof AudioResult => $result->getText() ?? base64_encode($result->getAudio()), - $result instanceof ImageResult => $result->getText() ?? base64_encode($result->getImage()), - default => throw new \LogicException(\sprintf('Unsupported result type "%s".', $result::class)), - }; + )->asText(); } } From 7ba418f707696f7ae1144702d04152978c9c40bc Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 15:44:01 +0200 Subject: [PATCH 05/15] - --- examples/openai/platform-as-tool.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/openai/platform-as-tool.php b/examples/openai/platform-as-tool.php index 0abc97cc4..45fd2db15 100644 --- a/examples/openai/platform-as-tool.php +++ b/examples/openai/platform-as-tool.php @@ -43,10 +43,8 @@ // The agent can now use ElevenLabs for speech-to-text while using OpenAI for reasoning $audioPath = dirname(__DIR__, 2).'/fixtures/audio.mp3'; $messages = new MessageBag( - Message::ofUser(sprintf( - 'I have an audio file. Please transcribe it and tell me what it says. Audio: %s', - Audio::fromFile($audioPath) - )) + Message::ofUser('I have an audio file. Please transcribe it and tell me what it says.'), + Message::ofUser(Audio::fromFile($audioPath)), ); $result = $agent->call($messages); From 1a0bb2c1b673873fd8950ca5c012868184937888 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 15:57:38 +0200 Subject: [PATCH 06/15] [Examples] Use MemoryToolFactory pattern in platform-as-tool example Updated platform-as-tool.php to follow the same pattern as agent-as-tool.php: - Use MemoryToolFactory to register tool with name and description - Use ChainFactory to combine MemoryToolFactory and ReflectionToolFactory - Provides better tool metadata for the agent --- examples/openai/platform-as-tool.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/examples/openai/platform-as-tool.php b/examples/openai/platform-as-tool.php index 45fd2db15..510df240b 100644 --- a/examples/openai/platform-as-tool.php +++ b/examples/openai/platform-as-tool.php @@ -13,6 +13,9 @@ use Symfony\AI\Agent\Toolbox\AgentProcessor; use Symfony\AI\Agent\Toolbox\Tool\Platform; use Symfony\AI\Agent\Toolbox\Toolbox; +use Symfony\AI\Agent\Toolbox\ToolFactory\ChainFactory; +use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory; +use Symfony\AI\Agent\Toolbox\ToolFactory\ReflectionToolFactory; use Symfony\AI\Platform\Bridge\ElevenLabs\PlatformFactory as ElevenLabsPlatformFactory; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Content\Audio; @@ -33,8 +36,22 @@ // Wrap ElevenLabs platform as a tool $speechToText = new Platform($elevenLabsPlatform, 'scribe_v1'); +// Use MemoryToolFactory to register the tool with metadata +$memoryFactory = new MemoryToolFactory(); +$memoryFactory->addTool( + $speechToText, + 'transcribe_audio', + 'Transcribes audio files to text using ElevenLabs speech-to-text. Accepts audio file content.', +); + +// Combine with ReflectionToolFactory using ChainFactory +$chainFactory = new ChainFactory([ + $memoryFactory, + new ReflectionToolFactory(), +]); + // Create toolbox with the platform tool -$toolbox = new Toolbox([$speechToText], logger: logger()); +$toolbox = new Toolbox([$speechToText], toolFactory: $chainFactory, logger: logger()); $processor = new AgentProcessor($toolbox); // Create agent with OpenAI platform but with ElevenLabs tool available From f7a09e48b9d93e766837a754d4f1b37607aa4ef2 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:03:42 +0200 Subject: [PATCH 07/15] - --- examples/openai/platform-as-tool.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/openai/platform-as-tool.php b/examples/openai/platform-as-tool.php index 510df240b..ef0950a2e 100644 --- a/examples/openai/platform-as-tool.php +++ b/examples/openai/platform-as-tool.php @@ -11,7 +11,7 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Platform; +use Symfony\AI\Agent\Toolbox\Tool\Platform as PlatformTool; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Agent\Toolbox\ToolFactory\ChainFactory; use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory; @@ -34,7 +34,7 @@ ); // Wrap ElevenLabs platform as a tool -$speechToText = new Platform($elevenLabsPlatform, 'scribe_v1'); +$speechToText = new PlatformTool($elevenLabsPlatform, 'scribe_v1'); // Use MemoryToolFactory to register the tool with metadata $memoryFactory = new MemoryToolFactory(); From f9d22a9b76e54807e07a6277c29af8db91448691 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:08:01 +0200 Subject: [PATCH 08/15] [Examples] Simplify platform-as-tool to use OpenAI gpt-4o Changed from ElevenLabs speech-to-text example to a simpler OpenAI-only example that mirrors the agent-as-tool pattern: - Main agent uses gpt-4o-mini - Platform tool uses gpt-4o for advanced analysis - Demonstrates using a more powerful model as a tool for complex tasks - Removes external dependency on ElevenLabs API key --- examples/openai/platform-as-tool.php | 40 +++++++++------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/examples/openai/platform-as-tool.php b/examples/openai/platform-as-tool.php index ef0950a2e..94b4a9ee7 100644 --- a/examples/openai/platform-as-tool.php +++ b/examples/openai/platform-as-tool.php @@ -12,36 +12,27 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; use Symfony\AI\Agent\Toolbox\Tool\Platform as PlatformTool; -use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Agent\Toolbox\ToolFactory\ChainFactory; use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory; use Symfony\AI\Agent\Toolbox\ToolFactory\ReflectionToolFactory; -use Symfony\AI\Platform\Bridge\ElevenLabs\PlatformFactory as ElevenLabsPlatformFactory; +use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; -use Symfony\AI\Platform\Message\Content\Audio; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; require_once dirname(__DIR__).'/bootstrap.php'; -// Create the main OpenAI platform -$openAiPlatform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client()); - -// Create ElevenLabs platform as a tool for speech-to-text -$elevenLabsPlatform = ElevenLabsPlatformFactory::create( - apiKey: env('ELEVEN_LABS_API_KEY'), - httpClient: http_client() -); +$platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client()); -// Wrap ElevenLabs platform as a tool -$speechToText = new PlatformTool($elevenLabsPlatform, 'scribe_v1'); +// Create a specialized OpenAI platform tool using gpt-4o for complex analysis +$analysisTool = new PlatformTool($platform, 'gpt-4o'); // Use MemoryToolFactory to register the tool with metadata $memoryFactory = new MemoryToolFactory(); $memoryFactory->addTool( - $speechToText, - 'transcribe_audio', - 'Transcribes audio files to text using ElevenLabs speech-to-text. Accepts audio file content.', + $analysisTool, + 'advanced_analysis', + 'Performs deep analysis and complex reasoning tasks using GPT-4o. Use this for tasks requiring sophisticated understanding.', ); // Combine with ReflectionToolFactory using ChainFactory @@ -50,20 +41,13 @@ new ReflectionToolFactory(), ]); -// Create toolbox with the platform tool -$toolbox = new Toolbox([$speechToText], toolFactory: $chainFactory, logger: logger()); +// Create the main agent with gpt-4o-mini but with gpt-4o available as a tool +$toolbox = new Toolbox([$analysisTool], toolFactory: $chainFactory, logger: logger()); $processor = new AgentProcessor($toolbox); +$agent = new Agent($platform, 'gpt-4o-mini', [$processor], [$processor], logger: logger()); -// Create agent with OpenAI platform but with ElevenLabs tool available -$agent = new Agent($openAiPlatform, 'gpt-4o-mini', [$processor], [$processor], logger: logger()); - -// The agent can now use ElevenLabs for speech-to-text while using OpenAI for reasoning -$audioPath = dirname(__DIR__, 2).'/fixtures/audio.mp3'; -$messages = new MessageBag( - Message::ofUser('I have an audio file. Please transcribe it and tell me what it says.'), - Message::ofUser(Audio::fromFile($audioPath)), -); - +// Ask a question that could benefit from advanced analysis +$messages = new MessageBag(Message::ofUser('Analyze the philosophical implications of artificial consciousness and whether current AI systems exhibit any form of genuine understanding. Provide a detailed analysis.')); $result = $agent->call($messages); echo $result->getContent().\PHP_EOL; From 3f58f41b4ed187d1abfdc6dbe6253df209118257 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:10:17 +0200 Subject: [PATCH 09/15] - --- examples/openai/platform-as-tool.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/openai/platform-as-tool.php b/examples/openai/platform-as-tool.php index 94b4a9ee7..077bf5bc1 100644 --- a/examples/openai/platform-as-tool.php +++ b/examples/openai/platform-as-tool.php @@ -47,7 +47,8 @@ $agent = new Agent($platform, 'gpt-4o-mini', [$processor], [$processor], logger: logger()); // Ask a question that could benefit from advanced analysis -$messages = new MessageBag(Message::ofUser('Analyze the philosophical implications of artificial consciousness and whether current AI systems exhibit any form of genuine understanding. Provide a detailed analysis.')); -$result = $agent->call($messages); +$result = $agent->call(new MessageBag(Message::ofUser( + 'Analyze the philosophical implications of artificial consciousness and whether current AI systems exhibit any form of genuine understanding. Provide a detailed analysis.' +))); echo $result->getContent().\PHP_EOL; From 79e071bc97b9d5b1d49d76d8c196e5114de7293f Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:10:38 +0200 Subject: [PATCH 10/15] - --- src/agent/src/Toolbox/Tool/Platform.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agent/src/Toolbox/Tool/Platform.php b/src/agent/src/Toolbox/Tool/Platform.php index be565fef1..93f730c51 100644 --- a/src/agent/src/Toolbox/Tool/Platform.php +++ b/src/agent/src/Toolbox/Tool/Platform.php @@ -34,9 +34,9 @@ public function __construct( } /** - * @param array|string|object $input the input to pass to the platform + * @param string $message the message to pass to the chain */ - public function __invoke(array|string|object $input): string + public function __invoke(string $message): string { return $this->platform->invoke( $this->model, From a541f792cdcfec9233bf0def2678d3f8769e032f Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:13:24 +0200 Subject: [PATCH 11/15] - --- src/agent/src/Toolbox/Tool/Platform.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agent/src/Toolbox/Tool/Platform.php b/src/agent/src/Toolbox/Tool/Platform.php index 93f730c51..0feb14f37 100644 --- a/src/agent/src/Toolbox/Tool/Platform.php +++ b/src/agent/src/Toolbox/Tool/Platform.php @@ -40,7 +40,7 @@ public function __invoke(string $message): string { return $this->platform->invoke( $this->model, - $input, + $message, $this->options, )->asText(); } From 581b6a92cb34aea2ac3b51c51d7d320c2637b110 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:13:45 +0200 Subject: [PATCH 12/15] - --- demo/config/packages/ai.yaml | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/demo/config/packages/ai.yaml b/demo/config/packages/ai.yaml index b2a0cf29d..ec8d79049 100644 --- a/demo/config/packages/ai.yaml +++ b/demo/config/packages/ai.yaml @@ -2,8 +2,6 @@ ai: platform: openai: api_key: '%env(OPENAI_API_KEY)%' - elevenlabs: - api_key: '%env(ELEVEN_LABS_API_KEY)%' agent: blog: model: 'gpt-4o-mini' @@ -52,15 +50,6 @@ ai: model: 'gpt-4o-mini' prompt: 'You are a helpful general assistant. Assist users with any questions or tasks they may have.' tools: false - elevenlabs_audio: - model: 'gpt-4o-mini' - prompt: 'You are a helpful assistant with access to speech-to-text capabilities via ElevenLabs.' - tools: - # Platform as tool 🚀 - - platform: 'elevenlabs' - model: 'scribe_v1' - name: 'transcribe_audio' - description: 'Transcribes audio files to text using ElevenLabs.' multi_agent: support: orchestrator: 'orchestrator' @@ -101,16 +90,7 @@ services: Symfony\AI\Store\Document\Loader\RssFeedLoader: ~ Symfony\AI\Store\Document\Transformer\TextTrimTransformer: ~ - - # Example: Using a Platform as a Tool - # This demonstrates how to wrap any platform as a tool that can be used by agents - app.tool.elevenlabs_transcription: - class: 'Symfony\AI\Agent\Toolbox\Tool\Platform' - arguments: - $platform: '@ai.platform.elevenlabs' - $model: 'scribe_v1' - $options: [] - + app.filter.week_of_symfony: class: 'Symfony\AI\Store\Document\Filter\TextContainsFilter' arguments: From 60eef5afac2d7d0fa33c9117c24c12755d0cefd2 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:15:00 +0200 Subject: [PATCH 13/15] [Examples] Use simple math question in platform-as-tool example Changed from complex philosophical question to the same simple math question used in agent-as-tool.php for consistency and clarity. --- examples/openai/platform-as-tool.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/openai/platform-as-tool.php b/examples/openai/platform-as-tool.php index 077bf5bc1..501536f91 100644 --- a/examples/openai/platform-as-tool.php +++ b/examples/openai/platform-as-tool.php @@ -12,10 +12,10 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; use Symfony\AI\Agent\Toolbox\Tool\Platform as PlatformTool; +use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Agent\Toolbox\ToolFactory\ChainFactory; use Symfony\AI\Agent\Toolbox\ToolFactory\MemoryToolFactory; use Symfony\AI\Agent\Toolbox\ToolFactory\ReflectionToolFactory; -use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; @@ -24,15 +24,15 @@ $platform = PlatformFactory::create(env('OPENAI_API_KEY'), http_client()); -// Create a specialized OpenAI platform tool using gpt-4o for complex analysis -$analysisTool = new PlatformTool($platform, 'gpt-4o'); +// Create a specialized OpenAI platform tool using gpt-4o for mathematical calculations +$mathTool = new PlatformTool($platform, 'gpt-4o'); // Use MemoryToolFactory to register the tool with metadata $memoryFactory = new MemoryToolFactory(); $memoryFactory->addTool( - $analysisTool, - 'advanced_analysis', - 'Performs deep analysis and complex reasoning tasks using GPT-4o. Use this for tasks requiring sophisticated understanding.', + $mathTool, + 'calculate', + 'Performs mathematical calculations using GPT-4o. Use this when you need to solve math problems or do arithmetic.', ); // Combine with ReflectionToolFactory using ChainFactory @@ -42,13 +42,13 @@ ]); // Create the main agent with gpt-4o-mini but with gpt-4o available as a tool -$toolbox = new Toolbox([$analysisTool], toolFactory: $chainFactory, logger: logger()); +$toolbox = new Toolbox([$mathTool], toolFactory: $chainFactory, logger: logger()); $processor = new AgentProcessor($toolbox); $agent = new Agent($platform, 'gpt-4o-mini', [$processor], [$processor], logger: logger()); -// Ask a question that could benefit from advanced analysis +// Ask a question that requires mathematical calculation $result = $agent->call(new MessageBag(Message::ofUser( - 'Analyze the philosophical implications of artificial consciousness and whether current AI systems exhibit any form of genuine understanding. Provide a detailed analysis.' + 'I have 15 apples and I want to share them equally among 4 friends. How many apples does each friend get and how many are left over?' ))); echo $result->getContent().\PHP_EOL; From ef482375353e90f7e0a780ba32d34c50d2170d63 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:16:06 +0200 Subject: [PATCH 14/15] [Agent] Update Platform tool docblock and fix parameter name - Removed ElevenLabs reference from docblock example - Updated example to use gpt-4o/gpt-4o-mini scenario - Fixed parameter name from $message to $input to match signature --- src/agent/src/Toolbox/Tool/Platform.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/agent/src/Toolbox/Tool/Platform.php b/src/agent/src/Toolbox/Tool/Platform.php index 0feb14f37..ac2033398 100644 --- a/src/agent/src/Toolbox/Tool/Platform.php +++ b/src/agent/src/Toolbox/Tool/Platform.php @@ -16,8 +16,8 @@ /** * Wraps a Platform instance as a tool, allowing agents to use specialized platforms for specific tasks. * - * This enables scenarios where an agent using one platform (e.g., OpenAI) can leverage - * another platform (e.g., ElevenLabs for speech-to-text) as a tool. + * This enables scenarios where an agent can leverage different models or platforms + * as tools (e.g., using gpt-4o for complex calculations while using gpt-4o-mini for the main agent). * * @author Oskar Stark */ @@ -34,13 +34,13 @@ public function __construct( } /** - * @param string $message the message to pass to the chain + * @param array|string|object $input the input to pass to the platform */ - public function __invoke(string $message): string + public function __invoke(array|string|object $input): string { return $this->platform->invoke( $this->model, - $message, + $input, $this->options, )->asText(); } From b2ebc89a04251abd710f6bbd108e37c889e56b54 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 2 Oct 2025 16:18:21 +0200 Subject: [PATCH 15/15] - --- src/agent/src/Toolbox/Tool/Platform.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/agent/src/Toolbox/Tool/Platform.php b/src/agent/src/Toolbox/Tool/Platform.php index ac2033398..0affe2feb 100644 --- a/src/agent/src/Toolbox/Tool/Platform.php +++ b/src/agent/src/Toolbox/Tool/Platform.php @@ -34,13 +34,13 @@ public function __construct( } /** - * @param array|string|object $input the input to pass to the platform + * @param string $message the message to pass to the chain */ - public function __invoke(array|string|object $input): string + public function __invoke(string $message): string { return $this->platform->invoke( $this->model, - $input, + $message, $this->options, )->asText(); }