定制 whilesmart/eloquent-agents 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

whilesmart/eloquent-agents

Composer 安装命令:

composer require whilesmart/eloquent-agents

包简介

AI tool-calling foundation for Laravel: ready-made tools, an agent harness, and an extension API on top of Prism

README 文档

README

AI tool-calling foundation for Laravel. Built on Prism, it adds the two things Prism leaves to you: a set of ready-made tools the model can call, and a small extension API so your app registers its own tools, agents ("harnesses"), and prompts.

Features

  • Batteries included. Ships safe, generic tools: scoped Eloquent read/write, HTTP fetch, web search, storage read, a clock, and a calculator.
  • Harnesses. A harness is a named agent: a system prompt + a tool set + a model + a step budget. Define one in a config array or a class.
  • Bring your own tools. Implement one method, register the class, and the model can call it.
  • Default-deny security. Every tool runs against a ToolContext (the acting user). Data tools enforce an allowlist of models and columns and scope every row to that user.
  • MCP ready. Adopt any Prism tool, including MCP server tools, through the registry.

Installation

composer require whilesmart/eloquent-agents
php artisan vendor:publish --tag=agents-config

Set credentials the Prism way (provider-native env vars), e.g. GEMINI_API_KEY, then choose a default model:

AGENTS_PROVIDER=gemini
AGENTS_MODEL=gemini-2.0-flash

Quick start

use Whilesmart\Agents\Facades\Agents;
use Whilesmart\Agents\ValueObjects\ToolContext;

// config/agents.php
'harnesses' => [
    'assistant' => [
        'prompt' => 'example-assistant',          // a prompt name or literal text
        'tools'  => ['clock', 'calculator'],
        'max_steps' => 5,
    ],
],

// anywhere in the app
$result = Agents::harness('assistant')->run(
    'What is 1200.50 plus 300, and what was last month?',
    ToolContext::forUser($user),
);

$result->text;       // the model's answer
$result->toolCalls;  // what it called
$result->usage;      // token usage

Built-in tools

Name Permission What it does
clock read Current date/time and relative anchors (start of last month, etc.).
calculator read Deterministic arithmetic over + - * / and parentheses.
eloquent.query read List/aggregate the user's own records across an allowlist of models.
eloquent.write write Create/update allowlisted models+columns, owner-scoped. Off by default.
http.fetch external GET an allowlisted host, size-capped.
web.search external Search via a pluggable driver (null driver by default).
storage.read read List/read files on a disk, jailed to a path prefix.

The Eloquent tools read nothing until you declare an allowlist:

// config/agents.php
'eloquent' => [
    'allow_writes' => true,
    'models' => [
        'transactions' => [
            'model' => App\Models\Transaction::class,
            'owner_key' => 'user_id',                    // rows scoped to the acting user
            'readable' => ['amount', 'type', 'description', 'created_at'],
            'writable' => ['amount', 'type', 'description'],
        ],
    ],
],

Writing your own tool

use Whilesmart\Agents\Tools\AbstractTool;
use Whilesmart\Agents\ValueObjects\ParameterSpec;
use Whilesmart\Agents\ValueObjects\ToolContext;

class CreateReminderTool extends AbstractTool
{
    public function name(): string { return 'create_reminder'; }

    public function description(): string { return 'Create a reminder for the user.'; }

    public function parameters(): array
    {
        return [
            ParameterSpec::string('text', 'What to be reminded about'),
            ParameterSpec::string('due', 'Due date (YYYY-MM-DD)'),
        ];
    }

    public function handle(array $arguments, ToolContext $context): string|array
    {
        $reminder = $context->user->reminders()->create($arguments);

        return ['id' => $reminder->id];
    }
}

Register it by config ('tools' => [CreateReminderTool::class]), at runtime (Agents::registerTool(new CreateReminderTool)), or enable auto-discovery of App\Ai\Tools.

Harness as a class

When config arrays are not enough, extend AbstractHarness:

use Whilesmart\Agents\Harness\AbstractHarness;
use Whilesmart\Agents\Enums\ToolPermission;

class FinanceHarness extends AbstractHarness
{
    public function name(): string { return 'finance'; }

    public function systemPrompt(): string { return 'You are a careful finance assistant.'; }

    public function toolNames(): array { return ['clock', 'calculator', 'eloquent.query']; }

    public function allowedPermissions(): array { return [ToolPermission::READ]; }   // refuse write tools
}

Agents::registerHarness('finance', FinanceHarness::class).

Overriding prompts

run() resolves a harness prompt by name in this order: config('agents.prompts.{name}'), a published file at resources/vendor/agents/prompts/{name}.md, then the package default. A value that matches no prompt is used as literal text.

MCP tools

use Prism\Prism\Tools\LaravelMcpTool;
use Whilesmart\Agents\Engines\Prism\Tools\McpTool;

Agents::registerTool(McpTool::wrap(new LaravelMcpTool($mcpServerTool)));

Engine abstraction

Prism is a swappable layer, not a hard dependency of your tools. Everything you write (tools, harnesses, parameters, results) speaks the package's own types. All Prism SDK code lives behind the AgentEngine contract under src/Engines/Prism/:

  • PrismEngine builds and runs the Prism request and maps the response to an AgentResult.
  • PrismToolAdapter translates a package Tool into a Prism tool.

To move to a different backend, implement AgentEngine and rebind it:

// a service provider
$this->app->bind(\Whilesmart\Agents\Contracts\AgentEngine::class, MyEngine::class);

Nothing else changes: tools, harnesses, registries, and the facade are untouched.

Console

php artisan agents:tools        # list registered tools
php artisan agents:harnesses    # list registered harnesses
php artisan agents:run finance "how much did I spend last month?" --user=1

Security model

Default-deny. Tools authorize against the ToolContext before running. eloquent.query/eloquent.write expose nothing outside the configured model+column allowlist and scope every row to the acting user; eloquent.write additionally requires allow_writes and applies only whitelisted columns (mass-assignment guard), forcing the owner key on create. http.fetch honours a host allowlist; storage.read is jailed to a path prefix and rejects traversal. The agent loop is bounded by agents.max_steps.

Testing

make check     # pint + phpunit via Docker
# or
composer test

License

MIT

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-24

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固