| Install | |
|---|---|
composer require helgesverre/pagent |
|
| Latest Version: | v1.0.0 |
| PHP: | ^8.3 |
A Pest-inspired LLM Agent Framework for PHP
Build intelligent agents with automatic tool calling, multi-provider support, safety guards, and multi-agent orchestrationβall with a clean, fluent API.
composer require helgesverre/pagent
Requirements:
// Configure an agent
agent('assistant')
->provider('anthropic')
->system('You are a helpful assistant')
->temperature(0.7);
// Use the agent
$response = agent('assistant')->prompt('Hello!');
echo $response->content;
// Or stream responses in real-time
agent('assistant')->streamTo('Tell me a story', function ($chunk) {
if ($chunk->isText()) {
echo $chunk->content;
flush();
}
});
// Persist conversations across sessions
agent('support')
->memory('sqlite', ['path' => 'storage/conversations.db'])
->sessionId('user-123')
->contextWindow(100000)
->prompt('Hello');
π Explore: Streaming Guide | Memory & Persistence
$mock = mock([
'Hello' => 'Hi there!',
'How are you?' => 'I am doing great!'
]);
$response = $mock->prompt('Hello');
echo $response->content; // "Hi there!"
export ANTHROPIC_API_KEY="your-key"
$claude = anthropic();
$response = $claude->prompt('Hello!', [
'model' => 'claude-3-sonnet-20240229',
'max_tokens' => 100
]);
export OPENAI_API_KEY="your-key"
$gpt = openai();
$response = $gpt->prompt('Hello!', [
'model' => 'gpt-4',
'temperature' => 0.8
]);
Run models locally with complete privacy and zero API costs:
# Install Ollama and pull models
ollama pull qwen3:8b
ollama pull gpt-oss:20b
ollama serve
$ollama = ollama();
$response = $ollama->prompt('Hello!', [
'model' => 'qwen3:8b',
'temperature' => 0.7
]);
Benefits:
π Full Guide: Ollama Integration
Agents provide a higher-level abstraction with conversation history:
// Define an agent
agent('support')
->provider('anthropic')
->system('You are a customer support agent')
->model('claude-3-haiku-20240307')
->temperature(0.3);
// Have a conversation
$agent = agent('support');
$agent->prompt('I need help with my order');
$agent->prompt('Order number is 12345');
// Access conversation history
foreach ($agent->messages as $message) {
echo "[{$message['role']}]: {$message['content']}\n";
}
Pagent supports two ways to configure providers:
Use provider names for quick setup with default configuration:
agent('assistant')
->provider('anthropic') // String name
->system('You are helpful');
// With config options
agent('custom')
->provider('ollama', ['base_url' => 'http://custom:11434', 'timeout' => 180])
->model('qwen3:8b');
Use helper functions or direct instantiation for custom configuration:
// Using helper functions
agent('assistant')
->provider(anthropic(['api_key' => 'custom-key']))
->prompt('Hello');
agent('local')
->provider(ollama(['timeout' => 300, 'base_url' => 'http://10.0.0.5:11434']))
->model('llama3.1');
// Direct instantiation
use Pagent\Providers\OpenAI;
agent('custom')
->provider(new OpenAI(['api_key' => getenv('CUSTOM_KEY')]))
->prompt('Hello');
When to use each:
The library is intentionally "leaky" - you can use provider-specific features:
// Anthropic-specific models
$response = anthropic()->prompt('Complex analysis task', [
'model' => 'claude-3-opus-20240229',
'max_tokens' => 4096
]);
// OpenAI-specific features
$response = openai()->prompt('Generate JSON data', [
'model' => 'gpt-3.5-turbo-1106',
'response_format' => ['type' => 'json_object']
]);
Define tools using PHP closures with automatic JSON schema generation:
use Pagent\Tool\Tool;
// Create a tool from a closure
$weatherTool = Tool::fromClosure(
'get_weather',
'Get the current weather for a location',
fn(string $location, bool $include_forecast = false) => "Weather data..."
);
// Add tools to an agent
$agent = agent('assistant')
->provider('anthropic')
->tool('calculate', 'Perform calculations', fn(int $a, int $b) => $a + $b)
->tool('get_time', 'Get current time', fn(string $tz = 'UTC') => date('H:i:s'));
// Execute tools
$result = $agent->executeTool('calculate', [10, 5]); // 15
// Generate provider-specific schemas
$anthropicSchema = $weatherTool->toAnthropicSchema();
$openaiSchema = $weatherTool->toOpenAISchema();
Type hints are automatically converted to JSON schema types:
string β "string"int β "integer"float β "number"bool β "boolean"array β "array"Pagent includes 9 production-ready class-based tools in the Pagent\Tools namespace:
use Pagent\Tools\FileRead;
use Pagent\Tools\FileWrite;
use Pagent\Tools\WebFetch;
use Pagent\Tools\Bash;
use Pagent\Tools\Grep;
use Pagent\Tools\Glob;
use Pagent\Tools\PdfReader;
use Pagent\Tools\DataExtract;
use Pagent\Tools\SearchTool;
// Use class-based tools with agents
$agent = agent('assistant')
->provider('anthropic')
->tool(new FileRead())
->tool(new WebFetch())
->prompt('Read the file data.json and fetch https://api.example.com/data');
// Add multiple tools at once
$agent = agent('file-assistant')
->provider('anthropic')
->tools([
new FileRead(baseDir: '/project'),
new FileWrite(baseDir: '/project'),
new Glob(baseDir: '/project'),
new Grep(baseDir: '/project'),
])
->prompt('List all PHP files and show me the config');
// Create custom class-based tools
use Pagent\Tools\Tool;
class DatabaseQuery extends Tool
{
public function name(): string
{
return 'query_database';
}
public function description(): string
{
return 'Execute a database query and return results';
}
public function parameters(): array
{
return [
'type' => 'object',
'properties' => [
'query' => ['type' => 'string', 'description' => 'SQL query to execute'],
'limit' => ['type' => 'integer', 'description' => 'Maximum rows to return'],
],
'required' => ['query'],
];
}
public function execute(array $params): mixed
{
// Your implementation here
return ['results' => []];
}
}
// Use your custom tool
agent('assistant')->tool(new DatabaseQuery());
Both closure-based and class-based tools implement ToolInterface and work seamlessly with all providers.
The SearchTool provides powerful full-text search capabilities powered by TNTSearch, enabling agents to search through documents, files, and databases:
use Pagent\Tools\SearchTool;
// Search through an array of documents (RAG pattern)
$documents = [
['id' => 1, 'title' => 'PHP Guide', 'content' => 'Learn PHP programming...'],
['id' => 2, 'title' => 'Laravel Tutorial', 'content' => 'Build web apps with Laravel...'],
];
agent('docs-assistant')
->tools([searchDocuments($documents)])
->prompt('Find information about PHP');
// Search through files in a directory
agent('codebase-helper')
->tools([new SearchTool(paths: ['docs/', 'src/'])])
->prompt('Find all documentation about API endpoints');
// Use a pre-built search index
agent('knowledge-bot')
->tools([searchIndex('knowledge/docs.index')])
->prompt('Search the knowledge base for deployment guides');
// Database-backed search
agent('db-search')
->tools([
new SearchTool(
query: 'SELECT id, title, content FROM articles',
connection: ['driver' => 'mysql', 'host' => 'localhost', 'database' => 'mydb']
)
])
->prompt('Find articles about Laravel');
Key Features:
Configuration Options:
new SearchTool(
documents: $docs, // Array of documents to index
returnContent: true, // Return full documents vs just IDs
fuzzy: true, // Enable fuzzy search
fuzziness: 2, // Levenshtein distance (1-3)
maxResults: 20, // Max results to return
storage: ':memory:', // Index storage location
stemmer: PorterStemmer::class // Custom stemmer class
);
Search Results:
[
'hits' => 3,
'execution_time' => '1.5ms',
'results' => [
['id' => 1, 'score' => 4.2, 'document' => [...]],
['id' => 2, 'score' => 3.8, 'document' => [...]],
]
]
Perfect for building:
Pagent includes comprehensive OpenTelemetry instrumentation for monitoring and debugging your LLM agents in production.
use function Pagent\{agent, telemetry_console};
// Enable console telemetry for debugging
telemetry_console(verbose: true);
agent('assistant')
->provider('anthropic')
->telemetry(true) // Enable tracing for this agent
->prompt('Hello!');
// Console shows:
// ββ Span: agent.prompt
// β Duration: 1.23s
// β Attributes:
// β - gen_ai.system: anthropic
// β - gen_ai.usage.total_tokens: 125
// ββ
Connect to Jaeger, Zipkin, or any OpenTelemetry-compatible platform:
use function Pagent\{agent, telemetry_jaeger};
// Export to Jaeger
telemetry_jaeger('http://localhost:14268/api/traces');
// All operations automatically traced
agent('support')
->telemetry(true)
->tool('search', 'Search knowledge base', $searchFn)
->prompt('Help me find documentation');
// View traces at http://localhost:16686
use function Pagent\{agent, pipeline, telemetry_jaeger};
telemetry_jaeger('http://localhost:14268/api/traces');
// Enable telemetry on agents
agent('researcher')->provider('anthropic')->telemetry(true);
agent('writer')->provider('anthropic')->telemetry(true);
// Run workflow - creates hierarchical trace
pipeline('content-creation')
->step('research', agent('researcher'))
->step('write', agent('writer'))
->run('Write article about PHP');
// Trace shows:
// workflow.pipeline
// ββ workflow.step (research)
// β ββ agent.prompt β llm.request β tool.execute
// ββ workflow.step (write)
// ββ agent.prompt β llm.request
π Full Guide: Observability Documentation
# Setup project
just setup # Install dependencies and git hooks
# Testing
just test # Run all tests
just coverage # Run tests with coverage report
# Code Quality
just format # Fix code style (PHP + Markdown)
just analyse # Run PHPStan static analysis
just pr # Prepare for PR (fix, analyse, test)
# Observability Stack
just obs-up # Start observability tools (Jaeger, Phoenix, Langfuse, etc.)
just obs-down # Stop and remove observability stack
# Run unit tests (no API calls)
./vendor/bin/pest --exclude-group=api
# Run API integration tests (requires API keys)
cp .env.example .env # Add your keys to .env
./vendor/bin/pest --group=api
The Pagent Guide is a comprehensive 28-chapter tutorial covering everything from basics to advanced patterns:
See guide/README.md for learning paths based on your experience level.
Learn how to integrate Pagent into your application:
Deep-dive into specific features:
See the docs/ folder for all guides.
We welcome contributions! Please see CONTRIBUTING.md for details on:
Read our Code of Conduct and Security Policy.
See CHANGELOG.md for recent changes.
MIT License. See LICENSE for details.
Created by Helge Sverre.
Inspired by Pest's elegant API design.