laravel/agent-detector
Laravel Agent Detector is a lightweight PHP 8.2+ utility for detecting whether your code runs inside an AI agent or automated development environment, with known-agent checks and a simple standalone detectAgent() helper.
Architecture fit. laravel/agent-detector is a zero-configuration, single-purpose PHP utility: a static AgentDetector::detect() call (plus a namespaced helper function detectAgent()) returning an AgentResult with isAgent, name, knownAgent(), and label(). It has no service provider, no config file, no database, no HTTP client, and no queue integration. That makes it architecturally inert — it fits any Laravel 10/11/12 application, CLI tool, or bare PHP script without touching the framework's bootstrapping. For a TPM, the relevant framing is that this is not an infrastructure dependency; it is a conditional-behavior primitive you call at specific decision points (artisan commands, CI scripts, test bootstrapping, seeders, deployment hooks).
Integration feasibility. Very high. A single composer require, PHP 8.2+, MIT license, and no transitive dependencies beyond the Composer autoloader. The README is sufficient to integrate in under an hour. The realistic use cases are guardrails and provenance: disabling destructive or interactive commands when running under an agent, suppressing prompts/colored output, tagging commits or telemetry as agent-originated, skipping rate-limited external calls, or annotating logs and audit trails. Feasibility is limited only by scope ambition, not by technical friction.
Technical risk. Low blast radius, but meaningful semantic risk. Detection is entirely heuristic: environment-variable presence/values plus one filesystem check (/opt/.devin). Consequences:
AI_AGENT prefix). Every new agent in the market is a potential silent false negative until upstream ships a release.AI_AGENT, CURSOR_AGENT, CLAUDECODE, etc. are trivially set by anyone. This must never be treated as an authentication or authorization control, only as a hint that alters UX, logging, or non-destructive defaults.laravel/* package (transferred from shipfastlabs, evidenced by the changelog URLs), which materially reduces abandonment risk versus a random community package.AgentDetector → Laravel\AgentDetector, AgentResult constructor signature). v2.0.1–v2.0.4 followed quickly. Minor releases change the detection matrix, which changes runtime behavior without an API change.Key questions.
isAgent, and what is the safe default when detection is wrong in either direction?knownAgent()) or only the boolean? The former couples us to the vendor list; the latter is nearly future-proof.AI_AGENT + a couple of documented vars deliver 80% of the value with 0% of the dependency? If yes, is the package earning its place purely as a maintained, community-curated detector list?Stack fit. Laravel-first, PHP 8.2+, Composer-only. It composes naturally with existing tooling: artisan command handle() methods, Composer\Script\Event handlers, Pest/PHPUnit bootstrap, database seeders, deployment scripts, and queue job payloads. There is nothing to register in config/app.php or a bootstrap/providers.php; there is nothing to publish or cache. For non-Laravel PHP services in the estate, it works identically via the standalone function, which keeps the integration pattern uniform across repositories.
Migration path. Greenfield — no migration required. The only historical migration concern is the v1 → v2 namespace move; any internal snippet or gist written against AgentDetector\AgentDetector must be updated to Laravel\AgentDetector\AgentDetector. Treat v2.x as the floor and pin ^2.0 in composer.json; do not float on * given the fast-moving detection matrix. If the package is adopted broadly, the right pattern is an internal adapter (e.g., App\Support\Runtime\AgentContext) that exposes isAgent(): bool and agentName(): ?string and delegates to the package. That adapter is the seam that makes a future swap to a hand-rolled detector a one-file change.
Compatibility. No known conflict surface: no dependencies, no Laravel framework version constraints beyond PHP, no global helpers that could collide (the helper is namespaced). Watch two things: (a) the KnownAgent enum will grow, so any exhaustive match on it in our code will be a maintenance hotspot — always include a default arm and never persist enum cases by name into a database column; (b) AI_AGENT is both the generic custom-agent escape hatch and, per v2.0.2, a Claude detection prefix, so overlapping heuristics mean precedence is an upstream implementation detail we should not depend on precisely.
Sequencing.
detectAgent() inside one artisan command and one CI script under a real agent session and under a normal terminal. Confirm the CLI-vs-HTTP boundary empirically before designing anything.AgentDetector::AGENT_ENV_VARS is public as of v2.0.1, which helps, but env manipulation should still be centralized in a test helper.migrate:fresh, db:wipe) when isAgent is true. Ship it, measure, and confirm no developer-facing complaints.Maintenance. Ongoing cost is dominated not by code (the package is tiny) but by tracking upstream. The agent-detector detection table is a moving target — new agent vendors appear monthly and env var conventions shift. Practically: subscribe to releases, review changelogs on each bump (they are short and readable), and budget a recurring ~30-minute monthly review. Two upgrade risks to watch: a v2 → v3 breaking change (v2.0.0 precedent shows the maintainers will rename namespaces and change constructor signatures), and behavioral drift in minor releases as heuristics are broadened (v2.0.2's AI_AGENT prefix matching for Claude is exactly that kind of change). Both are cheap to absorb if the internal adapter and enum-default-arm disciplines are in place.
Support. Support burden is low but non-obvious, because the package's behavior is invisible until it changes something. The failure that generates tickets is "my command behaved differently in CI / in Cursor than in my terminal" — which requires the on-call engineer to know the package exists. Mitigation: log the detected agent at debug level in the adapter, document the semantics in the runbook, and make the adapter's fallback behavior explicit rather than implicit. Also document that detection is a hint, not a security boundary — otherwise someone will eventually propose using it to gate permissions.
Scaling. Negligible. Cost is a handful of getenv()/$_SERVER reads and one file_exists() per call. It should still be called once per process and cached in a container singleton or static, rather than re-evaluated per request or per iteration in a loop. No network calls, no cache backend, no serialization concerns. It scales linearly and irrelevantly alongside the application.
Failure modes.
CLAUDECODE=1 in a shell profile, or a CI runner inherits a variable from an agent-spawned job. Results in unnecessary restrictions or mislabeled provenance. Low severity, confusing to debug.AI_AGENT=github-copilot is one export away. Not a threat model unless someone incorrectly treats it as one./opt/.devin probe assumes a container layout; in a read-only or re-mounted filesystem it simply returns false. Non-fatal.KnownAgent cases or exhaustively matching on them will break on the next minor release.Ramp-up. Hours. A mid-level Laravel engineer can read the README, add the package, and ship the first guardrail in a single day. The conceptual ramp-up is the real cost: the team must internalize that this detects the runtime process environment, that it is CLI-centric, and that it is advisory. A single short ADR plus the adapter's docblock covers it. No training, no platform team involvement, no vendor contract, no cost.
TPM verdict. Adopt opportunistically for a narrow, clearly-scoped guardrail or provenance use case; wrap it behind an internal adapter; pin to ^2.0; and do not let it become an authorization primitive. The opportunity score (64.7) reflects a genuinely useful first-party utility in a fast-forming market niche, offset by thin adoption (92 stars, 0 dependents) and a reliance on undocumented vendor environment variables. The correct posture is low-commitment adoption with a 90-day keep/kill review — the integration cost is so low that the decision is reversible, which is the strongest argument for trying it.
How can I help you explore Laravel packages today?