A step-by-step guide to mastering the Prompts system in Claude PHP Agent framework.
- Introduction
- Getting Started with PromptTemplate
- Building Conversations with ChatTemplate
- Few-Shot Learning
- Using the PromptLibrary
- Advanced Composition
- Best Practices
- Real-World Examples
The Prompts system helps you create reusable, validated, and composable prompts for your LLM applications. Instead of building prompts with string concatenation, you use structured templates that:
- Validate inputs - Ensure all required variables are provided
- Enable reuse - Create once, use many times
- Compose easily - Combine simple templates into complex prompts
- Maintain clarity - Separate prompt structure from data
Let's create a simple template for summarization:
use ClaudeAgents\Prompts\PromptTemplate;
$template = PromptTemplate::create(
'Summarize the following text in {length}:\n\n{text}'
);The {length} and {text} are variables that will be replaced when you format the template.
Now provide the values and get your prompt:
$prompt = $template->format([
'text' => 'Claude is a large language model created by Anthropic...',
'length' => '2 sentences',
]);
echo $prompt;
// Output:
// Summarize the following text in 2 sentences:
//
// Claude is a large language model created by Anthropic...See what variables your template needs:
$variables = $template->getVariables();
// Returns: ['length', 'text']Ensure all required variables are provided:
try {
$template->validate(['text' => 'Some text']);
// Missing 'length' - will throw ValidationException
} catch (\ClaudeAgents\Exceptions\ValidationException $e) {
echo $e->getMessage();
// Helpful error message with what's missing and what's available
}Try creating your own template:
$translator = PromptTemplate::create(
'Translate "{text}" from {source_language} to {target_language}'
);
$prompt = $translator->format([
'text' => 'Hello world',
'source_language' => 'English',
'target_language' => 'Spanish',
]);ChatTemplate is perfect for multi-turn conversations:
use ClaudeAgents\Prompts\ChatTemplate;
$chat = ChatTemplate::create()
->system('You are a {expertise} expert')
->user('I need help with {problem}')
->assistant('I understand. Let me help you with {problem}.')
->user('Specifically, I want to {specific_request}');Get an array of messages ready for the API:
$messages = $chat->format([
'expertise' => 'PHP',
'problem' => 'performance optimization',
'specific_request' => 'reduce database queries',
]);
// Returns array of message objects:
// [
// ['role' => 'system', 'content' => 'You are a PHP expert'],
// ['role' => 'user', 'content' => 'I need help with performance optimization'],
// ...
// ]Send to Claude:
$response = $client->messages()->create([
'model' => 'claude-sonnet-4-5',
'messages' => $messages,
'max_tokens' => 1024,
]);Create a support conversation template:
$support = ChatTemplate::create()
->system('You are a {company} support agent. Be {tone} and helpful.')
->user('I have an issue: {issue}')
->assistant('I apologize for the inconvenience. Let me help you with {issue}.')
->user('My account is: {account_id}');
$messages = $support->format([
'company' => 'Acme Inc',
'tone' => 'friendly',
'issue' => 'login problems',
'account_id' => '12345',
]);Few-shot learning teaches the LLM by example. The FewShotTemplate makes this easy.
Collect input-output pairs:
$examples = [
['input' => 'I love this product!', 'output' => 'positive'],
['input' => 'Terrible experience', 'output' => 'negative'],
['input' => 'It works fine', 'output' => 'neutral'],
];Use the classification factory:
use ClaudeAgents\Prompts\FewShotTemplate;
$template = FewShotTemplate::forClassification(
$examples,
['positive', 'negative', 'neutral']
);$prompt = $template->format([
'input' => 'Best purchase ever!'
]);
// The prompt includes all examples followed by the new inputBuild your own from scratch:
$custom = FewShotTemplate::create()
->withPrefix('Extract named entities from text.')
->addExample('John works at Google', 'Person: John, Company: Google')
->addExample('Paris is in France', 'City: Paris, Country: France')
->withSuffix('Now extract from:')
->withInputTemplate('{text}')
->withExampleFormat('Text: ', 'Entities: ');
$prompt = $custom->format(['text' => 'Alice lives in Tokyo']);Create a few-shot template that converts code style:
$styleConverter = FewShotTemplate::create()
->withPrefix('Convert code to follow PSR-12 style guide')
->addExample(
'function test(){return true;}',
'function test()\n{\n return true;\n}'
)
->addExample(
'class foo{private $bar;}',
'class Foo\n{\n private $bar;\n}'
)
->withInputTemplate('{code}');Don't reinvent the wheel! Use pre-built templates.
use ClaudeAgents\Prompts\PromptLibrary;
// Summarization
$summary = PromptLibrary::summarization();
$prompt = $summary->format([
'text' => 'Long article...',
'length' => '3 sentences'
]);
// Sentiment analysis
$sentiment = PromptLibrary::sentimentAnalysis();
$prompt = $sentiment->format(['text' => 'Customer review...']);
// Question answering
$qa = PromptLibrary::questionAnswering();
$prompt = $qa->format([
'context' => 'Background information...',
'question' => 'What is the main point?'
]);
// Code review
$review = PromptLibrary::codeReview();
$prompt = $review->format([
'code' => 'class Example { ... }',
'language' => 'PHP'
]);- Text Processing: summarization, rewrite, translation
- Classification: classification, sentiment analysis, entity extraction
- Q&A: question answering, fact checking
- Code: code explanation, code review, SQL generation, API docs
- Creative: brainstorming, creative writing
- Analysis: comparison, pros/cons, error diagnosis
- Communication: email responses, meeting notes
Create a content analysis pipeline:
// Step 1: Extract entities
$extraction = PromptLibrary::entityExtraction();
$entities = $extraction->format(['text' => $article]);
// Step 2: Analyze sentiment
$sentiment = PromptLibrary::sentimentAnalysis();
$feeling = $sentiment->format(['text' => $article]);
// Step 3: Summarize
$summary = PromptLibrary::summarization();
$brief = $summary->format(['text' => $article, 'length' => '2 sentences']);For complex prompts, use PromptComposer.
Combine multiple sections:
use ClaudeAgents\Prompts\PromptComposer;
$composer = PromptComposer::create()
->addText('Task: {task}')
->addText('Context: {context}')
->addText('Requirements:')
->addList('requirements', '- {item}')
->addText('Please provide detailed output.')
->withSeparator("\n\n");
$prompt = $composer->compose([
'task' => 'Build a login system',
'context' => 'PHP 8.1, MySQL database',
'requirements' => ['Secure password hashing', 'Email verification', 'Rate limiting'],
]);Add sections only when needed:
$composer = PromptComposer::create()
->addText('Analyze: {code}')
->addIfVariable('context', 'Context: {context}')
->addConditional(
'This is a HIGH PRIORITY review',
fn($values) => ($values['priority'] ?? '') === 'high'
);
// Context appears only if provided
// Priority notice appears only if priority is 'high'
$prompt = $composer->compose([
'code' => 'function example() { }',
'context' => 'Legacy code',
'priority' => 'high',
]);Add formatted lists:
$composer = PromptComposer::create()
->addText('Project Plan')
->addList('tasks', '✓ {item}', 'Tasks:')
->addList('blockers', '⚠ {item}', 'Blockers:');
$prompt = $composer->compose([
'tasks' => ['Design database', 'Implement API', 'Write tests'],
'blockers' => ['Waiting for API keys', 'Server not provisioned'],
]);Combine composition with few-shot learning:
$composer = PromptComposer::create()
->addText('Task: Classify sentiment')
->addExamples('training_examples', 'Review: ', 'Sentiment: ')
->addText('Now classify: {input}');
$prompt = $composer->compose([
'training_examples' => [
['input' => 'Love it!', 'output' => 'positive'],
['input' => 'Hate it', 'output' => 'negative'],
],
'input' => 'Pretty good',
]);Create a comprehensive code review prompt:
$codeReview = PromptComposer::create()
->addText('=== CODE REVIEW ===')
->addText('Language: {language}')
->addIfVariable('project_context', 'Project: {project_context}')
->addText('Code:\n```{language}\n{code}\n```')
->addList('focus_areas', '• {item}', 'Review Focus:')
->addIfVariable('previous_issues', 'Previous Issues:\n{previous_issues}')
->addText('Provide detailed analysis with:')
->addList('output_sections', '{item}', '')
->withSeparator("\n\n");
$prompt = $codeReview->compose([
'language' => 'PHP',
'project_context' => 'Payment processing',
'code' => 'function processPayment($amount) { ... }',
'focus_areas' => ['Security', 'Error handling', 'Input validation'],
'output_sections' => ['1. Security issues', '2. Code quality', '3. Recommendations'],
]);Always validate before using templates in production:
$template = PromptTemplate::create('Hello {name}');
if (isset($_POST['name'])) {
try {
$template->validate($_POST);
$prompt = $template->format($_POST);
// Safe to use
} catch (\ClaudeAgents\Exceptions\ValidationException $e) {
// Handle missing variables
logError($e->getMessage());
}
}// Good
$template = PromptTemplate::create(
'Translate {source_text} from {source_language} to {target_language}'
);
// Less clear
$template = PromptTemplate::create(
'Translate {text} from {lang1} to {lang2}'
);// Instead of recreating:
$template = PromptTemplate::create('Analyze sentiment of: {text}');
// Use the library:
$template = PromptLibrary::sentimentAnalysis();// Rigid
$prompt = "Task: $task\nContext: $context\nRequirements:\n- $req1\n- $req2";
// Flexible
$composer = PromptComposer::create()
->addText('Task: {task}')
->addIfVariable('context', 'Context: {context}')
->addList('requirements', '- {item}', 'Requirements:');
// Works with or without optional fields// Define once
class MyTemplates {
public static function productReview(): FewShotTemplate {
return FewShotTemplate::forClassification(
self::getReviewExamples(),
['positive', 'negative', 'neutral']
);
}
private static function getReviewExamples(): array {
return [
['input' => 'Great product!', 'output' => 'positive'],
// ... more examples
];
}
}
// Use everywhere
$template = MyTemplates::productReview();
$prompt = $template->format(['input' => $userReview]);use ClaudeAgents\Prompts\ChatTemplate;
use ClaudeAgents\Prompts\PromptComposer;
// Conversation template
$support = ChatTemplate::create()
->system('You are a {company} support agent. Tone: {tone}. Priority: {priority}')
->user('Issue: {issue}\nAccount: {account_id}')
->assistant('Let me help you with this {priority} priority issue.');
// Dynamic knowledge base injection
$composer = PromptComposer::create()
->addText('Relevant documentation:')
->addList('docs', '- {item}')
->addIfVariable('similar_cases', 'Similar resolved cases:\n{similar_cases}');
// Combine them
$messages = $support->format([
'company' => 'TechCorp',
'tone' => 'empathetic',
'priority' => 'high',
'issue' => 'Cannot login',
'account_id' => 'USR-12345',
]);
$context = $composer->compose([
'docs' => ['Password reset guide', 'Account recovery process'],
'similar_cases' => 'Case #5423: Reset password via email',
]);use ClaudeAgents\Prompts\FewShotTemplate;
$codeGen = FewShotTemplate::create()
->withPrefix('Generate {language} code based on description')
->addExample(
'Create a function that adds two numbers',
'function add($a, $b) {\n return $a + $b;\n}'
)
->addExample(
'Create a class with a private property and getter',
'class User {\n private $name;\n \n public function getName() {\n return $this->name;\n }\n}'
)
->withSuffix('Now generate code for:')
->withInputTemplate('{description}')
->withExampleFormat('Description: ', 'Code:\n```{language}\n');
$prompt = $codeGen->format([
'language' => 'PHP',
'description' => 'Create a function that validates an email address',
]);use ClaudeAgents\Prompts\PromptLibrary;
use ClaudeAgents\Chains\SequentialChain;
use ClaudeAgents\Chains\LLMChain;
// Step 1: Extract entities
$extractionChain = LLMChain::create($client)
->withPromptTemplate(PromptLibrary::entityExtraction());
// Step 2: Sentiment analysis
$sentimentChain = LLMChain::create($client)
->withPromptTemplate(PromptLibrary::sentimentAnalysis());
// Step 3: Summarize
$summaryChain = LLMChain::create($client)
->withPromptTemplate(PromptLibrary::summarization());
// Compose into pipeline
$pipeline = SequentialChain::create()
->addChain('extract', $extractionChain)
->addChain('sentiment', $sentimentChain)
->addChain('summary', $summaryChain);
$result = $pipeline->invoke([
'text' => $articleContent,
'length' => '3 sentences',
]);- Explore the full Prompts documentation
- Check out the complete demo
- Learn about Chains for prompt composition
- Study the source code for implementation details
// PromptTemplate
$t = PromptTemplate::create('Hello {name}');
$prompt = $t->format(['name' => 'Alice']);
// ChatTemplate
$c = ChatTemplate::create()
->system('You are {role}')
->user('{message}');
$messages = $c->format(['role' => 'helper', 'message' => 'Hi']);
// FewShotTemplate
$f = FewShotTemplate::forClassification($examples, $categories);
$prompt = $f->format(['input' => 'test']);
// PromptLibrary
$template = PromptLibrary::summarization();
$prompt = $template->format(['text' => '...', 'length' => '2 sentences']);
// PromptComposer
$composer = PromptComposer::create()
->addText('Task: {task}')
->addList('items', '- {item}')
->addIfVariable('context', 'Context: {context}');
$prompt = $composer->compose($values);