PHP code example of blundergoat / strands-php-client
1. Go to this page and download the library: Download blundergoat/strands-php-client library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
blundergoat / strands-php-client example snippets
use StrandsPhpClient\StrandsClient;
use StrandsPhpClient\Config\StrandsConfig;
$client = new StrandsClient(
config: new StrandsConfig(endpoint: 'http://localhost:8081'),
);
$response = $client->invoke('Should we migrate to microservices?');
echo $response->text;
echo $response->agent; // Which agent handled it (e.g. "analyst")
echo $response->usage->inputTokens;
use StrandsPhpClient\StrandsClient;
use StrandsPhpClient\Config\StrandsConfig;
use StrandsPhpClient\Http\PsrHttpTransport;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
$client = new StrandsClient(
config: new StrandsConfig(endpoint: 'http://localhost:8081'),
transport: new PsrHttpTransport(
httpClient: new Client(['timeout' => 120]),
requestFactory: new HttpFactory(),
streamFactory: new HttpFactory(),
),
);
$response = $client->invoke('Should we migrate to microservices?');
echo $response->text;
use StrandsPhpClient\Context\AgentInput;
// Text with an image
$input = AgentInput::text("What's in this image?")
->withImage(base64_encode($imageBytes), 'image/png');
$response = $client->invoke(message: $input);
// Text with a document from S3
$input = AgentInput::text('Summarise this report')
->withDocumentFromS3('s3://my-bucket/report.pdf', 'pdf', 'report');
// Resume after an interrupt (human-in-the-loop)
$input = AgentInput::interruptResponse($interruptId, ['approved' => true]);
use StrandsPhpClient\Context\AgentContext;
$response = $client->invoke(
message: 'Analyse this proposal',
context: AgentContext::create()
->withMetadata('persona', 'analyst')
->withSystemPrompt('Be concise.'),
sessionId: 'session-001',
);
$response->text; // Agent's response
$response->agent; // Agent name (e.g. "analyst")
$response->sessionId; // Session ID for follow-ups
$response->usage; // Token usage (inputTokens, outputTokens)
$response->usage->totalTokens(); // Total tokens (input + output)
$response->toolsUsed; // Tools the agent called
$response->metadata; // Unrecognised response fields (forward-compat)
// Interrupt handling (human-in-the-loop)
if ($response->isInterrupted()) {
foreach ($response->interrupts as $interrupt) {
echo $interrupt->toolName; // Tool that needs approval
echo $interrupt->reason; // Why the agent paused
}
}
// Guardrail traces (content safety)
if ($response->guardrailTrace !== null) {
echo $response->guardrailTrace->action; // 'INTERVENED' or 'NONE'
}
use StrandsPhpClient\Streaming\StreamEvent;
use StrandsPhpClient\Streaming\StreamEventType;
$result = $client->stream(
message: 'Explain quantum computing',
onEvent: function (StreamEvent $event) {
match ($event->type) {
StreamEventType::Text => print($event->text),
StreamEventType::ToolUse => print("[Using tool: {$event->toolName}]"),
StreamEventType::Complete => print("\n[Done]"),
StreamEventType::Error => print("Error: {$event->errorMessage}"),
default => null,
};
},
sessionId: 'session-001',
);
echo $result->text; // Full accumulated text
echo $result->sessionId; // Session ID
echo $result->usage->inputTokens; // Token usage
echo $result->usage->totalTokens(); // Total tokens (input + output)
echo $result->textEvents; // Number of text chunks received
echo $result->totalEvents; // Total events received
echo $result->timeToFirstTextTokenMs; // Client-measured TTFT in ms
echo $result->isInterrupted() ? 'yes' : 'no'; // Whether the agent was interrupted
// Synchronous - returns raw decoded JSON array
$result = $client->postJson('/file-summarise', [
'file_base64' => base64_encode($fileBytes),
'file_name' => 'report.pdf',
], timeout: 120);
// Streaming - delivers raw decoded JSON arrays to the callback
$client->streamSse('/file-summarise-stream', [
'file_base64' => base64_encode($fileBytes),
], function (array $event) {
match ($event['type'] ?? '') {
'text' => print($event['content']),
'complete' => print("\n[Done]"),
default => null,
};
}, timeout: 120);
$r1 = $client->invoke('Draft a referral letter', sessionId: 'consult-001');
$r2 = $client->invoke('Make it more formal', sessionId: 'consult-001');
$context = AgentContext::create()
->withMetadata('clinic_id', 'CL-789')
->withSystemPrompt('You are a clinical documentation assistant.')
->withPermission('read:patients')
->withDocument('referral.pdf', base64_encode($pdfBytes), 'application/pdf');
$config = new StrandsConfig(
endpoint: 'https://api.example.com/agent',
maxRetries: 3, // Retry up to 3 times (invoke/postJson only)
retryDelayMs: 500, // 500ms → 1s → 2s (exponential backoff with jitter)
connectTimeout: 5, // Fail fast if server is down
);
$client = new StrandsClient(config: $config, logger: $yourPsr3Logger);
use StrandsPhpClient\Auth\NullAuth;
use StrandsPhpClient\Auth\ApiKeyAuth;
// No auth (default -local development)
$config = new StrandsConfig(
endpoint: 'http://localhost:8081',
);
// API key auth (production)
$config = new StrandsConfig(
endpoint: 'https://api.example.com/agent',
auth: new ApiKeyAuth('sk-your-api-key'),
);
// Custom header (e.g. X-API-Key instead of Authorization: Bearer)
$config = new StrandsConfig(
endpoint: 'https://api.example.com/agent',
auth: new ApiKeyAuth('sk-your-api-key', headerName: 'X-API-Key', valuePrefix: ''),
);
// AWS SigV4 auth (agents behind API Gateway with IAM)
use StrandsPhpClient\Auth\SigV4Auth;
$config = new StrandsConfig(
endpoint: 'https://abc123.execute-api.us-east-1.amazonaws.com/prod',
auth: new SigV4Auth(
accessKeyId: 'AKIA...',
secretAccessKey: 'wJalr...',
region: 'us-east-1',
),
);
// SigV4 from environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
$config = new StrandsConfig(
endpoint: 'https://abc123.execute-api.us-east-1.amazonaws.com/prod',
auth: SigV4Auth::fromEnvironment(region: 'us-east-1'),
);
use StrandsPhpClient\StrandsClient;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
class ChatController extends AbstractController
{
public function __construct(
#[Autowire(service: 'strands.client.analyst')]
private readonly StrandsClient $analyst,
#[Autowire(service: 'strands.client.skeptic')]
private readonly StrandsClient $skeptic,
) {}
}
use StrandsPhpClient\StrandsClient;
class ChatController extends Controller
{
public function __construct(
private readonly StrandsClient $client, // default agent
) {}
}
// Named agent via container
$analyst = app('strands.client.analyst');
use StrandsPhpClient\Integration\Laravel\Facades\Strands;
$response = Strands::invoke('Analyse this proposal');
composer
mermaid
graph LR
A["PHP Application<br/><small>Laravel · Symfony · Slim</small>"] -->|"invoke() / stream()"| B["strands-php-client"]
B -->|"HTTP + SSE"| C["Strands Agent<br/><small>Python · FastAPI</small>"]
C -->|"Reasoning Loop"| D["LLM Provider<br/><small>Bedrock · Ollama · OpenAI</small>"]
C -->|"Tool Calls"| E["Tools & APIs<br/><small>DB · Search · Custom</small>"]
style A fill:#7c3aed,color:#fff,stroke:none
style B fill:#2563eb,color:#fff,stroke:none
style C fill:#059669,color:#fff,stroke:none
style D fill:#d97706,color:#fff,stroke:none
style E fill:#d97706,color:#fff,stroke:none
bash
composer vendor:publish --tag=strands-config
bash
composer
bash
composer
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.