Laravel 工作管理器
适用于Laravel的工作单控制平面——配备一流AI代理集成(MCP)。
对于 AI代理、后台服务以及管理/仪表板流程 这些需要在状态、幂等性、可审计性和安全并发执行方面提供强有力的保障。
这个包为你提供了一种原生框架的方式来创建、租赁、验证、批准和应用(相关内容) 打字的工作单它内置了一个 MCP(模型上下文协议)服务器 对于AI代理,提供一个轻量级的HTTP API,您可以将其挂载到任何命名空间下,支持计划任务以自动生成工作,并提供清晰的扩展点以支持自定义类型、验证和执行。
内置的MCP服务器: 通过MCP协议连接AI代理(Claude/Claude Code、Cursor等),以自动发现工具、检出工作、提交结果并轮询决策。MCP服务器提供与HTTP API相同的服务和验证。HTTP API将继续为非MCP客户端和自定义集成提供支持。
______________________________________________________________________
为何存在此现象
现代人工智能系统执行着非平凡的后台工作——包括研究、数据丰富化、迁移、数据同步等,这些工作通常由外部代理完成。您需要:
- 一条可审计的单一路径用于 所有突变 (没有侧门)。
- 安全、并发的 租赁 带有TTL(生存时间)+ 心跳机制。
- 打字的 与每种类型的模式、验证器和幂等性协同工作 apply() 的中文翻译是“应用” 逻辑。
- 幂等性 以及明确的重试语义。
- 通过(某种方式/平台)实现轻松的代理用户体验 结账 → 心跳检测 → 提交 → 审批/申请。
- 强大的 事件/来源/差异 为了实现可观测性和合规性。
Laravel Work Manager 正是提供了这样的功能。
______________________________________________________________________
你所得到的
- 打印出的工作订单按类型划分的架构 + 规划 + 接受策略 + 应用钩子。 (
Contracts\OrderType,Support\AbstractOrderType) - 状态机强制执行的订单/项目生命周期 + 事件。 (
Services\StateMachine,Support\Enums) - 租赁与并发性单次结算、生存时间(TTL)、心跳检测、回收、最大尝试次数。 (
Services\LeaseService) - 幂等性基于头部的去重 + 存储的响应。 (
Services\IdempotencyService) - HTTP API可挂载的控制器,具备提议/检出/心跳/提交/批准/拒绝/日志功能。 (
Http\Controllers\WorkOrderApiController) - 计划任务命令发电机与维护。 (
work-manager:generate,work-manager:maintain) - “仅凭工作令执行”选择加入的中间件以阻止直接突变(需要
X-Work-Order-ID头球 (Http\Middleware\EnforceWorkOrderOnly) - 可审计性:
WorkEvent,WorkProvenance,且结构化Diff. - 文档: MCP服务器集成, HTTP API, 创建订单类型, 部分提交, 文档主页
______________________________________________________________________
安装
composer require gregpriday/laravel-work-manager
php artisan vendor:publish --tag=work-manager-config
php artisan vendor:publish --tag=work-manager-migrations
php artisan migrate要求: PHP 8.2+,Laravel 11 或 12,MySQL 8+ 或 PostgreSQL 13+。 可选的 Redis 租约后端 (默认:数据库;为提高并发性,建议使用Redis)。参见 安装指南 以了解详细要求。
______________________________________________________________________
快速入门
1. 安装与迁移:
composer require gregpriday/laravel-work-manager
php artisan vendor:publish --tag=work-manager-migrations
php artisan migrate2. 注册路由:
// routes/api.php
use GregPriday\WorkManager\Facades\WorkManager;
WorkManager::routes('agent/work', ['api', 'auth:sanctum']);3. 安排维护计划:
// app/Console/Kernel.php
$schedule->command('work-manager:generate')->everyFifteenMinutes();
$schedule->command('work-manager:maintain')->everyMinute();4. 定义订单类型 (见 创建订单类型):
// app/WorkTypes/UserDataSyncType.php
use GregPriday\WorkManager\Support\AbstractOrderType;
class UserDataSyncType extends AbstractOrderType
{
public function type(): string { return 'user.data.sync'; }
public function schema(): array { /* JSON schema */ }
public function apply(WorkOrder $order): Diff { /* Idempotent execution */ }
}5. 注册您的类型:
// app/Providers/AppServiceProvider.php
WorkManager::registry()->register(new UserDataSyncType());见 快速入门指南 以获取完整的操作指南。
______________________________________________________________________
详细示例(5步)
1) 注册路由(选择您的命名空间)
// routes/api.php
use GregPriday\WorkManager\Facades\WorkManager;
// Mount all endpoints under /agent/work with your own middleware/guard
WorkManager::routes('agent/work', ['api', 'auth:sanctum']);注: 如果你在(某个地方/某个时间)注册 routes/api.phpLaravel 会自动加上前缀 /api,所以这就变成了 /api/agent/work/*。
或者手动将它们连接起来,分别选择端点。
2) 定义订单类型
// app/WorkTypes/UserDataSyncType.php
use GregPriday\WorkManager\Support\AbstractOrderType;
use GregPriday\WorkManager\Models\WorkOrder;
use GregPriday\WorkManager\Models\WorkItem;
use GregPriday\WorkManager\Support\Diff;
final class UserDataSyncType extends AbstractOrderType
{
public function type(): string
{
return 'user.data.sync';
}
public function schema(): array
{
return [
'type' => 'object',
'required' => ['source', 'user_ids'],
'properties' => [
'source' => ['type' => 'string', 'enum' => ['crm', 'analytics']],
'user_ids' => ['type' => 'array', 'items' => ['type' => 'integer']],
],
];
}
// Laravel validation for agent submissions
protected function submissionValidationRules(WorkItem $item): array
{
return [
'success' => 'required|boolean',
'synced_users' => 'required|array',
'synced_users.*.user_id' => 'required|integer',
'synced_users.*.verified' => 'required|boolean|accepted',
];
}
// Custom verification logic
protected function afterValidateSubmission(WorkItem $item, array $result): void
{
// Verify all users in batch were processed
$expectedIds = $item->input['user_ids'];
$syncedIds = array_column($result['synced_users'], 'user_id');
if (count(array_diff($expectedIds, $syncedIds)) > 0) {
throw \Illuminate\Validation\ValidationException::withMessages([
'synced_users' => ['Not all users in batch were synced'],
]);
}
}
// Idempotent execution with database operations
public function apply(WorkOrder $order): Diff
{
$updatedCount = 0;
DB::transaction(function () use ($order, &$updatedCount) {
foreach ($order->items as $item) {
foreach ($item->result['synced_users'] as $syncedUser) {
$user = User::find($syncedUser['user_id']);
if ($user) {
$user->update($syncedUser['data']);
$updatedCount++;
}
}
}
});
return $this->makeDiff(
['updated_count' => 0],
['updated_count' => $updatedCount],
"Synced data for {$updatedCount} users"
);
}
// Post-execution cleanup
protected function afterApply(WorkOrder $order, Diff $diff): void
{
Cache::tags(['users'])->flush();
}
}这使用了 AbstractOrderType 其提供:
- 使用 Laravel 验证的默认接受策略
- 生命周期钩子:
beforeApply(),afterApply() - 验证钩子:
submissionValidationRules(),afterValidateSubmission(),canApprove() - 辅助方法:
makeDiff(),emptyDiff()
3) 注册您的类型
// app/Providers/AppServiceProvider.php
use GregPriday\WorkManager\Facades\WorkManager;
use App\WorkTypes\UserDataSyncType;
public function boot()
{
WorkManager::registry()->register(new UserDataSyncType());
}4) 安排任务
// app/Console/Kernel.php
$schedule->command('work-manager:generate')->everyFifteenMinutes();
$schedule->command('work-manager:maintain')->everyMinute();5) 调用API(作为代理)
# Propose
curl -X POST /api/agent/work/propose \
-H "Authorization: Bearer " \
-H "X-Idempotency-Key: propose-1" \
-d '{"type":"user.data.sync","payload":{"source":"crm","user_ids":[1,2,3]}}'
# Checkout → heartbeat → submit → approve
curl -X POST /api/agent/work/orders/{order}/checkout -H "X-Agent-ID: agent-1"
curl -X POST /api/agent/work/items/{item}/heartbeat -H "X-Agent-ID: agent-1"
curl -X POST /api/agent/work/items/{item}/submit \
-H "X-Idempotency-Key: submit-1" \
-d '{"result":{"success":true,"synced_users":[...],"verified":true}}'
curl -X POST /api/agent/work/orders/{order}/approve -H "X-Idempotency-Key: approve-1"______________________________________________________________________
核心概念
工作订单与工作项
WorkOrder高级合约(类型、有效载荷、状态、来源)。WorkItem代理租赁的单元、心跳信号,并提交。
优雅的模型位于 src/Models 使用枚举类型进行状态转换。
类型与生命周期钩子
订单类型 定义了工作类型的完整生命周期:
// What is this work?
public function type(): string
// What data is required?
public function schema(): array
// How to break into items?
public function plan(WorkOrder $order): array
// Verification hooks (using AbstractOrderType):
protected function submissionValidationRules(WorkItem $item): array
protected function afterValidateSubmission(WorkItem $item, array $result): void
protected function canApprove(WorkOrder $order): bool
// Execution hooks:
protected function beforeApply(WorkOrder $order): void
public function apply(WorkOrder $order): Diff // Idempotent!
protected function afterApply(WorkOrder $order, Diff $diff): void抽象订单类型 为以下内容提供默认实现和钩子(或回调机制):
- Laravel 验证集成
- 自定义验证逻辑
- 审批准备检查
- 执行前/后的钩子(或:执行前/后回调)
摘要接受政策 对于那些希望将验证与类型类分离的团队来说。
看 生命周期与流程 关于完整的钩子(hook)文档。
状态机
对于订单和项目,实行严格的过渡规定:
queued → checked_out → in_progress → submitted → approved → applied → completed也支持失败/被拒绝的路径。每次转换都会记录事件。
租赁
每件商品单独结账,使用TTL(生存时间)+心跳机制。过期的租约将由维护系统回收;商品将在最大尝试次数后重新排队或失败。
幂等性
提供 X-Idempotency-Key 用于提议/提交/批准/拒绝。该包存储密钥哈希和缓存的响应,以确保代理重试的安全性。
验证(两阶段)
- 代理提交Laravel验证规则 + 自定义业务逻辑
- 审批准备就绪执行前的跨项目验证(由……实现)
canApprove()(在您的接纳政策中)
“仅凭工作令”执行
附加 EnforceWorkOrderOnly 在您的应用程序中,为任何可变端点添加中间件,以确保所有写入操作都通过有效的工单进行。这是 选择加入(或主动选择) 并且要求 X-Work-Order-ID 标题(或 _work_order_id 请求参数)。您可以选择性地指定允许的状态,例如。, approved|applied。
部分提交
可选的部分提交 让代理流式处理大量结果,并在稍后完成最终确定。对于复杂的工作项(例如,研究任务、多步骤流程),代理可以分批提交结果,而不是一次性全部提交:
POST /items/{item}/submit-part— 提交一个增量部分(独立验证)POST /items/{item}/finalize— 将所有已验证的部件组装成最终结果
在配置中启用: 'partials.enabled' => true (默认启用,且可配置最大分片数和有效载荷大小的限制)。
好处:
- 处理大型/复杂工作时不会出现超时问题
- 随着结果的生成,逐步进行验证
- 跨会话恢复工作
- 跟踪长时间运行任务的进度
每个部分都经过独立验证并存储。一旦所有部分提交完毕,请致电 finalize 将它们组合成最终的工作项目结果。参见 examples/CustomerResearchPartialType.php 以了解实施细节。
______________________________________________________________________
HTTP API 概述
挂载到任意前缀下(例如。, /agent/work),然后:
关于路由前缀的说明如果你在(某个框架或应用中)挂载路由 routes/api.phpLaravel 会自动为它们加上前缀 /api,所以 /agent/work/* 变成;成为 /api/agent/work/*。
幂等性: 发送 X-Idempotency-Key 在强制端点上启用头部(propose, submit, submit-part, finalize, approve, reject) 以获取带有缓存响应的安全重试。
POST /propose— 创建一个工作单(需要type,payload)GET /orders/GET /orders/{id}— 列出/显示订单POST /orders/{order}/checkout— 请选择下一个可用项目POST /items/{item}/heartbeat— 延长租约POST /items/{item}/submit— 提交完整结果(已验证)POST /items/{item}/submit-part— 提交部分结果(用于增量工作)POST /items/{item}/finalize— 通过组装所有部件完成工作项POST /orders/{order}/approve— 审批并应用(记录差异/事件)POST /orders/{order}/reject— 拒绝(可选择重新入队以进行重新处理)POST /items/{item}/release— 明确释放租约GET /items/{item}/logs— 最近的事件/差异
全部实现在 WorkOrderApiController。
认证/守卫配置为 config/work-manager.php (routes.guard,默认 sanctum)。
幂等性头部(或幂等性请求头): X-Idempotency-Key (可配置的)。
______________________________________________________________________
计划自动化
work-manager:generate— 你注册的(程序/服务)运行着吗 分配器策略/规划器端口 实现方案以创建新订单(例如,“扫描过期数据 → 创建同步订单”)work-manager:maintain— 回收过期租约,处理卡住的死信工作,并对陈旧订单发出警报
在你的调度程序中连接它们;参见 Console/* 用于选择。
______________________________________________________________________
MCP服务器(推荐用于AI代理)
该包裹包含一个 内置的MCP(模型上下文协议)服务器 以便AI代理与工单系统进行交互。这是 推荐的集成方法 用于人工智能集成开发环境(IDEs)和智能体。
快速入门
选择一种交通工具 (本地IDE使用stdio,远程/生产环境使用HTTP):
本地模式(适用于Cursor、Claude Desktop等):
php artisan work-manager:mcp --transport=stdioHTTP模式(用于远程代理/生产环境):
php artisan work-manager:mcp --transport=http --host=0.0.0.0 --port=8090MCP服务器一次运行一个传输,并暴露与HTTP API相同的服务。
带身份验证的HTTP模式(推荐用于生产环境):
# .env
WORK_MANAGER_MCP_HTTP_AUTH=true
WORK_MANAGER_MCP_AUTH_GUARD=sanctum # or any Laravel guard
WORK_MANAGER_MCP_STATIC_TOKENS=token1,token2 # optional: static tokens for dev/testing当启用认证时,客户端必须包含 Authorization: Bearer 在所有请求中添加头部信息。
MCP HTTP 端点: GET /mcp/sse (服务器发送事件), POST /mcp/message (消息端点)。在生产环境中启用Bearer认证,并将其置于TLS/反向代理之后;仅在开发环境中使用静态令牌。
注: MCP和REST认证是分开的。MCP HTTP使用上面配置的Bearer令牌;REST API使用在路由中配置的Laravel守护进程(例如,Sanctum)。
可用的MCP工具
服务器提供了13个工具,这些工具与工作管理器的操作一一对应:
work.propose— 创建新的工作订单work.list— 列出并过滤订单work.get— 获取订单详情work.checkout— 租赁工作项目work.heartbeat— 维持租赁关系work.submit— 提交完整结果work.submit_part— 提交部分结果(用于增量工作)work.list_parts— 列出工作项的所有部件work.finalize— 通过组装部件完成工作项work.approve— 审批并执行订单work.reject— 拒绝订单work.release— 释放租约work.logs— 查看事件历史
集成示例
Cursor 集成开发环境(IDE) - 添加到 .cursorrules:
{
"mcp": {
"servers": {
"work-manager": {
"command": "php",
"args": ["artisan", "work-manager:mcp", "--transport=stdio"],
"cwd": "/path/to/your/laravel/app"
}
}
}
}Claude Desktop(可译为“克劳德桌面版”或保持原名“Claude Desktop”,根据上下文选择是否需要意译) - 添加到配置中:
{
"mcpServers": {
"work-manager": {
"command": "php",
"args": ["/path/to/app/artisan", "work-manager:mcp"],
"env": { "APP_ENV": "local" }
}
}
}见 MCP服务器集成指南 以获取完整的文档,包括生产部署、身份验证设置、安全措施以及故障排除等内容。
______________________________________________________________________
配置
发布和编辑 config/work-manager.php. 关键部分:
- 路线基础路径,中间件,守卫
- 租赁TTL(生存时间)、心跳间隔、后端(数据库或Redis)
- 重试最大尝试次数,退避,抖动
- 幂等性头部名称 & 强制端点
- “Partials”可以翻译为“部分”或“片段”,具体取决于上下文。在数学、科学或技术领域,它通常指的是一个整体的一部分或一个不完整的部分。在文学或艺术领域,它可能指的是一个故事、作品或场景的片段或节选启用/禁用部分提交,每项最大部分数,有效载荷大小限制
- 状态机允许的跃迁
- 队列队列连接和名称
- 指标驱动程序(日志、Prometheus、StatsD)和命名空间
- 政策将能力映射到门/权限
- 维护死信队列和警报的阈值
- MCP(多用途指挥车)HTTP认证(启用、守护、静态令牌),CORS设置
______________________________________________________________________
Laravel 集成
Laravel 验证
protected function submissionValidationRules(WorkItem $item): array
{
return [
'user_id' => 'required|exists:users,id',
'email' => 'required|email|unique:users',
'data' => 'required|array',
];
}Laravel 事件
订阅生命周期事件:
use GregPriday\WorkManager\Events\WorkOrderApplied;
Event::listen(WorkOrderApplied::class, function($event) {
Log::info('Order applied', [
'order_id' => $event->order->id,
'diff' => $event->diff->toArray(),
]);
});可用事件:
WorkOrderProposed,WorkOrderPlanned,WorkOrderCheckedOut,WorkOrderApproved,WorkOrderApplied,WorkOrderCompleted,WorkOrderRejectedWorkItemLeased,WorkItemHeartbeat,WorkItemSubmitted,WorkItemFailed,WorkItemLeaseExpired,WorkItemFinalizedWorkItemPartSubmitted,WorkItemPartValidated,WorkItemPartRejected
Laravel 作业/队列
protected function afterApply(WorkOrder $order, Diff $diff): void
{
ProcessData::dispatch($order)->onQueue('work');
SendNotifications::dispatch($diff)->onQueue('notifications');
}数据库操作
public function apply(WorkOrder $order): Diff
{
return DB::transaction(function () use ($order) {
foreach ($order->items as $item) {
// Insert/update records
Model::create($item->result['data']);
}
return $this->makeDiff($before, $after);
});
}______________________________________________________________________
示例
- 数据库插入操作: 数据库记录插入示例 — 批量插入 + 验证 + 惟一性应用
- 用户数据同步: 用户数据同步示例 外部API与每批项目同步
- 快速入门: 快速入门指南 — 5分钟快速入门指南
- 生命周期概述/生命周期回顾: 生命周期与流程 — 每个钩子和事件都已记录在案
- 建筑学: 架构概述 — 系统设计和数据流
______________________________________________________________________
安全与合规
- 对所有已挂载的路由要求进行身份验证(默认
auth:sanctum) - 使用 幂等性密钥 对于来自代理的所有变异调用
- 附加 仅强制执行工作订单 阻止任何遗留的突变路由进行侧门写入
- 记录来源:代理名称/版本,请求指纹
- 将事件/差异发送/传输到您的SIEM/可观测性堆栈
______________________________________________________________________
测试
已包含 Pest/PHPUnit 的设置。为您的自定义类型添加功能测试,涵盖:
- 提案 → 结账 → 发送心跳信号 → 提交 → 审批/申请
- 拒绝与重新提交的路径
- 租赁到期和重试逻辑
- 幂等性行为
composer test
# Run with coverage
vendor/bin/pest --coverage注一些边缘情况测试目前被跳过,等待进一步调查(例如,租约冲突检测、订单准备就绪检查)。这些测试被标记为 markTestSkipped 并且不影响核心功能。
______________________________________________________________________
路线图
- ✅ 核心模型、租赁(或租约)、状态机、幂等性、控制器和命令
- ✅ 抽象基类(
AbstractOrderType,AbstractAcceptancePolicy) - ✅ 完整的生命周期钩子,集成Laravel验证功能
- ✅ 全面的示例和文档
- ✅ MCP服务器 带有stdio和HTTP传输方式
- ✅ 部分提交 用于增量工作项结果
- ✅ 可选的 Redis 租约后端 (参见配置:
'lease.backend' => 'redis') - ✅ 数据库指标跟踪 用于监控工作订单和项目
- 🔜 为挂载的路由生成OpenAPI文档的工具
______________________________________________________________________
文档
Laravel Work Manager 提供了全面且适用于生产的文档,涵盖了该包的所有方面。
📚 完整文档
文档分为以下部分:
- 入门指南/开始使用 - 引言、要求、安装及快速入门指南
- 概念 - 核心架构、生命周期、状态管理以及安全性
- 指南 - 实用的构建和部署操作指南
- 示例 - 实际应用中的完整可运行代码实现
- 参考 - 完整的API、配置、路由、事件和架构参考
- 故障排除 - 常见错误、问题解答(FAQ)和已知限制
- 做出贡献 - 如何贡献、安全策略以及社区支持
🚀 快速入门路径
新接触 Laravel Work Manager?请遵循以下学习路径:
📖 热门话题
- 创建订单类型 - 创建自定义订单类型的完整指南
- MCP服务器集成 - 通过模型上下文协议连接AI代理
- HTTP API 参考 - 完整的REST API文档
- 部分提交 - 复杂任务的增量式工作提交
- 事件与监听器 - 对生命周期事件作出响应
- 部署指南 - 生产部署和扩展
如有关于问题、疑问或功能请求,请访问 。
______________________________________________________________________
贡献
我们欢迎投稿!请参阅 CONTRIBUTING.md(贡献指南文件) for: (在中文中,这个短语通常不单独翻译,因为它是一个介词,表示“为了”或“对于”的意思,具体翻译需结合上下文。例如,“for you”可以翻译为“为了你”或“给你的”。)
- 如何报告错误
- 如何提出功能建议
- 开发环境设置
- 运行测试
- 编码规范
- 拉取请求流程
关键部件 (见 架构概述 (用于系统设计):
src/Http/Controllers/WorkOrderApiController.phpAPI端点src/Services/{WorkAllocator,WorkExecutor,LeaseService,IdempotencyService,StateMachine}— 核心服务src/Support/{AbstractOrderType,AbstractAcceptancePolicy,Enums,Diff,Helpers}— 原始类型 & 基类src/Models/{WorkOrder,WorkItem,WorkEvent,WorkProvenance,WorkIdempotencyKey}— 表达流畅的模型src/Console/{GenerateCommand,MaintainCommand}— 调度器命令
______________________________________________________________________
许可证
麻省理工学院 © 格雷格·普里达伊。见 LICENSE.md。
______________________________________________________________________
支持
需要帮助吗?
- 文档从……开始 常见问题解答(FAQ) 和 常见错误
- 问题报告错误或请求功能请在
- 安全通过电子邮件报告漏洞(参见 安全策略)
- 商业支持如需咨询或获得优先支持,请联系 greg@siteorigin.com
见 支持与社区 以获取更多资源。
______________________________________________________________________
*此README文件展示了当前的包结构,该结构实现了一个包含生命周期钩子、Laravel集成以及全面文档的完整工单控制平面。*
