PHP SDK

⚠️
Preview — this feature is being built; the design below is the spec.

syntic/syntic-php is the planned official PHP client. It is generated from the OpenAPI description, works with any PSR-18 HTTP client, and adds helpers for streaming with generators, pagination, a tool runner and batch waiting. It is in the second release wave; see Other languages.

Today, use ext-curl as shown in Quickstart: PHP. That code keeps working after the SDK ships.

Install

composer require syntic/syntic-php
RequirementValue
PHP8.1 or newer
Packagesyntic/syntic-php on Packagist
HTTPAny PSR-18 client; Guzzle is used when installed

Create a client

<?php
require 'vendor/autoload.php';
 
$client = Syntic\Client::fromEnv(); // SYNTIC_API_KEY, SYNTIC_BASE_URL
 
$client = Syntic\Client::create([
    'api_key' => getenv('SYNTIC_API_KEY'),
    'base_url' => 'https://app.syntic.ai/v1',
    'max_retries' => 3,
    'timeout' => 300,
]);
OptionDefaultNotes
api_keySYNTIC_API_KEYPrivate key or workload identity token.
base_urlSYNTIC_BASE_URL, else https://app.syntic.ai/v1
versionThe release’s API versionSent as syntic-version.
betas[]Sent as syntic-beta; methods that need a flag add it.
max_retries2rate_limit, overloaded, api_error and network errors.
timeout600 seconds
http_clientdiscoveredYour own PSR-18 client.

A first request

$reply = $client->chat->completions->create([
    'model' => 'Amara S1.2',
    'max_tokens' => 200,
    'messages' => [
        ['role' => 'system', 'content' => 'Answer in one sentence.'],
        ['role' => 'user', 'content' => 'Why is the sky blue?'],
    ],
]);
 
echo $reply->choices[0]->message->content, PHP_EOL;
echo $reply->usage->totalTokens, ' tokens, request ', $reply->requestId, PHP_EOL;

Streaming

$stream = $client->chat->completions->stream([
    'model' => 'Amara Quick',
    'messages' => [['role' => 'user', 'content' => 'Write a haiku about rain.']],
]);
 
foreach ($stream->textDeltas() as $text) {
    echo $text;
    flush();
}
$final = $stream->finalCompletion(); // assembled message, tool calls, usage

Tool loop

$getOrder = Syntic\Tool::define(
    name: 'get_order',
    description: 'Look up an order by its id.',
    parameters: ['order_id' => ['type' => 'string', 'description' => 'Order id such as 88123']],
    required: ['order_id'],
    handler: fn (array $args) => ['order_id' => $args['order_id'], 'status' => 'shipped'],
);
 
$result = $client->tools->run([
    'model' => 'Amara S1.2',
    'messages' => [['role' => 'user', 'content' => 'Where is order 88123?']],
    'tools' => [$getOrder],
    'max_rounds' => 8,
]);
echo $result->finalMessage->content, PHP_EOL;

Errors

Exceptionerror.type
Syntic\Exception\InvalidRequestExceptioninvalid_request
Syntic\Exception\AuthenticationExceptionauthentication
Syntic\Exception\PermissionDeniedExceptionpermission
Syntic\Exception\NotFoundExceptionnot_found
Syntic\Exception\QuotaExhaustedExceptionquota_exhausted
Syntic\Exception\RateLimitExceptionrate_limit
Syntic\Exception\OverloadedExceptionoverloaded
Syntic\Exception\ServerExceptionapi_error
Syntic\Exception\ConnectionExceptionNo response received

All API exceptions extend Syntic\Exception\ApiException with getStatusCode(), getType(), getErrorCode(), getParam(), getDetails() and getRequestId().

try {
    $client->chat->completions->create(['model' => 'Amara S1.2', 'messages' => []]);
} catch (Syntic\Exception\QuotaExhaustedException $e) {
    echo 'Paused until ', $e->getDetails()['resets_at'] ?? 'unknown', PHP_EOL;
}

Pagination

foreach ($client->agents->list(['limit' => 50])->autoPaging() as $agent) {
    echo $agent->id, ' ', $agent->name, PHP_EOL;
}

Files, batches, agents and admin

$file = $client->files->upload(path: 'contract.pdf', purpose: 'document');
 
$batch = $client->batches->create(['input_file_id' => $file->id]);
$batch = $client->batches->wait($batch->id, pollInterval: 30);
 
$session = $client->sessions->create(['agent_id' => 'agt_01JC4R8W6Q2N9X3T5V7Y']);
foreach ($client->sessions->stream($session->id) as $event) {
    if ($event->type === 'message.completed') {
        echo $event->content, PHP_EOL;
    }
}
 
$admin = Syntic\AdminClient::fromEnv(); // SYNTIC_ADMIN_KEY
foreach ($admin->users->list()->autoPaging() as $user) {
    echo $user->email, PHP_EOL;
}

Raw responses

$raw = $client->chat->completions->withRawResponse()->create($params);
echo $raw->getHeaderLine('x-syntic-billing-source'), PHP_EOL;
$reply = $raw->parse();
Was this page helpful?