PHPackages                             toxo/toxo-cloud-laravel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. toxo/toxo-cloud-laravel

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

toxo/toxo-cloud-laravel
=======================

Laravel client package for TOXO Cloud (.toxo layers)

00PHP

Since Apr 1Pushed 3mo agoCompare

[ Source](https://github.com/spiderdev27/toxo-cloud-laravel)[ Packagist](https://packagist.org/packages/toxo/toxo-cloud-laravel)[ RSS](/packages/toxo-toxo-cloud-laravel/feed)WikiDiscussions main Synced 4w ago

READMEChangelogDependenciesVersions (1)Used By (0)

toxo-cloud-laravel
------------------

[](#toxo-cloud-laravel)

Laravel package for calling **TOXO Cloud** from PHP, mirroring the Python `toxo-cloud` client for `.toxo` layers.

### What this package is for

[](#what-this-package-is-for)

- **Bring your own `.toxo` layer** (small file that contains your domain rules/soft-prompt/memory)
- Call TOXO Cloud endpoints from Laravel using a thin PHP client (Guzzle)
- Run query, multimodal query, feedback, training, resume training, extraction, RAG, and agent workflows

### Capability matrix (endpoint parity)

[](#capability-matrix-endpoint-parity)

CapabilityEndpointPHP methodService root`GET /``$client->root()`Health check`GET /health``$client->health()`Text query`POST /v1/query``$client->query()`Multimodal (image/document)`POST /v1/query_multimodal``$client->queryMultimodal()`Feedback`POST /v1/feedback``$client->feedback()`Train from data`POST /v1/train_from_data``$client->trainFromData()`Resume training`POST /v1/train_resume_from_data``$client->trainResumeFromData()`Extract contexts`POST /v1/train/extract_contexts``$client->trainExtractContexts()`RAG index`POST /v1/rag/index``$client->ragIndex()`RAG query`POST /v1/rag/query``$client->ragQuery()`Agent workflow`POST /v1/agent/run``$client->agentRun()`### Install

[](#install)

```
composer require toxo/toxo-cloud-laravel
```

Laravel auto-discovers the service provider.

Publish config:

```
php artisan vendor:publish --provider="Toxo\Cloud\Laravel\ToxoCloudServiceProvider" --tag=config
```

### Standalone usage (without Laravel)

[](#standalone-usage-without-laravel)

`toxo-cloud-laravel` is “Laravel-friendly”, but the client itself does **not** require a fully booted Laravel app.

By default it will use **Guzzle** if present (recommended). If you don’t want Guzzle, you can pass any **PSR-18** client + **PSR-17** factories.

You can use it from any PHP script:

```
require __DIR__ . '/vendor/autoload.php';

use Toxo\Cloud\Laravel\ToxoCloudClient;

$client = new ToxoCloudClient(api_key: getenv('GEMINI_API_KEY'), timeout: 180);
$answer = $client->query(__DIR__ . '/finance_expert.toxo', 'Explain inflation briefly.');
echo $answer;
```

Using PSR-18 explicitly (example):

```
use Toxo\Cloud\Laravel\ToxoCloudClient;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\StreamFactoryInterface;

/** @var ClientInterface $http */
/** @var RequestFactoryInterface $requests */
/** @var StreamFactoryInterface $streams */

$client = new ToxoCloudClient(
    apiKey: getenv('GEMINI_API_KEY'),
    timeout: 180,
    httpClient: $http,
    requestFactory: $requests,
    streamFactory: $streams,
);
```

### Authentication (API key resolution)

[](#authentication-api-key-resolution)

The client resolves keys in this order:

1. Explicit method option `['api_key' => '...']` / param `api_key`
2. `config('toxo-cloud.api_key')` (`TOXO_CLOUD_API_KEY`)
3. `GEMINI_API_KEY`
4. `GOOGLE_API_KEY`

If no key is available, endpoints that require provider access will fail.

Example `.env`:

```
TOXO_CLOUD_API_KEY="YOUR_GEMINI_OR_PROVIDER_KEY"
TOXO_CLOUD_TIMEOUT=120
```

### Basic usage (controller / DI)

[](#basic-usage-controller--di)

```
use Toxo\Cloud\Laravel\ToxoCloudClient;

class AskController
{
    public function __invoke(ToxoCloudClient $toxo)
    {
        $answer = $toxo->query(
            base_path('layers/finance_expert.toxo'),
            'Explain inflation in simple words.',
            [
                'response_depth' => 'balanced', // concise | balanced | detailed
                'model' => 'gemini-2.5-flash-lite',
                'provider' => 'gemini',
            ]
        );

        return response()->json(['answer' => $answer]);
    }
}
```

### Error handling

[](#error-handling)

- Non-2xx responses throw a `RuntimeException` with best-effort `detail` from the response body.
- File paths (`.toxo`, docs/images, agent config) are validated locally and throw early if missing.

### Saving trained layers (`layer_base64` → `.toxo` file)

[](#saving-trained-layers-layer_base64--toxo-file)

Training endpoints return a `layer_base64` field. To persist the new layer:

```
$bytes = base64_decode($result['layer_base64'] ?? '');
file_put_contents(base_path('layers/my_layer.toxo'), $bytes);
```

Local testing (smoke test)
--------------------------

[](#local-testing-smoke-test)

This repo includes a local harness at `toxo-cloud-laravel-smoketest/` that calls all endpoints using your repo `.env` (it reads `GEMINI_API_KEY`).

Run it with Docker:

```
# from the repo root
docker run --rm -v "$(pwd)":/app -w "/app/toxo-cloud-laravel-smoketest" composer:2 \
  sh -lc "composer install --no-interaction --no-ansi --prefer-source"

docker run --rm -v "$(pwd)":/app -w "/app/toxo-cloud-laravel-smoketest" php:8.4-cli php test.php
```

Notes:

- The smoke test uses `finance_expert_cloud_20_examples.toxo` as its base layer.
- For `train_resume_from_data`, use **at least 2 examples** in the request to avoid edge-case failures from tiny datasets.

Endpoint-by-endpoint examples
-----------------------------

[](#endpoint-by-endpoint-examples)

All examples below assume:

```
use Toxo\Cloud\Laravel\ToxoCloudClient;

$client = app(ToxoCloudClient::class);
```

### 1) `GET /` (service root)

[](#1-get--service-root)

```
$info = $client->root();
```

### 2) `GET /health` (health check)

[](#2-get-health-health-check)

```
$health = $client->health(); // e.g. ["status" => "ok"]
```

### 3) `POST /v1/query` (text query)

[](#3-post-v1query-text-query)

```
$answer = $client->query(
    base_path('layers/finance_expert.toxo'),
    'Explain inflation in 3 bullets.',
    [
        'response_depth' => 'balanced',
        'provider' => 'gemini',
        'model' => 'gemini-2.5-flash-lite',
    ]
);
```

### 4) `POST /v1/query_multimodal` (image or document query)

[](#4-post-v1query_multimodal-image-or-document-query)

Exactly one source is required:

- `image_path`
- `document_path`
- `image_base64`
- `document_base64`

```
// Document from path (mime inferred when possible)
$docAnswer = $client->queryMultimodal(
    base_path('layers/ops_expert.toxo'),
    'Summarize this policy and list action items.',
    [
        'document_path' => storage_path('app/policy.pdf'),
    ]
);

// Image from path
$imgAnswer = $client->queryMultimodal(
    base_path('layers/ops_expert.toxo'),
    'Extract key metrics from this dashboard screenshot.',
    [
        'image_path' => storage_path('app/dashboard.png'),
    ]
);
```

Notes:

- If you pass **raw base64**, the client wraps it into `data:;base64,...`.
- If you pass a path and mime cannot be detected, you can force it via `mime_type`.

### 5) `POST /v1/feedback` (quality feedback)

[](#5-post-v1feedback-quality-feedback)

```
$result = $client->feedback(
    base_path('layers/finance_expert.toxo'),
    'What is inflation?',
    'Inflation is the rise in prices over time.',
    [
        'rating' => 9.0,
        'suggestions' => ['Add one real-world example.'],
    ]
);
```

### 6) `POST /v1/train_from_data` (train a new layer)

[](#6-post-v1train_from_data-train-a-new-layer)

This returns a response containing `layer_base64`. This package **does not auto-save**; you choose where to write the `.toxo`.

```
$result = $client->trainFromData([
    'description' => 'Finance helper for beginner investing questions.',
    'examples' => [
        ['input' => 'What is diversification?', 'output' => 'Spreading risk across asset types.'],
        ['input' => 'Explain compounding.', 'output' => 'Interest on interest over time.'],
    ],
    'contexts' => [
        'Prefer simple explanations for beginners unless they request details.',
    ],
    'epochs' => 3,
    'llm_provider' => 'gemini',
    'llm_model' => 'gemini-2.5-flash-lite',
]);

$layerBytes = base64_decode($result['layer_base64'] ?? '');
file_put_contents(base_path('layers/finance_trained.toxo'), $layerBytes);
```

### 7) `POST /v1/train_resume_from_data` (resume training from an existing `.toxo`)

[](#7-post-v1train_resume_from_data-resume-training-from-an-existing-toxo)

```
$result = $client->trainResumeFromData([
    'base_layer'  => base_path('layers/support_expert_v1.toxo'),
    'description' => 'Support expert v2 with better escalation rules.',
    'examples'    => [
        ['input' => 'How to handle a failed payment escalation?', 'output' => '...'],
    ],
    'contexts'    => [
        'Prefer clear step-by-step escalation paths.',
    ],
    'epochs'      => 3,
    'llm_provider' => 'gemini',
    'llm_model' => 'gemini-2.5-flash-lite',
]);

file_put_contents(
    base_path('layers/support_expert_v2.toxo'),
    base64_decode($result['layer_base64'] ?? '')
);
```

You can also include documents (each doc is uploaded as base64):

```
$result = $client->trainResumeFromData([
    'base_layer' => base_path('layers/support_expert_v1.toxo'),
    'description' => 'Support expert v2 (add policy docs).',
    'documents' => [
        storage_path('app/policy.pdf'),
        storage_path('app/faq.md'),
    ],
    'epochs' => 2,
]);
```

### 8) `POST /v1/train/extract_contexts` (extract contexts from docs)

[](#8-post-v1trainextract_contexts-extract-contexts-from-docs)

```
$result = $client->trainExtractContexts([
    'docs' => [
        storage_path('app/policy.pdf'),
        storage_path('app/faq.md'),
    ],
    'index_id' => 'billing_contexts',
    'domain' => 'billing',
]);
```

### 9) `POST /v1/rag/index` (index docs in cloud vector store)

[](#9-post-v1ragindex-index-docs-in-cloud-vector-store)

```
$result = $client->ragIndex([
    'index_id' => 'product_docs_v1',
    'domain' => 'product',
    'docs' => [
        storage_path('app/docs/guide.md'),
        storage_path('app/docs/faq.pdf'),
    ],
]);
```

Optionally include a layer for domain-aware chunking / preprocessing:

```
$result = $client->ragIndex([
    'index_id' => 'product_docs_v1',
    'domain' => 'product',
    'layer' => base_path('layers/product_expert.toxo'),
    'docs' => [storage_path('app/docs/faq.pdf')],
]);
```

### 10) `POST /v1/rag/query` (query a cloud index)

[](#10-post-v1ragquery-query-a-cloud-index)

```
$result = $client->ragQuery([
    'layer' => base_path('layers/product_expert.toxo'),
    'index_id' => 'product_docs_v1',
    'question' => 'What are the cancellation rules?',
    'top_k' => 5,
    'response_depth' => 'balanced',
]);

$answer = $result['response'] ?? '';
```

### 11) `POST /v1/agent/run` (agent orchestration)

[](#11-post-v1agentrun-agent-orchestration)

`agentRun()` accepts:

- `config`: array OR path to JSON/YAML file
- `layer_map`: map of `agent_id => layer_path`

```
$result = $client->agentRun([
    'config' => base_path('agent_config.json'),
    'layer_map' => [
        'research' => base_path('layers/research_expert.toxo'),
        'writer' => base_path('layers/writer_expert.toxo'),
    ],
    'llm_provider' => 'gemini',
    'llm_model' => 'gemini-2.5-flash-lite',
]);

$final = $result['final'] ?? null;
```

YAML config support requires:

```
composer require symfony/yaml
```

Notes / gotchas
---------------

[](#notes--gotchas)

- **Timeouts**: training and indexing can take a while; this client uses higher per-endpoint timeouts (same idea as the Python client).
- **File sizes**: docs/images are uploaded as base64; keep an eye on payload size.
- **Where the `.toxo` is saved**: for training endpoints you must write `layer_base64` to a file yourself (examples above).
- **Resume training minimums**: very small datasets (e.g. 1 example) can be unstable for some training flows; prefer 2+ examples for resume training requests.

###  Health Score

18

—

LowBetter than 8% of packages

Maintenance55

Moderate activity, may be stable

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity12

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/ee6ed459e1507381784f5bcbd5dbd2a9c715dd1f39e0523aeedd5ddf62bd8afe?d=identicon)[spiderdev](/maintainers/spiderdev)

---

Top Contributors

[![spiderdev-unstop](https://avatars.githubusercontent.com/u/260589701?v=4)](https://github.com/spiderdev-unstop "spiderdev-unstop (12 commits)")

### Embed Badge

![Health badge](/badges/toxo-toxo-cloud-laravel/health.svg)

```
[![Health](https://phpackages.com/badges/toxo-toxo-cloud-laravel/health.svg)](https://phpackages.com/packages/toxo-toxo-cloud-laravel)
```

###  Alternatives

[mike42/escpos-php

PHP receipt printer library for use with ESC/POS-compatible thermal and impact printers

2.8k2.1M25](/packages/mike42-escpos-php)[infusionsoft/php-sdk

PHP SDK for the Infusionsoft

1292.2M7](/packages/infusionsoft-php-sdk)[pingpong/generators

Laravel Generators

33239.8k8](/packages/pingpong-generators)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
