PHPackages                             agentadmit/agentadmit-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. agentadmit/agentadmit-sdk

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

agentadmit/agentadmit-sdk
=========================

AgentAdmit SDK for PHP - User-mediated AI agent authorization for Laravel

v1.4.0(2w ago)02proprietaryPHPPHP &gt;=8.1CI passing

Since Jun 11Pushed 1w agoCompare

[ Source](https://github.com/PhoenixCo-Founder/agentadmit-sdk-php)[ Packagist](https://packagist.org/packages/agentadmit/agentadmit-sdk)[ Docs](https://agentadmit.com)[ RSS](/packages/agentadmit-agentadmit-sdk/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (4)Versions (9)Used By (0)

AgentAdmit SDK for PHP (Laravel)
================================

[](#agentadmit-sdk-for-php-laravel)

User-mediated AI agent authorization. Plug-and-play for any Laravel app.

> **Get started:** Sign up at [agentadmit.com](https://agentadmit.com) → Get your test keys → Install the SDK → Build. Test keys are available immediately after signup. Live keys become available when you subscribe an app.

Quick Start
-----------

[](#quick-start)

```
composer require agentadmit/laravel
php artisan vendor:publish --tag=agentadmit-config
```

Add your credentials to `.env`:

```
AGENTADMIT_APP_ID=app_yourappid
AGENTADMIT_API_KEY=aa_test_yourkey
```

Add scope enforcement to any route:

```
// routes/api.php
Route::middleware('agentadmit.scope:read:orders')->get('/orders', [OrderController::class, 'index']);
```

Your app now supports AI agent connections with:

- Scoped access control (you define the scopes)
- User-controlled connection duration
- Token generation and exchange
- Mandatory introspection (every agent request validated through AgentAdmit)
- Revocation and remote audit logging (via the AgentAdmit hosted service)

How It Works
------------

[](#how-it-works)

1. User clicks "AgentAdmit" in your app
2. Selects scopes and connection duration
3. Gets a token to give to their AI agent
4. Agent exchanges the token for scoped API access
5. User revokes anytime

The token goes to the human, not the agent. No automated delivery = no prompt injection surface.

Important
---------

[](#important)

**Mandatory introspection.** All token validation goes through api.agentadmit.com. There is no self-hosted mode. No local JWT validation. No bypass. This is required for security, audit logging, and scope enforcement.

**Admin revocation.** As the app operator, you can revoke any user's agent connection by calling `TokensClient::revoke($connectionId)` from your backend (requires your operator API key).

**Embeddable admin panel.** Drop the `` React component into your admin section to view all agent connections, usage metrics, billing status, and revoke any connection without leaving your app. See the React SDK for details.

**In-app AI scopes.** If your app has built-in AI features (analysis, plan generation, photo recognition), do not expose those as agent scopes. The user's AI agent can read the raw data and do the analysis itself. Exposing in-app AI endpoints to agents creates double cost.

Consent Ledger (Caller-Identity Consent)
----------------------------------------

[](#consent-ledger-caller-identity-consent)

AgentAdmit can host per-user consent switches for three independent caller classes: `human_session`, `in_app_ai`, and `external_agent`. No class's setting implies another's.

**External agents:** the verify result already carries the verdict:

```
$result = $introspectionClient->verify($token);
if (!$result->consentGranted()) {
    abort(403, 'The data owner has not enabled external agent access.');
}
```

`consentGranted()` fails closed when the verdict is absent (the hosted service omits it while its consent store is unreadable). To keep serving during that degraded mode, resolve an absent verdict authoritatively with `ConsentClient::checkConsent($result->userId, 'external_agent')` — the `CallerConsent` middleware does this for you.

**Human sessions and in-app AI** never hold AgentAdmit tokens, so ask directly:

```
use AgentAdmit\ConsentClient;

$consent = new ConsentClient(config('agentadmit'));
$verdict = $consent->checkConsent('user_8842', ConsentClient::CALLER_CLASS_IN_APP_AI);
if (!$verdict['granted']) {
    // do not run AI over this user's data
}
```

Consent is orthogonal to revocation: a denied verdict means your app returns its own 403; the connection and token stay valid so the user can flip consent back on without re-connecting. Write switches through `PUT /api/v1/consent/settings` from your backend; export the audit trail with `GET /api/v1/consent/export` (every plan).

**One-middleware drop-in.** Instead of wiring the three paths by hand, the `agentadmit.caller_consent` middleware classifies the caller from the credential and evaluates the right independent path:

```
// config/agentadmit.php
'caller_consent' => [
    // derive the class from your own credential structure, never caller input
    'classify_non_agent' => fn ($request) => $request->headers->get('x-internal-ai') === env('INTERNAL_AI_SECRET')
        ? 'in_app_ai' : 'human_session',
    'resolve_data_owner_id' => fn ($request) => $request->route('owner_id'),
],

// routes: the middleware parameter is the required scope for external agents
Route::middleware('agentadmit.caller_consent:read:records')
    ->get('/api/records/{owner_id}', ...);
// Downstream: $request->attributes->get('agentadmit.caller_class' / 'agentadmit.consent')
```

External agents are checked via hosted introspection (consent verdict plus scope); in-app AI via the Consent Ledger (fail closed); the human path defers to your own permission model unless `caller_consent.gate_human` is true. It is a consent gate, not an authenticator, so register it after your own authentication.

Presence Verification (WebAuthn Step-Up)
----------------------------------------

[](#presence-verification-webauthn-step-up)

AgentAdmit can require the human behind a connection to complete a WebAuthn presence ceremony on the consent page. The verify result carries the outcome as an additive `presence` block, and the SDK surfaces it next to the consent verdict:

```
$result = $introspectionClient->verify($token);
if (!$result->presenceVerified()) {
    abort(403, 'This action requires a connection authorized with human presence verification.');
}
```

Or enforce it per route with the fail-closed middleware:

```
// routes/api.php
Route::middleware('agentadmit.presence')->post('/orders', [OrderController::class, 'store']);
```

`presenceVerified()` is strict: it returns `true` only when the platform reports `verified: true`. Connections minted without a ceremony, malformed blocks, and older servers that omit the block entirely all count as not verified, so guarded routes return a 403 with `error: presence_required`. Unlike consent, absence does not mean allowed: presence fails closed because a missing block means no ceremony was ever proven.

Rate Limiting
-------------

[](#rate-limiting)

The AgentAdmit introspection endpoint enforces rate limits. The PHP SDK handles HTTP 429 responses **automatically** with exponential backoff and jitter - no changes needed in your middleware code.

### Retry behavior

[](#retry-behavior)

ParameterDefaultDescriptionInitial delay1 secondFirst retry waitBackoff multiplier2×Doubles each retryCap30 secondsMaximum wait per retryJitter0–500 msRandom addition to each delayMax retries**3**ConfigurableThe SDK also respects the `Retry-After` response header - if present, it overrides the computed backoff delay.

### Configuring max retries

[](#configuring-max-retries)

In `config/agentadmit.php` or `.env`:

```
// config/agentadmit.php
'max_retries' => 5, // default: 3
```

```
AGENTADMIT_MAX_RETRIES=5
```

### Handling exhausted retries

[](#handling-exhausted-retries)

When all retries are exhausted, `IntrospectionClient::verify()` throws `RateLimitException`:

```
use AgentAdmit\RateLimitException;

try {
    $result = $client->verify($token);
} catch (RateLimitException $e) {
    return response()->json(['error' => 'rate_limited'], 429)
        ->header('Retry-After', $e->getRetryAfter() ?? 60);
}
```

`RateLimitException` methods:

- `getRetryAfter()` - seconds from `Retry-After` header (`null` if absent)
- `getLimit()` - `X-RateLimit-Limit` header value (`null` if absent)
- `getRemaining()` - `X-RateLimit-Remaining` header value (`null` if absent)
- `getReset()` - `X-RateLimit-Reset` Unix timestamp (`null` if absent)

Documentation
-------------

[](#documentation)

Full integration guide:

Data Collection &amp; Privacy
-----------------------------

[](#data-collection--privacy)

The AgentAdmit PHP SDK runs server-side and does not interact with app stores or end-user devices directly.

### What the SDK does

[](#what-the-sdk-does)

- Validates AgentAdmit tokens by calling AgentAdmit's hosted introspection endpoint (`https://api.agentadmit.com/api/v1/verify`) on every agent request - this is mandatory introspection; there is no local or offline validation mode
- Enforces scope-based access control on your API routes
- Manages connection lifecycle (issue, exchange, revoke) via the AgentAdmit hosted service

### What the SDK does NOT do

[](#what-the-sdk-does-not-do)

- Does not transmit raw end-user PII (such as name, email, or device identifiers) - each introspection request sends the opaque access token and your API key
- Does not perform passive background telemetry or analytics - network calls occur only during active token validation
- Does not maintain its own persistent storage; connection state and audit logs are held by the AgentAdmit hosted service

### What the AgentAdmit hosted service records

[](#what-the-agentadmit-hosted-service-records)

On every token validation, AgentAdmit's `/api/v1/verify` endpoint receives the access token and API key, resolves the token to its `user_id`, `connection_id`, granted `scopes`, and `agent_label`, and records per-call metadata (including the endpoint and timestamp) for billing, audit logging, the security alerts engine, and usage metering. This is integral to how AgentAdmit works and applies to both test and live keys. See the "Mandatory introspection" notes above and the [compliance guide](https://agentadmit.com/docs/compliance) for the full data-handling description.

### Privacy impact

[](#privacy-impact)

Since this SDK runs on your server, it has no direct App Store or Play Store compliance surface. Your client-side integration (e.g., the AgentAdmit React SDK) handles privacy manifest and data safety requirements.

For complete compliance guidance, see our [compliance guide](https://agentadmit.com/docs/compliance).

License
-------

[](#license)

All rights reserved. Patent pending.

Security Alerts
---------------

[](#security-alerts)

```
use AgentAdmit\AlertsClient;
$alerts = new AlertsClient(config('agentadmit'));
```

Six alert type constants on `AlertsClient`.

### Configure

[](#configure)

```
$alerts->configureAlerts('app_abc123', AlertsClient::ALERT_TYPE_VOLUME_SPIKE, [
    'enabled' => true, 'threshold_value' => 100, 'threshold_window_minutes' => 5,
    'kill_switch_enabled' => true,
]);
```

### List Events

[](#list-events)

```
$events = $alerts->listAlerts(appId: 'app_abc123', alertType: AlertsClient::ALERT_TYPE_VOLUME_SPIKE);
```

### Get Config

[](#get-config)

```
$config = $alerts->getAlertConfig(appId: 'app_abc123');
```

### Notifying Your Users

[](#notifying-your-users)

AgentAdmit detects anomalies, fires alerts, and (with kill switch) auto-revokes connections. **How you notify your own users is up to you.** AgentAdmit provides the data - you deliver it through your own system (in-app notifications, email, push, etc.).

- **Poll alerts** - Use the SDK methods above from your backend to check for new events, then notify users through your existing system.
- **Webhook delivery** - Configure a webhook URL in your AgentAdmit dashboard. When an alert fires, AgentAdmit POSTs the payload to your server, signed with your `whsec_…` secret. Always verify the signature against the raw request body before trusting the payload:

    ```
    use AgentAdmit\Webhook;
    use AgentAdmit\AgentAdmitException;

    Route::post('/agentadmit/alerts', function (Request $request) {
        try {
            Webhook::verifySignature(
                $request->getContent(),
                $request->header('X-AgentAdmit-Signature', ''),
                config('agentadmit.webhook_secret'), // whsec_… from AGENTADMIT_WEBHOOK_SECRET
            );
        } catch (AgentAdmitException $e) {
            return response()->json(['error' => 'invalid_signature'], 400);
        }
        $event = $request->json()->all();
        // ...
    });
    ```

    The header format is `t=,v1=` - an HMAC-SHA256 of `{t}.{rawBody}` keyed with your signing secret. Verification uses `hash_equals()` (constant time) and rejects timestamps more than 5 minutes off (replay protection).
- **React SDK** - Embed the `` component so users can view their own alert history and tighten thresholds.

### Issuing &amp; Exchanging Tokens

[](#issuing--exchanging-tokens)

```
use AgentAdmit\TokensClient;

$tokens = app(TokensClient::class);

// Duration is tri-state:
//   omit the argument                     → AgentAdmit default (30 days)
//   null                                  → until the user revokes
//   int seconds (60–31536000)             → explicit duration
$issued = $tokens->issueToken('user_42', ['read:orders'], role: 'user', durationSeconds: null);
$connectionToken = $issued['token']; // ag_ct_…

// Agent side  -  no API key needed; the connection token is the credential.
$granted = $tokens->exchange($connectionToken, agentLabel: 'MyAssistant');

// Revoke when the user disconnects the agent.
$tokens->revoke($granted['connection_id'], reason: 'user_requested');
```

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance97

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~5 days

Total

5

Last Release

20d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/52b70f74a0c209d22702a8ea16ccb03d89b68fbc051c647be2571e1f99465fe3?d=identicon)[agentadmit](/maintainers/agentadmit)

---

Top Contributors

[![PhoenixCo-Founder](https://avatars.githubusercontent.com/u/263823802?v=4)](https://github.com/PhoenixCo-Founder "PhoenixCo-Founder (3 commits)")

---

Tags

agentadmitai-agentauthorizationlaravelphpsdkmiddlewarelaravelauthauthorizationai-agentagentadmit

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/agentadmit-agentadmit-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/agentadmit-agentadmit-sdk/health.svg)](https://phpackages.com/packages/agentadmit-agentadmit-sdk)
```

###  Alternatives

[laravel/socialite

Laravel wrapper around OAuth 1 &amp; OAuth 2 libraries.

5.7k108.5M925](/packages/laravel-socialite)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[spatie/laravel-export

Create a static site bundle from a Laravel app

674146.0k6](/packages/spatie-laravel-export)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.6k](/packages/simplestats-io-laravel-client)[hasinhayder/tyro

Tyro - The ultimate Authentication, Authorization, and Role &amp; Privilege Management solution for Laravel 12 &amp; 13

6765.1k6](/packages/hasinhayder-tyro)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
