1. Go to this page and download the library: Download phpro/agent-rules library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
phpro / agent-rules example snippets
final class OrderRequest
{
public function __construct(
public readonly ?string $email,
public readonly ?string $productId,
public readonly ?int $quantity,
) {}
}
use Phpro\AgentRules\RuleInterface;
use Phpro\AgentRules\RuleEvaluation;
use Phpro\AgentRules\Result\IncompleteResult;
/**
* @implements RuleInterface<OrderRequest>
*/
class EmailRule implements RuleInterface
{
public function name(): string
{
return 'email_validation';
}
public function dependencies(): array
{
return []; // No dependencies
}
public function check(mixed $subject): RuleEvaluation
{
// Missing email? Ask for it!
if ($subject->email === null) {
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'email',
message: 'Please provide your email address to proceed.'
)
);
}
// Invalid format? Request correction!
if (!filter_var($subject->email, FILTER_VALIDATE_EMAIL)) {
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'email',
message: 'The email address is invalid. Please provide a valid email.'
)
);
}
// All good!
return RuleEvaluation::pass();
}
}
use Phpro\AgentRules\RuleEngine;
$engine = new RuleEngine(
new EmailRule(),
new ProductRule(),
new QuantityRule(),
);
$request = new OrderRequest(
email: null,
productId: 'PROD-123',
quantity: 2
);
$evaluation = $engine->evaluate($request);
if (!$evaluation->isPass()) {
$result = $evaluation->result;
echo $result->message; // "Please provide your email address to proceed."
echo $result->missingField; // "email"
}
return RuleEvaluation::respond(
new CompleteResult(
message: 'Order validated successfully!'
)
);
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'shippingAddress',
message: 'We need your shipping address to complete the order.'
)
);
return RuleEvaluation::respond(
new BlockedResult(
reason: 'Product out of stock',
message: 'This product is currently unavailable.'
)
);
return RuleEvaluation::respond(
new ErrorResult(
message: 'Unable to validate product availability.',
resolution: 'Please try again later or contact support.'
)
);
use Phpro\AgentRules\Sequence;
$allRequired = new Sequence(
new EmailRule(),
new ProductRule(),
new QuantityRule(),
);
use Phpro\AgentRules\Any;
$paymentMethod = new Any(
new CreditCardRule(),
new PayPalRule(),
new BankTransferRule(),
);
use Phpro\AgentRules\Either;
$authentication = new Either(
new OAuthRule(),
new PasswordRule(),
);
class DiscountRule implements RuleInterface
{
public function dependencies(): array
{
return ['product_validation', 'user_authentication'];
}
public function name(): string
{
return 'discount_calculation';
}
public function check(mixed $subject): RuleEvaluation
{
// This runs only after dependencies pass
// ...
}
}
use Phpro\AgentRules\Source\Source;
$result = new IncompleteResult(
missingField: 'productId',
message: 'Please provide the product ID.'
);
$result->sources()->add(
new Source(
name: 'Product Catalog',
reference: 'https://example.com/products',
content: 'Browse our product catalog to find product IDs.'
)
);
return RuleEvaluation::respond($result);
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('order.validation.rule', ['priority' => 100])]
class EmailRule implements RuleInterface
{
// ...
}
use Symfony\AI\Platform\Contract\JsonSchema\Attribute\With;
final class RegistrationRequest
{
public function __construct(
public readonly ?string $email = null,
#[With(minLength: 10, maxLength: 255)]
#[\SensitiveParameter]
public readonly ?string $password = null,
public readonly ?string $fullName = null,
public readonly ?bool $termsAccepted = null,
) {}
}
#[AutoconfigureTag('registration.rule', ['priority' => 100])]
class EmailRule implements RuleInterface
{
public function name(): string { return 'email'; }
public function dependencies(): array { return []; }
public function check(mixed $subject): RuleEvaluation
{
if (!$subject->email) {
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'email',
message: "What's your email address?"
)
);
}
if (!filter_var($subject->email, FILTER_VALIDATE_EMAIL)) {
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'email',
message: 'Please provide a valid email address.'
)
);
}
return RuleEvaluation::pass();
}
}
#[AutoconfigureTag('registration.rule', ['priority' => 90])]
class PasswordRule implements RuleInterface
{
public function name(): string { return 'password'; }
public function dependencies(): array { return ['email']; }
public function check(mixed $subject): RuleEvaluation
{
if (!$subject->password) {
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'password',
message: 'Please create a password (minimum 8 characters).'
)
);
}
if (strlen($subject->password) < 8) {
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'password',
message: 'Password must be at least 8 characters long.'
)
);
}
return RuleEvaluation::pass();
}
}
#[AsTool(
name: 'validate_registration',
description: 'Validates user registration data and requests missing information.'
)]
final class RegistrationTool implements HasSourcesInterface
{
use HasSourcesTrait;
public function __construct(
#[Autowire(service: 'RegistrationEngine')]
private RuleEngine $ruleEngine,
) {}
public function __invoke(
RegistrationRequest $request,
): ResultInterface {
$evaluation = $this->ruleEngine->evaluate($request);
$result = $evaluation->result ?? new CompleteResult(
message: 'Registration validated! Your account has been created.'
);
foreach ($result->sources() as $source) {
$this->addSource(new \Symfony\AI\Agent\Toolbox\Source\Source(
name: $source->name,
reference: $source->reference,
content: $source->content
));
}
return $result;
}
}
class ConditionalShippingRule implements RuleInterface
{
public function check(mixed $subject): RuleEvaluation
{
// Only check shipping if physical product
if ($subject->productType !== 'physical') {
return RuleEvaluation::pass();
}
if (!$subject->shippingAddress) {
return RuleEvaluation::respond(
new IncompleteResult(
missingField: 'shippingAddress',
message: 'Physical products
$checkoutValidation = new Sequence(
new UserAuthenticationRule(),
new Any(
new GuestCheckoutRule(),
new AccountRequiredRule(),
),
new Either(
new ExpressCheckoutRule(),
new Sequence(
new ShippingRule(),
new PaymentRule(),
new BillingRule(),
),
),
);
class InventoryRule implements RuleInterface
{
public function __construct(
private ProductRepository $products,
) {}
public function check(mixed $subject): RuleEvaluation
{
$product = $this->products->find($subject->productId);
if (!$product || $product->stock < $subject->quantity) {
return RuleEvaluation::respond(
new BlockedResult(
reason: 'Insufficient inventory',
message: 'This product is out of stock.'
)
);
}
// You could even save products based on the subject input.
return RuleEvaluation::pass();
}
}
use PHPUnit\Framework\TestCase;
class EmailRuleTest extends TestCase
{
public function test_it_requests_missing_email(): void
{
$rule = new EmailRule();
$request = new OrderRequest(email: null, productId: 'P1', quantity: 1);
$evaluation = $rule->check($request);
$this->assertFalse($evaluation->isPass());
$this->assertInstanceOf(IncompleteResult::class, $evaluation->result);
$this->assertEquals('email', $evaluation->result->missingField);
}
public function test_it_validates_email_format(): void
{
$rule = new EmailRule();
$request = new OrderRequest(email: 'invalid-email', productId: 'P1', quantity: 1);
$evaluation = $rule->check($request);
$this->assertFalse($evaluation->isPass());
$this->assertStringContainsString('valid email', $evaluation->result->message);
}
public function test_it_passes_with_valid_email(): void
{
$rule = new EmailRule();
$request = new OrderRequest(email: '[email protected]', productId: 'P1', quantity: 1);
$evaluation = $rule->check($request);
$this->assertTrue($evaluation->isPass());
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.