Skip to content

SuperInstance/plato-client-php

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PLATO Client PHP

A PHP 8.0+ client library for interacting with a PLATO room server. Submit tiles, query knowledge, manage rooms, and register fleet agents.

Part of the Cocapn fleet — lighthouse keeper architecture.


Installation

composer require superinstance/plato-client-php

Or manually:

git clone https://github.com/SuperInstance/plato-client-php.git
cd plato-client-php
composer install

Quick Start

use SuperInstance\PlatoClient\PlatoClient;

$client = new PlatoClient('http://localhost:8847');

// Check server status
$status = $client->getStatus();
echo "Server version: {$status['version']}\n";

// Submit a tile
$result = $client->submitTile(
    'my_room',
    'What is Phi?',
    'Phi measures how much a room\'s whole exceeds the sum of its tiles.',
    ['confidence' => 0.85]
);
echo "Tile hash: {$result['tile_hash']}\n";

// Query tiles
$results = $client->queryTiles('my_room', 'Phi', limit: 10);
foreach ($results as $tile) {
    echo "- {$tile['question']}\n";
}

Architecture

plato-client-php/
├── composer.json
├── README.md
└── src/
    ├── PlatoClient.php      # Main HTTP client
    ├── PlatoException.php   # Error handling
    ├── PlatoErrorCode.php   # Error code enum
    ├── Tile.php             # Tile value object
    ├── Room.php             # Room value object
    ├── AgentRegistry.php    # Fleet agent helpers
    ├── TileQuery.php        # Query builder
    └── CLI.php              # Command-line tool

Tile Primitive

The tile is the fundamental unit of PLATO knowledge. Each tile is a structured Q&A pair:

  • question — the anchor/question text
  • answer — the learned content
  • confidence — 0.0 to 1.0 quality signal
  • domain / room_id — which room it belongs to
  • _hash — content-derived identifier
  • source / author — who/what submitted it

Room Structure

Rooms are named collections of tiles. They accumulate knowledge over time. Each room has:

  • id — room name (used as domain)
  • description — room purpose
  • tile_count — number of tiles
  • created_at — when the room was created
  • agents — fleet agents active in this room

API Reference

PlatoClient

Constructor

$client = new PlatoClient(string $serverUrl, ?string $apiToken = null);
  • $serverUrl — base URL of PLATO server (e.g., http://localhost:8847)
  • $apiToken — optional API token. Falls back to PLATO_API_TOKEN env var.

getStatus()

$status = $client->getStatus(): array;

Returns server status including version, room count, gate statistics.

$status = $client->getStatus();
echo $status['version'];      // e.g., "v2.0"
echo $status['rooms'];        // room count
echo $status['total_tiles'];  // total tiles across all rooms

listRooms()

$rooms = $client->listRooms(int $limit = 100): array;

List all rooms. Returns array of room summaries.

$rooms = $client->listRooms(limit: 50);
foreach ($rooms as $name => $meta) {
    echo "{$name}: {$meta['tile_count']} tiles\n";
}

createRoom()

$room = $client->createRoom(string $roomId, string $description = ''): array;

Create a new room.

$client->createRoom('fleet_orchestration', 'Fleet coordination knowledge');

getRoom()

$room = $client->getRoom(string $roomId): array;

Get room details including all tiles.

$room = $client->getRoom('oracle1_history');
echo count($room['tiles']) . " tiles in this room\n";

deleteRoom()

$deleted = $client->deleteRoom(string $roomId): bool;

Delete a room. Returns true on success, false if room not found.

submitTile()

$result = $client->submitTile(
    string $roomId,
    string $question,
    string $answer,
    array $metadata = []
): array;

Submit a tile to a room. The server validates through deadband gates (length, no absolute claims).

$result = $client->submitTile(
    'my_room',
    'What is a deadband?',
    'A deadband is a range of values where a system does not react to input changes.',
    ['confidence' => 0.8, 'source' => 'oracle1']
);
echo "Accepted: " . ($result['status'] === 'accepted') . "\n";

getTile()

$tile = $client->getTile(string $roomId, string $tileId): array;

Get a specific tile by ID from a room.

queryTiles()

$tiles = $client->queryTiles(string $roomId, string $query, int $limit = 20): array;

Search tiles by query string. Filters by room if $roomId is non-empty.

$results = $client->queryTiles('fleet_orchestration', 'consciousness', limit: 10);

getRecentTiles()

$tiles = $client->getRecentTiles(string $roomId, int $limit = 20): array;

Get most recent tiles from a room, sorted newest first.

streamTiles()

$client->streamTiles(string $roomId, callable $callback): void;

Stream tiles in real-time using SSE or long-polling. The callback receives each new tile.

$client->streamTiles('oracle1_history', function(array $tile) {
    echo "New tile: {$tile['question']}\n";
});
// Runs indefinitely — use in a separate process or with timeout

registerAgent()

$result = $client->registerAgent(string $agentId, array $capabilities): array;

Register a fleet agent with the server.

$result = $client->registerAgent('my-agent-php', ['search', 'submit', 'query']);

setTimeout()

$client->setTimeout(int $seconds): void;

Set the request timeout. Default is 10 seconds.


Value Objects

Tile

use SuperInstance\PlatoClient\Tile;

$tile = Tile::fromArray($data);
echo $tile->id;          // tile hash
echo $tile->question;    // anchor text
echo $tile->answer;       // content
echo $tile->confidence;  // 0.0-1.0

$arr = $tile->toArray();       // convert to array
$valid = $tile->validate();    // check required fields

Room

use SuperInstance\PlatoClient\Room;

$room = Room::fromArray($data);
echo $room->id;          // room name
echo $room->tileCount;   // number of tiles
echo $room->description; // room purpose

Query Builder

Use TileQuery to construct complex searches:

use SuperInstance\PlatoClient\TileQuery;

$query = TileQuery::create('fleet_orchestration')
    ->whereConfidence(min: 0.7)
    ->whereAuthor('oracle1')
    ->whereQuestionContains('consciousness')
    ->orderBy('created_at', 'desc')
    ->limit(20);

$results = $query->execute($client);
// Or pass the query string directly:
$tiles = $client->queryTiles('fleet_orchestration', $query->build());

Available filters:

  • whereConfidence(float $min) — minimum confidence score
  • whereAuthor(string $author) — filter by submitter
  • whereUpdatedSince(DateTime $since) — tiles updated after this time
  • whereUpdatedUntil(DateTime $until) — tiles updated before this time
  • whereQuestionContains(string $text) — question contains text
  • whereAnswerContains(string $text) — answer contains text
  • whereMetadataKey(string $key, $value) — filter by metadata field
  • whereLinkedTo(string $tileId) — tiles linked to a specific tile
  • orderBy(string $field, string $direction) — sort field and direction
  • limit(int $n) — result limit

Agent Registry

Helper for fleet agent operations:

use SuperInstance\PlatoClient\AgentRegistry;

// Register an agent
AgentRegistry::registerAgent($client, 'my-agent', ['search', 'submit']);

// Send heartbeat
$ok = AgentRegistry::heartbeat($client, 'my-agent');

// Get agent status
$status = AgentRegistry::getAgentStatus($client, 'my-agent');
echo $status['status'];  // 'active', 'unknown', etc.

Error Handling

All errors throw PlatoException with a PlatoErrorCode:

use SuperInstance\PlatoClient\PlatoClient;
use SuperInstance\PlatoClient\PlatoException;
use SuperInstance\PlatoClient\PlatoErrorCode;

try {
    $client->submitTile('room', 'Q', 'A');
} catch (PlatoException $e) {
    match ($e->getErrorCode()) {
        PlatoErrorCode::CONNECTION_ERROR => print "Cannot reach server\n",
        PlatoErrorCode::ROOM_NOT_FOUND => print "Room doesn't exist\n",
        PlatoErrorCode::AUTH_ERROR => print "Authentication failed\n",
        PlatoErrorCode::TILE_NOT_FOUND => print "Tile not found\n",
        PlatoErrorCode::QUERY_ERROR => print "Bad query syntax\n",
        PlatoErrorCode::SERVER_ERROR => print "Server error: {$e->getMessage()}\n",
        PlatoErrorCode::TIMEOUT => print "Request timed out\n",
    };
}

Static factories for common errors:

PlatoException::connectionError('http://localhost:8847');
PlatoException::connectionRefused('http://localhost:8847');
PlatoException::timeout('http://localhost:8847', 10);
PlatoException::authError();
PlatoException::roomNotFound('my_room');
PlatoException::tileNotFound('my_room', 'abc123');
PlatoException::queryError('invalid query syntax');
PlatoException::serverError('Internal error', 500);

Environment Variables

Variable Description Default
PLATO_API_TOKEN API token for authentication none
PLATO_SERVER_URL Base URL for CLI commands http://localhost:8847

CLI Tool

# Check server status
php src/CLI.php status

# List rooms
php src/CLI.php rooms --limit=50

# List tiles in a room
php src/CLI.php tiles fleet_orchestration --limit=20

# Submit a tile
php src/CLI.php submit my_room "What is Phi?" "Phi measures knowledge integration."

# Query tiles
php src/CLI.php query fleet_orchestration "consciousness" --limit=10

# Stream tiles in real-time
php src/CLI.php stream oracle1_history

# Agent management
php src/CLI.php agent register --agent-id=my-agent --capabilities=search,submit
php src/CLI.php agent heartbeat --agent-id=my-agent
php src/CLI.php agent status --agent-id=my-agent

HTTP Implementation

  • Uses cURL if available, falls back to file_get_contents with stream context
  • 10-second default timeout, configurable via setTimeout()
  • JSON-encoded request bodies
  • Bearer token authentication when apiToken is set
  • Connection refused and timeout errors throw typed PlatoException

Real PLATO API Examples

Full workflow: submit and query

$client = new PlatoClient('http://localhost:8847');

// Create a room if it doesn't exist
try {
    $client->createRoom('knowledge_fleet', 'Fleet knowledge base');
} catch (PlatoException $e) {
    // Room may already exist — that's fine
}

// Submit a tile
$tile = $client->submitTile(
    'knowledge_fleet',
    'How does agent registration work?',
    'Agents register via POST /agents/{agent_id} with capabilities list. ' .
    'They send periodic heartbeats to stay active in the fleet registry.',
    ['confidence' => 0.85, 'source' => 'oracle1']
);

// Query for it
$results = $client->queryTiles('knowledge_fleet', 'agent registration');
foreach ($results as $result) {
    echo "{$result['question']}: {$result['answer']}\n";
}

// Use query builder for complex searches
$tiles = TileQuery::create('knowledge_fleet')
    ->whereConfidence(0.7)
    ->whereAuthor('oracle1')
    ->orderBy('created_at', 'desc')
    ->limit(10)
    ->execute($client);

Streaming live updates

$client = new PlatoClient('http://localhost:8847');
$count = 0;

$client->streamTiles('oracle1_history', function(array $tile) use (&$count) {
    $count++;
    echo "[{$count}] {$tile['question']}\n";
    echo "   Answer: " . substr($tile['answer'], 0, 100) . "...\n";
});

Agent heartbeat loop

$client = new PlatoClient('http://localhost:8847');
$agentId = 'background-worker-php';

AgentRegistry::registerAgent($client, $agentId, ['search', 'submit']);

while (true) {
    $ok = AgentRegistry::heartbeat($client, $agentId);
    echo $ok ? "Heartbeat OK\n" : "Heartbeat failed\n";
    sleep(30); // every 30 seconds
}

🦐 Cocapn fleet — lighthouse keeper architecture

About

PHP client library for PLATO room server — interact with PLATO tiles, rooms, and agent registry

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages