Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Agent Laravel Package

jbsommeling/agent

A Laravel package for building and running AI agents in PHP. It offers a simple API for prompts, tools, and agent workflows, making it easy to add assistant-style automation and conversational features to existing Laravel apps without complex setup.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install: composer require jbsommeling/agent. v1.0.3 restores PHP 8.0 support and is CI-tested against Laravel 9 through 13, so the same install works whether you're maintaining an older Laravel 9 app or starting fresh on the newest skeleton. No --ignore-platform-req workaround needed anymore.
  • Publish and configure: php artisan vendor:publish --tag="agent-config", then set your provider credentials in .env (the package reads them through config/agent.php). Keep per-environment model names in the config, not in code.
  • Read in this order: the README quickstart → config/agent.php (it documents every knob the package actually honours) → the package's tests/ directory. For a v1.x package with a small doc surface, the test suite is the most reliable specification of expected usage.
  • First use case: a single synchronous prompt behind an artisan command or a throwaway route — no tools, no memory. Confirm you get a response and see the request/response in your logs before layering on tool calling or conversation state. Once that works, move the call into a queued job (see below); almost everything that goes wrong in production with agent packages is a timeout or a rate limit, and the queue solves both.

Implementation Patterns

  • One agent class per task. Wrap the package call in a small application-level class (Support\Agents\SummariseTicket, etc.) rather than calling the package directly from controllers. Keeps prompts versionable, makes the call mockable in tests, and gives you one place to add logging and retries.
  • Always queue. Agent calls are slow and flaky. Dispatch a job, broadcast or poll for the result. Reserve synchronous calls for local development and CLI commands. Combine with retryUntil/backoff for provider 429s and 5xx.
  • Prompts live in files, not string literals. Blade views or resources/prompts/*.md loaded by the agent class. Diffing prompts in git is the single biggest quality-of-life win once you have more than two agents.
  • Tool calling. Register the smallest possible set of tools, validate arguments defensively inside the tool, and return an error array rather than throwing — a thrown exception usually aborts the run, while a structured error lets the model correct itself on the next turn. Always cap the tool-call loop (max_steps or equivalent); an unbounded loop is an unbounded bill.
  • Multi-turn conversations. Persist the message history yourself (messages table keyed by conversation ULID) and pass it in on each call. Treat any in-process memory the package offers as a per-request convenience, not storage — it will not survive the next HTTP request or a queue worker restart.
  • Streaming. For chat UIs, stream via SSE (response()->stream() or a Livewire wire:stream). For fire-and-forget generation, don't stream at all — streaming a queued job gives you nothing but complexity.
  • Testing. Fake the HTTP layer (Http::fake()) or the package's own fake if it ships one, then assert on the outgoing payload (model, messages, tool schema) rather than on the model's prose. Snapshot-test your rendered prompts; they're the thing most likely to regress silently.
  • Observability. Log token usage and latency per call with a correlation ID, and keep a agent_runs table of prompt + response + usage for at least a few weeks. When someone reports a bad answer, you want the exact input that produced it.
  • RAG, if you need it. Embed on write (a queued job on model save), store vectors in a dedicated table or an external store, and retrieve top-k before constructing the prompt. Don't retrieve inside the tool loop unless the model genuinely needs to decide what to look up.

Gotchas and Tips

  • PHP 8.0 support constrains the codebase. Because v1.0.3 explicitly targets PHP 8.0, the package cannot use readonly properties, enums, pure intersection types, never, or first-class callable syntax. You can use all of those in your application on 8.1+, but any PR or local patch to the package will fail its CI. Don't vendor-patch it with 8.1-only syntax and expect upstream to take it.
  • Laravel 9–13 in the CI matrix means a deliberately narrow framework surface. Avoid assuming helpers added in later releases (Str:: additions in 10/11, Sleep::, newer Http client options) exist inside the package's own code. If you hit a BadMethodCallException after a framework upgrade, that's the first place to look.
  • Config caching bites. Agents resolved in a service-provider closure read config at boot. After changing model/key/timeout, run php artisan config:clear locally and re-deploy on prod — otherwise you'll debug a "wrong model" issue that doesn't exist in the code.
  • Timeouts are the #1 production failure. Raise both the HTTP timeout in config/agent.php and PHP's max_execution_time for any sync path; large completions routinely exceed 30s. Catch Illuminate\Http\Client\ConnectionException and surface a retryable error to the user.
  • Streaming breaks behind middleware. Compression, Content-Length, and output buffering all corrupt SSE. Disable them for the streaming route and call ob_end_flush()/flush() after each chunk. Behind nginx, also set proxy_buffering off.
  • Context windows don't trim themselves. If you keep appending history, you'll eventually get a provider 400, not a graceful truncation. Implement a rolling window or summarisation of older turns.
  • Debugging payloads: add a global Http::after() hook (or Http::preventStrayRequests() in tests) to dump the exact request body. Nearly every failure is a malformed JSON schema for a tool, a missing api_key, or a model name that doesn't exist on that provider.
  • Cost control: set explicit max_tokens, cap tool-call iterations, and alert on daily token spend. A retry loop with backoff against a paid endpoint compounds fast.
  • Extension points to prefer: the publishable config, container bindings for a custom provider/driver, and any before/after-call events. Prefer these over subclassing internals — at v1.0.x the internals are still moving.
  • Upgrading from v1.0.2: this is a compatibility release, not a behavioural one, but if you pinned PHP 8.0 you may have been stuck on 1.0.1. Run composer update jbsommeling/agent and, if it refuses, composer why-not jbsommeling/agent 1.0.3 to find the constraining dependency.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource