connect('sampling', $this->clientSampling()); $result = $client->callTool('summarize', ['text' => 'a long report']); $this->assertInstanceOf(TextContent::class, $result->content[0]); $this->assertSame('test-model said: a long report', $result->content[0]->text); } #[TestDox('the prompt the tool passed arrives at the client')] public function testPromptReachesTheClient(): void { // The client stays in this process, so what it was asked can be // collected by reference even though the tool asking runs in another. /** @var \ArrayObject $seen */ $seen = new \ArrayObject(); $client = $this->connect('sampling', $this->clientSampling($seen)); $client->callTool('summarize', ['text' => 'inspect me']); $this->assertCount(1, $seen); $this->assertInstanceOf(TextContent::class, $seen[0]->messages[0]->content); $this->assertSame('inspect me', $seen[0]->messages[0]->content->text); $this->assertSame(64, $seen[0]->maxTokens); } #[TestDox('a client that cannot sample refuses instead of stalling the tool')] public function testClientWithoutSamplingRefuses(): void { // The gateway has no supportsSampling() to consult, so the tool finds // out by asking and the refusal surfaces as a ClientException. $client = $this->connect('sampling'); $result = $client->callTool('summarize', ['text' => 'anything']); $this->assertInstanceOf(TextContent::class, $result->content[0]); $this->assertSame('Client does not handle "sampling/createMessage" requests.', $result->content[0]->text); } /** * @param \ArrayObject|null $seen collects what the server asked for */ private function clientSampling(?\ArrayObject $seen = null): ClientBuilder { $callback = new class($seen ?? new \ArrayObject()) implements SamplingCallbackInterface { /** @param \ArrayObject $seen */ public function __construct(private readonly \ArrayObject $seen) { } public function __invoke(CreateSamplingMessageRequest $request): CreateSamplingMessageResult { $this->seen[] = $request; $prompt = $request->messages[0]->content; \assert($prompt instanceof TextContent); return new CreateSamplingMessageResult(Role::Assistant, new TextContent($prompt->text), 'test-model'); } }; return $this->clientBuilder() ->setCapabilities(new ClientCapabilities(sampling: true)) ->addRequestHandler(new SamplingRequestHandler($callback)); } }