Install the Bundle
composer require agtp/agtp-symfony
Enable the bundle in config/bundles.php (Symfony Flex handles this automatically).
Set Up agtpd
Ensure the AGTP daemon (agtpd) is running locally or on the same host, typically via:
# Example: Running agtpd in a Docker container
docker run -p 4480:4480 -v /etc/agtpd:/etc/agtpd nomoticai/agtpd
Create a Handler
Define a service class with an #[AgtpEndpoint]-annotated method:
use Agtp\AgtpEndpoint;
final class GreetingHandler
{
#[AgtpEndpoint(method: 'GREET', path: '/hello')]
public function greet(): string {
return "Hello, AGTP!";
}
}
Register the Service
Tag the handler in config/services.yaml:
services:
App\Agtp\GreetingHandler:
tags: ['agtp.endpoint']
Export the Manifest Generate the daemon manifest:
bin/console agtp:export-manifest --output=/etc/agtpd/endpoints
Run the Worker Start the AGTP worker:
bin/console agtp:serve --gateway-socket=/var/run/agtpd/gateway.sock
Build a lightweight, high-performance API endpoint (e.g., a booking system) without the overhead of HTTP request/response cycles. AGTP’s long-lived workers reduce kernel boot time to a one-time cost, making it ideal for:
Handler Development
#[AgtpEndpoint] attributes to define endpoints (method, path, scopes, errors).EntityManager, Logger) via constructor.EndpointResponse or EndpointError for success/failure.#[AgtpEndpoint(
method: 'CREATE',
path: '/user',
requiredScopes: ['user:create'],
errors: ['user_exists']
)]
public function createUser(EndpointContext $ctx): EndpointResponse|EndpointError {
if ($this->userExists($ctx->input['email'])) {
return new EndpointError('user_exists', 'Email already registered.');
}
return new EndpointResponse(['user_id' => $this->saveUser($ctx->input)]);
}
Service Tagging
agtp.endpoint via:
tags: ['agtp.endpoint']).#[AutoconfigureTag('agtp.endpoint')]).Manifest Management
agtp:export-manifest after every handler change to update agtpd.--dry-run to preview changes:
bin/console agtp:export-manifest --dry-run
Worker Deployment
agtp:serve manually.Deployment:
[Service]
ExecStart=/usr/bin/php bin/console agtp:serve --gateway-socket=/run/agtpd.sock
Restart=always
Testing
Agtp\Testing to mock EndpointContext and assert responses:
public function testCreateUserSuccess() {
$handler = new UserHandler($this->createMock(EntityManagerInterface::class));
$ctx = Testing::makeContext(['email' => 'test@example.com']);
$response = Testing::assertOk($handler->createUser($ctx));
$this->assertArrayHasKey('user_id', $response->body);
}
EntityManagerInterface or repositories into handlers.$ctx->agentId and $ctx->authorityScope for pre-verified identity/scope.#[AgtpEndpoint] and return EndpointError with details.LoggerInterface for debugging:
public function __construct(private readonly LoggerInterface $logger) {}
$this->logger->info('Handler invoked', ['input' => $ctx->input]);
Manifest Staleness
agtp:export-manifest after adding/updating handlers causes agtpd to ignore changes.# Example Git hook (in .git/hooks/post-commit)
php bin/console agtp:export-manifest --output=/etc/agtpd/endpoints
Worker Crashes
try {
return $handler->method($ctx);
} catch (\Throwable $e) {
return new EndpointError('internal_error', $e->getMessage());
}
Socket Permissions
agtp:serve fails with "Permission denied" on /var/run/agtpd/gateway.sock.www-data):
sudo chown www-data:www-data /var/run/agtpd/gateway.sock
Scope Mismatches
requiredScopes.agtpd config and test with:
bin/console agtp:export-manifest --dry-run | grep requiredScopes
Testing Context
$ctx->input is empty or malformed.EndpointContext with Testing::makeContext() and validate input:
$ctx = Testing::makeContext(['room_type' => 'single']);
$this->assertEquals('single', $ctx->input['room_type']);
agtp:serve output for errors (e.g., missing socket, invalid TOML).agtpd logs (journalctl -u agtpd or container logs) for protocol-level issues.--dry-run to validate TOML syntax before deployment.Custom Error Handlers
Agtp\EndpointError or create a middleware-like service to transform errors:
$errorHandler = new CustomErrorHandler();
return $errorHandler->handle($error);
Context Enhancement
EndpointContext by adding properties to the TOML manifest or via a custom context class.Dynamic Endpoints
#[AgtpEndpoint] attributes dynamically (e.g., from a database) using reflection or a compiler pass.Cross-Protocol Integration
Router to dispatch to AGTP handlers.agtpd’s configured socket (default: /var/run/agtpd/gateway.sock).agtp:export-manifest requires valid TOML. Use a linter like tomal to validate.agtp:serve process handles all endpoints. For isolation, use separate processes or namespaces.php -m or htop.agtpd supports multiple module connections. Scale workers horizontally by running multiple instances.How can I help you explore Laravel packages today?