PHPackages                             lyre/ai-agents - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. lyre/ai-agents

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

lyre/ai-agents
==============

Forward-only Agents/Bots orchestration on top of Laravel + OpenAI Responses API.

1.3.1(1mo ago)0378↓31.7%MITPHPPHP ^8.1

Since Feb 18Pushed 1mo agoCompare

[ Source](https://github.com/kigathi-chege/lyre-ai-agents-laravel)[ Packagist](https://packagist.org/packages/lyre/ai-agents)[ RSS](/packages/lyre-ai-agents/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (20)Versions (12)Used By (0)

lyre/ai-agents (Laravel)
========================

[](#lyreai-agents-laravel)

Forward-only Agents/Bots package using OpenAI Responses API with first-class Laravel orchestration.

Install
-------

[](#install)

```
composer require lyre/ai-agents
php artisan vendor:publish --tag=ai-agents-config
php artisan vendor:publish --tag=ai-agents-migrations
php artisan migrate
```

Quick start
-----------

[](#quick-start)

```
use Lyre\AiAgents\Facades\Agents;

Agents::registerTool([
    'name' => 'lookup_customer',
    'type' => 'function',
    'description' => 'Lookup customer by phone',
    'parameters_schema' => [
        'type' => 'object',
        'properties' => [
            'phone' => ['type' => 'string'],
        ],
        'required' => ['phone'],
    ],
    'handler' => fn (array $args) => ['customer' => ['phone' => $args['phone'], 'tier' => 'gold']],
]);

$agent = Agents::registerAgent([
    'name' => 'support-bot',
    'model' => 'gpt-4.1-mini',
    'instructions' => 'You are a support specialist.',
    'temperature' => 0.2,
    'max_output_tokens' => 800,
]);

$result = Agents::run($agent->id, 'Find customer with phone +254700111222', [
    'user_id' => auth()->id(),
    'ip' => request()->ip(),
]);
```

Streaming
---------

[](#streaming)

```
$stream = Agents::stream('support-bot', 'Explain invoice #INV-22');

foreach ($stream as $chunk) {
    echo $chunk;
}
```

Prompt templates
----------------

[](#prompt-templates)

Templates live in `ai_agents_prompt_templates` and are linked to an agent via `agents.prompt_template_id`. The resolver renders template content with `{{variable}}` substitution and supports inheritance.

### Inheritance

[](#inheritance)

Set `extends_template_id` on a template to compose it on top of a parent. The resolver walks root → leaf and concatenates content with the configured separator (default `\n\n`). Inheritance is depth-capped (`prompts.max_inheritance_depth`, default 3) and cycle-safe — on detection the resolver logs a warning and falls back to the leaf alone.

### Variables

[](#variables)

Any `{{token}}` in a template is substituted at resolve time. Variables are merged from these sources, lowest-to-highest priority:

1. Each template's `variables` JSON column (parent first, child overrides).
2. System defaults: `assistant_name`, `agent_id`, `model`.
3. `agent.metadata.template_variables`.
4. Caller-supplied map passed to `resolveInstructionsForAgent($agent, $variables)`.

### Section contributors

[](#section-contributors)

Host apps can append extra sections to the resolved prompt without forking the resolver:

```
use Lyre\AiAgents\Contracts\PromptSectionContributor;
use Lyre\AiAgents\Models\Agent;

class ImageCatalogSection implements PromptSectionContributor
{
    public function name(): string { return 'image_catalog'; }
    public function shouldApply(Agent $agent): bool { /* … */ }
    public function render(Agent $agent): ?string { /* … */ }
}

// In a service provider:
$this->app->bind(ImageCatalogSection::class);
$this->app->tag([ImageCatalogSection::class], PromptSectionContributor::TAG);
```

Structured output (`text.format`)
---------------------------------

[](#structured-output-textformat)

Set `agent.metadata.response_format` to a Responses API JSON-schema config and the runner forwards it as `text.format` on every call:

```
$agent->metadata = array_merge($agent->metadata ?? [], [
    'response_format' => [
        'type' => 'json_schema',
        'name' => 'kenchic_whatsapp_response',
        'strict' => true,
        'schema' => [/* … */],
    ],
]);
$agent->save();
```

Built-in tools
--------------

[](#built-in-tools)

### Lead capture (`submit_lead`)

[](#lead-capture-submit_lead)

```
app(\Lyre\AiAgents\Services\AgentKnowledgeService::class)
    ->ensureLeadToolForAllAgents('https://your-app.test/api/leads');
```

The tool name is config-driven via `tools.lead.tool_name` (default `submit_lead`). Any agent that previously had the legacy `submit_lead_to_axis` tool will be migrated idempotently on next call.

### Human handover (`request_human_handover`)

[](#human-handover-request_human_handover)

```
app(\Lyre\AiAgents\Services\AgentKnowledgeService::class)
    ->ensureHandoverToolForAllAgents('https://your-app.test/api/handover');
```

The handler endpoint receives the function-call arguments plus Lyre's run/conversation context and is responsible for whatever handover semantics the host app needs (flipping a flag, paging on-call, etc.).

Events dispatched
-----------------

[](#events-dispatched)

- `Lyre\AiAgents\Events\AgentRunStarted`
- `Lyre\AiAgents\Events\AgentToolCalled`
- `Lyre\AiAgents\Events\AgentRunCompleted`
- `Lyre\AiAgents\Events\AgentRunFailed`
- `Lyre\AiAgents\Events\ConversationUpdated`
- `Lyre\AiAgents\Events\UsageRecorded`

Local development
-----------------

[](#local-development)

```
"repositories": [
    {
        "type": "path",
        "url": "../packages/lyre-ai-agents-laravel",
        "options": {
            "symlink": true
        }
    }
]
```

Frontend safety
---------------

[](#frontend-safety)

- Frontend should call your backend proxy route, not OpenAI directly.
- If direct OpenAI is needed, use short-lived scoped credentials in trusted environments only.

Output length limits
--------------------

[](#output-length-limits)

Two optional env vars bound how long an agent's reply can be. Both default to unset, which keeps the prior behaviour (no character cap; the agent's own `max_output_tokens`, if any, is used).

```
# Global fallback for max_output_tokens when an agent has none set (native OpenAI limit).
AI_AGENTS_MAX_OUTPUT_TOKENS=800

# Hard cap on the final assistant TEXT, enforced by the package via truncation
# (OpenAI has no character limit). Skipped for structured json_schema responses.
AI_AGENTS_MAX_OUTPUT_CHARACTERS=1000
```

Precedence for tokens: the agent's own `max_output_tokens` column wins; otherwise `AI_AGENTS_MAX_OUTPUT_TOKENS`; otherwise unset. `max_output_characters` truncates the final `output_text` (and the stored assistant message) to that many characters. For live SSE streaming, deltas are forwarded verbatim, so use `max_output_tokens` to bound what streams in real time — the character cap backstops the persisted/returned text.

Table naming
------------

[](#table-naming)

By default, the package uses these tables: `agents`, `agent_tools`, `conversations`, `conversation_messages`, `agent_runs`, `usage_logs`, `events`.

You can set a global prefix for multi-project flexibility:

```
AI_AGENTS_TABLE_PREFIX=axis_
```

Or override individual table names:

```
AI_AGENTS_TABLE_CONVERSATIONS=axis_conversations
AI_AGENTS_TABLE_CONVERSATION_MESSAGES=axis_conversation_messages
```

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance93

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

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 ~15 days

Total

11

Last Release

33d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/38941486?v=4)[Kigathi](/maintainers/Kigathi)[@kigathi](https://github.com/kigathi)

---

Top Contributors

[![kigathi-chege](https://avatars.githubusercontent.com/u/30687709?v=4)](https://github.com/kigathi-chege "kigathi-chege (13 commits)")

### Embed Badge

![Health badge](/badges/lyre-ai-agents/health.svg)

```
[![Health](https://phpackages.com/badges/lyre-ai-agents/health.svg)](https://phpackages.com/packages/lyre-ai-agents)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

265.2k](/packages/aedart-athenaeum)[mike-bronner/laravel-model-caching

Automatic caching for Eloquent models.

2.4k161.4k2](/packages/mike-bronner-laravel-model-caching)[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k8.9M110](/packages/mongodb-laravel-mongodb)[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k16.3M154](/packages/laravel-pulse)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45844.8k1](/packages/pressbooks-pressbooks)

PHPackages © 2026

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