# 09_TASK_JOB_QUEUE_RUNTIME.md ## DevOS Developer Work OS ### Task / Job / Queue / Worker / Scheduler Runtime 设计规范 Version: 1.0 --- # 1. 文档目标 本文定义 DevOS 的统一异步执行基础设施: ```text Task Job Queue Worker Execution Scheduler Retry Progress Cancellation Concurrency ``` 核心目标: > **Agent、Plugin、Workflow、API、UI、CLI 都只能创建 Task / 调用 Action,不允许各自实现自己的任务队列和 Worker。** DevOS 最终应该形成唯一执行链: ```text User / Agent / Plugin / Workflow ↓ Task ↓ Job ↓ Queue ↓ Worker ↓ Action ↓ Action Runtime ↓ Execution ↓ Event ``` --- # 2. 为什么必须统一 Task Runtime 例如用户: > 给我生成 100 篇文章。 错误实现: ```text Agent ↓ for 1..100 ↓ LLM ↓ API ↓ LLM ↓ API ``` 这样会导致: * Agent 长时间占用 * Token 浪费 * 无法恢复 * 无法暂停 * 无法并发控制 * 无法查看单项进度 * 一个失败导致整个流程混乱 * Agent 崩溃后任务消失 正确实现: ```text Agent ↓ Task ├── Job 001 ├── Job 002 ├── Job 003 ├── ... └── Job 100 ↓ Queue ↓ Workers ``` Agent 只负责: ```text 创建任务 观察结果 调整策略 ``` 不负责: ```text Queue Worker Retry Loop Concurrency ``` --- # 3. Task / Job / Execution 的区别 必须严格区分: ```text Task = 用户/Agent 要完成的一项工作 Job = Task 中可独立调度的一次工作单元 Execution = Action 实际执行的一次运行记录 ``` 例如: ```text Task: 生成 100 篇 SEO 文章 Jobs: article-001 article-002 ... article-100 Execution: article-001.generate article-002.generate ... ``` --- # 4. 核心边界 ```text Agent ↓ 决定做什么 ↓ Task ↓ 决定有哪些 Job ↓ Queue ↓ 决定什么时候执行 ↓ Worker ↓ 执行 Job ↓ Action Runtime ↓ 产生 Execution ``` Golden Rule: > **Task 描述工作,Job 描述调度单位,Execution 描述实际执行。** --- # 5. Task Task 是用户可理解的业务工作单元。 例如: ```text SEO Audit Generate Articles Deploy Application Sync GitHub Backup Database Import Products ``` 定义: ```ts interface Task { id: string; type: string; name: string; description?: string; status: TaskStatus; actor: ActorRef; organizationId: string; projectId?: string; input?: unknown; output?: unknown; progress: TaskProgress; priority: TaskPriority; createdAt: Date; startedAt?: Date; completedAt?: Date; metadata?: Record; } ``` --- # 6. Task Status 统一状态: ```ts type TaskStatus = | "pending" | "queued" | "running" | "paused" | "waiting" | "completed" | "failed" | "cancelled" | "partially_completed"; ``` 状态: ```text pending ↓ queued ↓ running ↓ completed ``` 失败: ```text running ↓ failed ``` 暂停: ```text running ↓ paused ↓ queued ``` 取消: ```text pending / queued / running ↓ cancelled ``` --- # 7. Task 不等于 Job 例如: ```text Task: 部署 myapp ``` 可以包含: ```text Job 1: Build Docker Image Job 2: Push Image Job 3: Connect Server Job 4: Deploy Container Job 5: Health Check ``` 因此: ```text 1 Task + N Jobs ``` --- # 8. Job Job 是 Queue 可以调度的最小工作单元。 ```ts interface Job { id: string; taskId: string; type: string; actionId: string; input: unknown; status: JobStatus; priority: number; attempts: number; maxAttempts: number; scheduledAt?: Date; startedAt?: Date; completedAt?: Date; workerId?: string; executionId?: string; dependencies?: string[]; metadata?: Record; } ``` --- # 9. Job Status ```ts type JobStatus = | "pending" | "queued" | "leased" | "running" | "retrying" | "completed" | "failed" | "cancelled"; ``` 完整流程: ```text pending ↓ queued ↓ leased ↓ running ↓ completed ``` 失败: ```text running ↓ retrying ↓ queued ``` 最终: ```text failed ``` --- # 10. Execution Execution 是 Action Runtime 的实际执行记录。 例如: ```text Job: github.repository.sync Execution: exec_123456 ``` 定义: ```ts interface Execution { id: string; jobId?: string; actionId: string; actor: ActorRef; status: ExecutionStatus; input?: unknown; output?: unknown; error?: ExecutionError; startedAt?: Date; completedAt?: Date; durationMs?: number; metadata?: Record; } ``` --- # 11. 三者关系 ```text Task │ ├── Job │ └── Execution │ ├── Job │ └── Execution │ └── Job └── Execution ``` 一个 Job 在重试时: ```text Job ├── Execution #1 → failed ├── Execution #2 → failed └── Execution #3 → completed ``` 因此: > Job 是逻辑工作,Execution 是尝试。 --- # 12. 为什么 Retry 不能创建新 Task 错误: ```text Task A ↓ failed ↓ Task B ``` 正确: ```text Task A ↓ Job A ├── Execution 1 failed ├── Execution 2 failed └── Execution 3 completed ``` 这样整个任务的历史保持完整。 --- # 13. Queue Queue 是 Job 的调度层。 ```ts interface JobQueue { enqueue(job: Job): Promise; dequeue(queueName: string): Promise; acknowledge(jobId: string): Promise; retry(jobId: string, delayMs: number): Promise; cancel(jobId: string): Promise; } ``` --- # 14. Queue 不执行业务逻辑 Queue 只负责: ```text 保存 排序 等待 分发 重试调度 ``` 不能: ```text Queue ↓ GitHub API ``` 必须: ```text Queue ↓ Worker ↓ Action Runtime ``` --- # 15. Queue 类型 推荐至少: ```text default high low ai network browser deployment sync ``` 但不要过度创建 Queue。 可以通过: ```text priority concurrency resource group ``` 实现细粒度调度。 --- # 16. Queue Priority 定义: ```ts type TaskPriority = | "critical" | "high" | "normal" | "low"; ``` 内部转换: ```text critical → 100 high → 75 normal → 50 low → 25 ``` Worker 优先执行高优先级 Job。 --- # 17. Worker Worker 是真正执行 Job 的进程。 ```ts interface Worker { id: string; name: string; queues: string[]; status: WorkerStatus; concurrency: number; capabilities?: string[]; startedAt: Date; lastHeartbeatAt?: Date; } ``` --- # 18. Worker Status ```text starting idle busy draining stopped unhealthy ``` --- # 19. Worker 不应该拥有业务状态 Worker 不应该保存: ```text Task state User state Agent state Plugin state ``` Worker 只负责: ```text receive Job execute report ``` 这样 Worker 可以随时: ```text restart scale replace ``` --- # 20. Worker 执行流程 ```text Worker ↓ Receive Job ↓ Acquire Lease ↓ Validate Job ↓ Create Execution ↓ Action Runtime ↓ Report Progress ↓ Complete Execution ↓ Update Job ↓ Update Task ↓ Publish Event ``` --- # 21. Lease Worker 获取 Job 时必须建立 Lease。 例如: ```text Job: abc Lease: worker-03 Expires: 22:31:00 ``` 防止: ```text Worker A ↓ Job Worker A crash Worker B ↓ same Job ``` 导致重复执行。 --- # 22. Lease Timeout 如果 Worker 心跳消失: ```text Lease expired ``` Job: ```text leased ``` 重新变成: ```text queued ``` 然后其他 Worker 可以领取。 --- # 23. Heartbeat Worker: ```text 每 5 秒 ``` 发送: ```text heartbeat ``` 例如: ```ts interface WorkerHeartbeat { workerId: string; timestamp: Date; activeJobs: number; capacity: number; } ``` --- # 24. Worker Graceful Shutdown Worker 停止时: ```text SIGTERM ↓ draining ↓ 停止接收新 Job ↓ 等待当前 Job ↓ 完成 ↓ stopped ``` 如果超时: ```text release leases ``` 让其他 Worker 接管。 --- # 25. Worker Concurrency 例如: ```text Worker A concurrency = 5 ``` 最多: ```text 5 Jobs ``` 同时执行。 不同 Worker: ```text Worker A → 5 Worker B → 5 Worker C → 10 ``` 总并发: ```text 20 ``` --- # 26. Resource Concurrency 除了 Worker,还需要限制外部资源。 例如: ```text OpenAI maxConcurrency = 10 GitHub maxConcurrency = 20 Browser maxConcurrency = 5 ``` 否则: ```text 100 Jobs ↓ 100 requests ↓ API rate limit ``` --- # 27. Resource Group Job 可以声明: ```ts resourceGroup?: string; ``` 例如: ```text ai.openai github.api browser.instance server.production ``` Scheduler / Queue Runtime 可以保证: ```text 同一 resourceGroup 最多 N 个并发 ``` --- # 28. Concurrency Policy ```ts interface ConcurrencyPolicy { key: string; maxConcurrent: number; scope: | "global" | "organization" | "project" | "resource"; } ``` 例如: ```text OpenAI Global: 100 Organization: 10 Project: 5 ``` --- # 29. Task Progress Task 必须支持统一进度: ```ts interface TaskProgress { total?: number; completed: number; failed: number; running: number; percentage?: number; message?: string; updatedAt: Date; } ``` 例如: ```text SEO Article Generation 72 / 100 72% ``` --- # 30. Job Progress Job 也可以报告: ```text 0% 25% 50% 75% 100% ``` 例如: ```text Download website ``` Worker: ```text 25% 50% 75% 100% ``` Task Runtime 汇总。 --- # 31. Progress Event 统一事件: ```text task.progress job.progress ``` 例如: ```ts { type: "job.progress", jobId: "job_123", percentage: 75 } ``` 前端通过: ```text WebSocket SSE Polling ``` 获取。 --- # 32. Cancellation Task 必须支持: ```text Cancel ``` 但: ```text Cancel ≠ kill process ``` 流程: ```text User ↓ Cancel Task ↓ Task Runtime ↓ Signal Job ↓ AbortSignal ↓ Action Runtime ↓ Plugin ``` --- # 33. AbortSignal ActionContext 已经定义: ```ts signal: AbortSignal; ``` Worker 必须传递: ```text Task ↓ Job ↓ Execution ↓ ActionContext.signal ``` Plugin / Action 必须响应取消。 --- # 34. Cancellation State 推荐: ```text pending → cancelled queued → cancelled running → cancelling → cancelled ``` 增加: ```ts "cancelling" ``` 可以避免误认为 Action 已立即停止。 --- # 35. 强制终止 如果 Action 长时间不响应: ```text Grace Period ↓ Force Termination ``` 但只能由: ```text Worker Runtime ``` 执行。 不能由 UI 直接杀 Worker。 --- # 36. Retry Job 可以定义: ```ts interface RetryPolicy { maxAttempts: number; backoff: | "fixed" | "linear" | "exponential"; initialDelayMs: number; maxDelayMs?: number; jitter?: boolean; } ``` --- # 37. Retry Example ```text Attempt 1 ↓ fail ↓ 1 sec ↓ Attempt 2 ↓ fail ↓ 2 sec ↓ Attempt 3 ↓ fail ↓ 4 sec ↓ Attempt 4 ``` --- # 38. Retryable Error Action Error 必须声明: ```ts interface ExecutionError { code: string; message: string; retryable: boolean; category?: string; details?: unknown; } ``` 例如: ```text HTTP 429 retryable = true ``` 而: ```text INVALID_INPUT retryable = false ``` --- # 39. Retry 分类 推荐: ```text network timeout rate_limit temporary dependency authentication authorization validation business system ``` 默认策略: ```text network → retry timeout → retry rate_limit → retry temporary → retry validation → no retry authorization → no retry invalid_input → no retry ``` --- # 40. Dead Letter Queue 最终失败的 Job: ```text Retry exhausted ↓ Dead Letter Queue ``` 例如: ```text DLQ ├── job-123 ├── job-456 └── job-789 ``` 管理员可以: ```text Retry Inspect Cancel Replay ``` --- # 41. Replay Replay 必须生成新的 Execution。 不能修改旧 Execution。 例如: ```text Job ├── Execution 1 failed ├── Execution 2 failed └── Execution 3 ← replay ``` Audit 保留完整历史。 --- # 42. Idempotency 所有可能重试的 Action 必须考虑幂等。 例如: ```text createRepository ``` 第一次: ```text GitHub 创建成功 ``` 但 Worker 在收到响应前崩溃。 系统认为: ```text failed ``` 再次执行可能产生: ```text duplicate repository ``` 所以必须支持: ```text idempotencyKey ``` --- # 43. Job Idempotency ```ts interface Job { idempotencyKey?: string; } ``` Action Runtime: ```text same key ↓ same logical operation ``` 如果已经成功: ```text return existing result ``` --- # 44. Task Idempotency 用户重复点击: ```text Generate 100 articles ``` 不能创建: ```text Task A Task B Task C ``` 除非用户明确要求。 可以使用: ```text taskType organization project idempotencyKey ``` 进行去重。 --- # 45. Scheduling Scheduler 负责: ```text 什么时候创建 Task / Job ``` 例如: ```text Every 10 minutes Daily Weekly At specific time After event ``` Scheduler 不负责执行。 --- # 46. Scheduler Architecture ```text Scheduler ↓ Detect Trigger ↓ Create Task / Job ↓ Queue ↓ Worker ``` --- # 47. Cron 支持: ```text 0 * * * * 0 0 * * * 0 0 * * 1 ``` 例如: ```text 每小时同步 GitHub ``` Scheduler: ```text cron ↓ github.repository.sync Task ``` --- # 48. Schedule Resource Schedule 本身也是 Resource: ```text scheduler.schedule ``` Action: ```text scheduler.schedule.create scheduler.schedule.update scheduler.schedule.delete scheduler.schedule.enable scheduler.schedule.disable ``` 这样 UI / API / Agent 都统一。 --- # 49. Schedule Definition ```ts interface Schedule { id: string; name: string; cron: string; timezone: string; actionId?: string; taskType?: string; input?: unknown; enabled: boolean; organizationId: string; projectId?: string; nextRunAt?: Date; lastRunAt?: Date; } ``` --- # 50. Timezone Schedule 必须明确: ```text timezone ``` 不能默认: ```text server timezone ``` 例如: ```text Asia/Tokyo UTC America/New_York ``` --- # 51. Missed Schedule 服务器停机: ```text 00:00 schedule ``` 但服务器: ```text 23:00 - 02:00 offline ``` 重启后怎么办必须由策略决定: ```text skip run_once run_all ``` 默认: ```text skip ``` 避免突然创建大量任务。 --- # 52. Event Trigger Task 也可以由 Event 创建。 例如: ```text github.pull_request.created ``` 触发: ```text code review Task ``` 流程: ```text Event ↓ Trigger ↓ Task ↓ Job ↓ Queue ``` --- # 53. Webhook Trigger 例如: ```text GitHub Webhook ↓ DevOS Event ↓ Task ``` Webhook Controller 只负责: ```text receive verify publish event ``` 不负责业务执行。 --- # 54. Task Dependencies Task 可以依赖其他 Task: ```text Build ↓ Deploy ↓ Health Check ``` Job 也可以依赖 Job: ```text Job A ↓ Job B ↓ Job C ``` --- # 55. Job Dependency Graph 定义: ```ts interface JobDependency { jobId: string; dependsOn: string[]; condition?: | "all" | "any" | "success" | "completed"; } ``` --- # 56. DAG 推荐使用 DAG: ```text Build / \ Test Security Scan \ / Deploy ↓ Health Check ``` 不能出现: ```text A → B B → C C → A ``` 必须检测循环。 --- # 57. Parallel Jobs 例如: ```text Build ↓ ├── Test ├── Security Scan └── Lint ``` 三者可以并发。 完成后: ```text Test Security Lint ↓ Deploy ``` --- # 58. Task Aggregation Task 状态由 Jobs 聚合: ```text 100 jobs ``` 如果: ```text 90 completed 5 failed 5 running ``` Task: ```text partially_completed ``` 进度: ```text 90% ``` --- # 59. Task Completion Policy 支持: ```text all_success best_effort any_success threshold ``` 例如: ```text 100 articles ``` 要求: ```text 至少 95 篇成功 ``` 则: ```text threshold = 95% ``` --- # 60. Batch Task 针对大量工作: ```text Task ↓ Batch ↓ Jobs ``` 例如: ```text 生成 1000 篇文章 ``` 不要: ```text 1000 个 Agent Run ``` 应该: ```text 1 Agent Goal ↓ 1 Task ↓ 1000 Jobs ``` --- # 61. Batch Job Generation Agent 可以告诉 Task Runtime: ```ts createBatchTask({ type: "content.generate", items: articles }); ``` Task Runtime: ```text items ↓ Job Factory ↓ Jobs ``` Agent 不负责逐个创建。 --- # 62. Job Factory ```ts interface JobFactory { createJobs( task: Task, input: unknown ): Promise; } ``` 例如: ```text 100 URLs ↓ 100 Jobs ``` --- # 63. Dynamic Job Creation 有些 Task 不知道最终 Job 数量。 例如: ```text 爬取网站 ``` 流程: ```text Job 1: Discover URLs ↓ 发现 500 URLs ↓ 创建 500 Jobs ``` 允许 Worker / Action 发布: ```text Task Expansion ``` 但必须通过: ```text Task Runtime ``` 完成。 --- # 64. Dynamic Expansion 限制 必须设置: ```text maxJobs maxDepth maxExpansion ``` 防止: ```text Job ↓ 100 jobs ↓ 10000 jobs ↓ 1,000,000 jobs ``` --- # 65. Backpressure 当 Queue: ```text 100000 jobs ``` 不能继续无限创建。 Task Runtime 应返回: ```text accepted queued throttled ``` 例如: ```text Queue capacity exceeded ``` 进入: ```text waiting ``` --- # 66. Rate Limiting Job 可以受: ```text Global Rate Limit Organization Rate Limit Project Rate Limit Plugin Rate Limit External API Rate Limit ``` 共同约束。 --- # 67. Token Budget AI Job 可以声明: ```ts interface JobBudget { maxTokens?: number; maxCost?: number; maxDurationMs?: number; } ``` 例如: ```text Generate Article maxTokens = 10000 maxCost = $0.10 ``` 超过: ```text budget exceeded ``` Job 失败或进入审批。 --- # 68. Cost Tracking 每次 Execution 记录: ```text inputTokens outputTokens totalTokens estimatedCost actualCost currency ``` Task 汇总: ```text 100 articles Total tokens: 2.4M Cost: $13.20 ``` --- # 69. External API Usage Execution 可以记录: ```text externalRequests externalDuration externalCost ``` 例如: ```text OpenAI: 10 requests GitHub: 5 requests Browser: 3 sessions ``` 用于: ```text Observability Billing Budget ``` --- # 70. Task Events 至少: ```text task.created task.queued task.started task.progress task.paused task.resumed task.completed task.failed task.cancelled ``` Job: ```text job.created job.queued job.started job.retrying job.completed job.failed job.cancelled ``` --- # 71. Task Audit 例如: ```text User created Task Agent modified Task Worker started Job Action executed Job retried User cancelled Task ``` 都进入: ```text Audit Runtime ``` --- # 72. Task API 推荐: ```text GET /api/tasks GET /api/tasks/:id POST /api/tasks POST /api/tasks/:id/pause POST /api/tasks/:id/resume POST /api/tasks/:id/cancel POST /api/tasks/:id/retry GET /api/tasks/:id/jobs GET /api/tasks/:id/executions GET /api/tasks/:id/events ``` --- # 73. Job API ```text GET /api/jobs GET /api/jobs/:id POST /api/jobs/:id/retry POST /api/jobs/:id/cancel GET /api/jobs/:id/executions ``` 普通用户通常不需要直接操作 Job。 Job API 主要服务: ```text Admin Developer Operations Agent Runtime ``` --- # 74. Worker API Worker 通常使用内部协议: ```text POST /internal/workers/register POST /internal/workers/heartbeat POST /internal/workers/lease POST /internal/workers/report ``` 也可以使用 Redis / Message Queue。 --- # 75. Queue Backend 第一版本可以使用: ```text Redis ``` 实现: ```text Queue Lease Retry Delay Priority ``` 数据库负责: ```text Task Job Execution Audit ``` Redis 负责: ```text Scheduling Queue Locks Heartbeat ``` --- # 76. Database 与 Queue 分工 不要把 Redis 当永久业务数据库。 推荐: ```text PostgreSQL ├── Task ├── Job ├── Execution ├── Schedule └── Audit Redis ├── Queue ├── Lease ├── Lock ├── Worker heartbeat └── Temporary state ``` --- # 77. Queue Consistency 关键问题: ```text DB Job created ↓ Redis enqueue failed ``` 如果直接: ```text DB commit Redis enqueue ``` 可能造成 Job 永远不执行。 因此必须支持: ```text Outbox Pattern ``` --- # 78. Outbox 流程: ```text DB Transaction ├── Create Job └── Create Outbox Event ↓ Commit ↓ Outbox Worker ↓ Redis Queue ``` 这样可以保证最终进入 Queue。 --- # 79. Event Outbox 同样: ```text Action Execution ↓ DB transaction ├── update execution └── event outbox ``` 再: ```text Outbox ↓ Event Bus ``` 避免: ```text DB 成功 Event 丢失 ``` --- # 80. Queue At-Least-Once 默认: ```text At-least-once delivery ``` 意味着: ```text Job 可能被执行超过一次 ``` 所以: > Action 必须尽可能幂等。 不要假设: ```text exactly-once ``` --- # 81. Duplicate Detection Worker 获取 Job: ```text jobId ``` Action Runtime 检查: ```text execution idempotency ``` 如果已经完成: ```text return existing execution ``` --- # 82. Distributed Lock 某些 Action 必须: ```text single execution ``` 例如: ```text production deployment ``` 使用: ```text Lock: deployment:production:app ``` 确保: ```text 只有一个 Job ``` 执行。 --- # 83. Task Lock Task 也可以: ```text exclusive ``` 例如: ```text Database Migration ``` 禁止同时执行: ```text Migration A Migration B ``` --- # 84. Pause Pause Task: ```text Task ↓ paused ``` 行为: ```text queued jobs → 不再领取 running jobs → 默认继续完成 new jobs → 不创建/不调度 ``` 也可以提供: ```text hard pause ``` 请求取消正在运行的 Job。 --- # 85. Resume ```text paused ↓ resume ↓ queued ``` 继续剩余 Jobs。 已经完成的 Job: ```text 不重复执行 ``` --- # 86. Task Timeout Task 可以定义: ```text maxDurationMs ``` 例如: ```text 2 hours ``` 超过: ```text Task timeout ``` 策略: ```text cancel remaining jobs ``` --- # 87. Job Timeout 每个 Job 可以定义: ```text timeoutMs ``` 例如: ```text browser.navigate 30 sec ``` 超时: ```text Execution timeout ↓ Abort ↓ Retry ``` 如果 retryable。 --- # 88. Queue Timeout 如果 Job: ```text queued ``` 超过: ```text maxQueueWait ``` 可以: ```text fail ``` 或者: ```text priority escalate ``` 用于检测 Worker 不足。 --- # 89. Worker Auto Scaling 未来可以: ```text Queue Depth ↓ Scaler ↓ Worker Count ``` 例如: ```text Queue: 1000 Jobs Workers: 5 Scale: 20 ``` 但第一版本不需要复杂 Kubernetes Autoscaler。 保留接口: ```ts interface WorkerScaler {} ``` --- # 90. Worker Capability 某些 Job 只能给特定 Worker。 例如: ```text browser Job ``` 要求: ```text worker.capabilities: browser ``` Server deployment: ```text worker.capabilities: docker ssh ``` --- # 91. Worker Tags Worker: ```text tags: browser linux gpu region-us ``` Job: ```text requiredTags: browser ``` Scheduler: ```text 只分配给匹配 Worker ``` --- # 92. Plugin Job Plugin 可以声明 Job 类型: ```text github.sync browser.crawl cloudflare.dns.update ``` 但执行: ```text Job ↓ Action Runtime ``` Plugin 不拥有 Worker Runtime。 --- # 93. Agent Task Agent 创建: ```text Task ``` 例如: ```text Goal: 检查 100 个网站 SEO Task: seo.batch_audit Jobs: site-001 ... site-100 ``` Agent: ```text 观察 ↓ 等待 Task ↓ 分析结果 ``` 而不是: ```text Agent ↓ 100 次工具调用 ``` --- # 94. Agent Observation Task 完成后产生: ```text task.completed ``` Agent 收到: ```text Observation ``` 然后决定: ```text Complete Replan Create another Task Ask Human ``` --- # 95. Agent 与 Task 的边界 ```text Agent: Why / What next Task: Work to be done Job: Unit to schedule Worker: Who executes Action: How to execute Execution: What happened ``` 这是整个 DevOS 最重要的边界之一。 --- # 96. Workflow 与 Task Workflow: ```text 预定义流程 ``` Task: ```text 一次实际工作 ``` 例如: ```text Workflow: SEO Audit Workflow Task: Audit example.com ``` 执行: ```text Workflow ↓ Task ↓ Jobs ``` --- # 97. Workflow 不应该绕过 Task 错误: ```text Workflow ↓ Action ↓ Action ↓ Action ``` 如果流程可能: * 长时间运行 * 可暂停 * 可重试 * 可观察 应该: ```text Workflow ↓ Task ↓ Jobs ``` --- # 98. Task UI 推荐: ```text /tasks ``` 列表: ```text Task Status Progress SEO Audit Running 72% Generate Articles Completed 100% Deploy App Failed 80% GitHub Sync Queued 0% ``` --- # 99. Task Detail ```text SEO Audit ──────────────────── Status: Running Progress: 72% Jobs: 72 completed 3 failed 5 running 20 queued Started: 10:30 Duration: 12m Cost: $2.31 ``` --- # 100. Task Timeline 显示: ```text 10:30 Task created 10:31 Job 001 started 10:31 Job 001 completed 10:32 Job 002 started 10:33 Job 002 retrying 10:34 Job 002 completed ... ``` 数据来自: ```text Event Execution Audit ``` 不是 UI 自己记录。 --- # 101. Job Detail ```text Job ──────────────── Action: seo.website.scan Status: Completed Attempts: 2 Execution: exec_123 Worker: worker-07 Duration: 31s Retry: 1 ``` --- # 102. Execution Detail ```text Execution ──────────────── Action: seo.website.scan Actor: agent:seo-agent Input: example.com Output: ... Duration: 13.2s External Requests: 4 Tokens: 0 Cost: $0.00 ``` --- # 103. Task Streaming 对于实时任务: ```text Task ↓ SSE / WebSocket ↓ UI ``` 推送: ```text progress logs job status execution output events ``` --- # 104. Task Logs 统一: ```text Task ↓ Job ↓ Execution ↓ Logs ``` 日志必须关联: ```text taskId jobId executionId workerId pluginId actionId ``` --- # 105. Task Output Task 可以最终产生: ```ts interface TaskOutput { summary?: string; data?: unknown; artifacts?: ArtifactRef[]; links?: LinkRef[]; } ``` 例如: ```text 100 SEO reports ``` 生成: ```text reports/*.json reports/*.html ``` 通过: ```text Artifact Runtime ``` 管理。 --- # 106. Artifact 不要直接把巨大结果塞进: ```text Task.output ``` 例如: ```text 1000 MB CSV ``` 应该: ```text Task ↓ Artifact ↓ Object Storage ``` Task 只保存: ```text artifactId ``` --- # 107. Task Result Size 推荐: ```text small output → DB large output → Artifact Storage ``` 例如: ```text JSON < 1MB → DB large HTML → Object Storage ``` 具体阈值配置化。 --- # 108. Task Security Task 必须带: ```text actor organizationId projectId ``` 查询 Task: ```text User A ``` 不能读取: ```text Organization B ``` --- # 109. Task Authorization 前端: ```text 显示/隐藏 ``` 只是 UX。 真正: ```text GET /tasks/:id POST /tasks/:id/cancel ``` 必须经过: ```text Authorization Resource Scope ``` --- # 110. Task Audit Cancel: ```text User ↓ task.cancel ↓ Task Runtime ``` Audit: ```text actor=user action=task.cancel resource=task:123 ``` --- # 111. Task API 不直接执行 Action 错误: ```text POST /tasks ↓ Controller ↓ executeAction() ``` 正确: ```text POST /tasks ↓ Task Runtime ↓ Create Task ↓ Create Job ↓ Queue ``` Worker 才执行 Action。 --- # 112. Action Runtime 与 Worker Worker 不应该自己实现 Action。 正确: ```text Worker ↓ ActionRuntime.execute(actionId, input, context) ``` Action Runtime 负责: ```text Permission Validation Middleware Transaction Audit Execution Error ``` --- # 113. Worker 与 Plugin Worker: ```text 不需要知道 GitHub Plugin 的内部实现 ``` 只需要: ```text Action ID ``` 例如: ```text github.repository.sync ``` Action Registry: ```text resolve ``` 然后执行。 --- # 114. Queue 与 Plugin Queue 不知道: ```text GitHub SEO Browser ``` Queue 只知道: ```text Job priority resourceGroup schedule ``` --- # 115. Scheduler 与 Agent Scheduler 可以触发: ```text Agent Goal ``` 例如: ```text Every Monday ↓ Create Agent Goal: 分析本周 SEO 数据 ``` Agent 再: ```text Goal ↓ Plan ↓ Task ``` 因此: ```text Scheduler ≠ Agent ``` --- # 116. Scheduler 与 Plugin Plugin 可以声明 Schedule: ```text GitHub Plugin ↓ github.sync schedule ``` Scheduler 统一执行。 Plugin 不实现 Cron Worker。 --- # 117. Queue Worker Architecture 推荐: ```text packages/task/ ├── task-runtime.ts ├── task-service.ts ├── task-progress.ts ├── task-cancellation.ts │ ├── job-runtime.ts ├── job-service.ts ├── job-factory.ts │ ├── queue/ │ ├── queue.ts │ ├── redis-queue.ts │ └── queue-scheduler.ts │ ├── worker/ │ ├── worker.ts │ ├── worker-manager.ts │ ├── worker-heartbeat.ts │ └── worker-lease.ts │ ├── retry/ │ └── retry-policy.ts │ ├── scheduler/ │ ├── scheduler.ts │ ├── cron.ts │ └── triggers.ts │ └── execution/ └── execution-service.ts ``` --- # 118. Database Models 至少: ```text Task Job Execution Schedule Worker JobDependency TaskEvent OutboxEvent ``` 可选: ```text TaskArtifact TaskLog JobLease ``` --- # 119. Task Repository ```ts interface TaskRepository { create(input): Promise; findById(id): Promise; updateStatus(id, status): Promise; updateProgress(id, progress): Promise; list(filter): Promise; } ``` --- # 120. Job Repository ```ts interface JobRepository { create(input): Promise; findById(id): Promise; claim(id, workerId): Promise; updateStatus(id, status): Promise; incrementAttempts(id): Promise; listByTask(taskId): Promise; } ``` --- # 121. Worker Manager ```ts interface WorkerManager { register(worker): Promise; heartbeat(workerId): Promise; drain(workerId): Promise; stop(workerId): Promise; list(): Promise; } ``` --- # 122. Queue Adapter 不要把 Redis API 直接暴露给业务。 定义: ```ts interface QueueAdapter { enqueue(job: QueueMessage): Promise; reserve( queue: string, workerId: string ): Promise; ack(messageId: string): Promise; release(messageId: string): Promise; delay(messageId: string, delayMs: number): Promise; } ``` 未来可以替换: ```text Redis RabbitMQ Kafka SQS NATS ``` 而不修改 Task Runtime。 --- # 123. 第一版本 Queue 第一版本推荐: ```text PostgreSQL + Redis ``` 不要一开始引入: ```text Kafka RabbitMQ Kubernetes Temporal ``` 除非实际规模已经需要。 架构层保留: ```text QueueAdapter ``` 未来可以替换。 --- # 124. Transaction Boundary 创建 Task: ```text BEGIN ↓ Task ↓ Jobs ↓ Outbox ↓ COMMIT ``` Queue: ```text Outbox ↓ Redis ``` 不要: ```text Redis enqueue ↓ DB transaction ``` 否则容易产生孤儿 Job。 --- # 125. Worker Crash Recovery 场景: ```text Worker ↓ Job ↓ Action executing ↓ Worker crash ``` Lease: ```text expired ``` 系统: ```text Job ↓ queued ↓ Worker B ``` 然后: ```text new Execution ``` --- # 126. Zombie Worker Worker 失去网络但仍运行: ```text Worker A ``` 如果 Lease 已过期: ```text Worker B ``` 领取 Job。 可能产生: ```text A + B ``` 同时执行。 因此: > 所有有副作用的 Action 必须使用 Idempotency / Distributed Lock。 --- # 127. Exactly Once 不作为基础假设 DevOS 默认: ```text at-least-once ``` 开发者必须: ```text 设计幂等 ``` 而不是依赖: ```text exactly-once ``` --- # 128. Task Retry 与 Agent Replan 两者完全不同。 ```text Retry = 相同 Job 再执行 Replan = Agent 改变解决方案 ``` 例如: ```text Browser API timeout ``` → Retry。 而: ```text 网站无法访问 ``` Agent 判断: ```text 改用 Search Plugin ``` → Replan。 --- # 129. Task Failure 与 Agent Failure Task: ```text failed ``` Agent 不一定: ```text failed ``` Agent 可以: ```text Observe ↓ Replan ↓ Create new Task ``` 例如: ```text SEO Audit Task ↓ failed ↓ Agent: 尝试 Browser Plugin ``` --- # 130. Task Approval 危险 Task 可以: ```text waiting ``` 等待: ```text Approval ``` 例如: ```text Production Deployment ``` 流程: ```text Agent ↓ Task ↓ Approval ↓ waiting ↓ Human approve ↓ queued ↓ Worker ``` --- # 131. Approval 不应该是 Worker 逻辑 Worker 遇到: ```text requiresApproval ``` 不能自己: ```text ask user ``` 而应该: ```text Task Runtime ↓ Approval Resource ``` --- # 132. Task Budget Task 可以定义: ```ts interface TaskBudget { maxJobs?: number; maxDurationMs?: number; maxCost?: number; maxTokens?: number; maxExternalRequests?: number; } ``` 超过预算: ```text budget_exceeded ``` --- # 133. Budget Aggregation 例如: ```text Task: 100 articles Budget: $20 ``` Jobs: ```text $0.10 $0.15 $0.08 ... ``` Task Runtime 汇总: ```text actualCost ``` 超过: ```text pause cancel fail approval ``` 策略可配置。 --- # 134. Task Resource Limits 可以限制: ```text maxJobs maxConcurrency maxRetries maxExecutionTime maxQueueTime maxCost ``` 防止异常 Agent 产生: ```text 1000000 Jobs ``` --- # 135. Task Observability 每个 Task 必须可以追踪: ```text Task ID Job IDs Execution IDs Worker IDs Action IDs Plugin IDs Events Logs Costs Retries ``` 形成完整 Trace: ```text Goal ↓ Task ↓ Job ↓ Execution ↓ Action ↓ Plugin ↓ External API ``` --- # 136. Task Trace ID 建议: ```text traceId ``` 贯穿: ```text Agent Task Job Execution Action Plugin External Request ``` 这样一次用户请求可以完整追踪。 --- # 137. Task Metrics 至少: ```text task.created task.completed task.failed job.created job.completed job.failed job.retry queue.depth queue.wait_time worker.active worker.capacity worker.failure execution.duration execution.failure ``` --- # 138. SLO 未来可以设置: ```text Task queue latency Task success rate Job execution latency Worker availability ``` 例如: ```text 95% Jobs < 30s queue wait ``` --- # 139. Task Retention Task / Job / Execution 数量可能巨大。 需要: ```text retention policy ``` 例如: ```text Execution logs: 30 days Task: 180 days Audit: 根据 Audit Policy ``` 但: > 不允许未经策略自动删除 Audit。 --- # 140. Archive 旧 Task: ```text active DB ↓ archive ``` 大数据: ```text PostgreSQL ↓ Object Storage ``` UI 仍然可以查询 Archive。 第一版本可以只实现: ```text retention metadata ``` 暂不实现复杂归档。 --- # 141. Task Search 支持: ```text Task ID Type Status Actor Organization Project Action Plugin Date ``` 例如: ```text plugin = github status = failed last 7 days ``` --- # 142. Admin Queue Dashboard 建议: ```text /admin/tasks /admin/jobs /admin/workers /admin/queues ``` 显示: ```text Queue Depth Running Failed Retrying Workers Throughput Latency ``` --- # 143. Queue Dashboard ```text Queues default 120 ai 32 browser 8 deployment 2 ``` 点击: ```text Queue ↓ Jobs ↓ Workers ``` --- # 144. Worker Dashboard ```text worker-01 ──────────────── Status: Busy Queues: default, ai Concurrency: 5 / 5 Jobs: job-123 job-456 ... Heartbeat: 2 sec ago ``` --- # 145. Scheduler Dashboard ```text Schedules GitHub Sync Every 10 min Next: 10:40 Healthy SEO Report Every Monday Next: Monday Enabled ``` --- # 146. Scheduler Misfire 如果 Scheduler 本身失败: ```text missed run ``` 根据: ```text misfirePolicy ``` 处理: ```text skip run_once run_all ``` --- # 147. Task Runtime 与 Notification Task Event: ```text task.completed ``` Notification Plugin 可以监听: ```text Task completed ``` 发送: ```text Email Slack Telegram Web notification ``` 因此 Task Runtime 不需要知道: ```text Email Slack Telegram ``` --- # 148. Task Runtime 与 Plugin 例如: ```text Cloudflare Plugin ``` 提供: ```text cloudflare.dns.update ``` Task Runtime: ```text Task ↓ Job ↓ Action Runtime ↓ Cloudflare Action ``` --- # 149. Task Runtime 与 Resource Task 本身也可以是: ```text Resource ``` 推荐: ```text core.task core.job core.execution ``` 这样可以复用: ```text Resource Registry Action Registry Permission UI Audit ``` --- # 150. Task Actions 至少: ```text core.task.create core.task.pause core.task.resume core.task.cancel core.task.retry core.task.archive ``` Job: ```text core.job.retry core.job.cancel ``` --- # 151. Task UI 自动生成 因为 Task 是 Resource: ```text Resource Metadata ↓ Generic List ↓ Generic Detail ``` 可以自动生成基础 UI。 特殊任务: ```text Plugin ``` 再提供: ```text Custom Task View ``` --- # 152. Task Event → Agent 例如: ```text task.completed ``` Agent Subscription: ```text Agent Runtime ``` 收到: ```text Observation ``` 然后: ```text Evaluate ↓ Complete / Replan ``` --- # 153. Task Event → Workflow Workflow 可以: ```text On Task Completed ``` 触发: ```text Next Task ``` 形成: ```text Task A ↓ Event ↓ Workflow ↓ Task B ``` --- # 154. Task Event → Plugin Plugin 可以监听: ```text task.failed ``` 例如: ```text Notification Plugin ``` 发送告警。 --- # 155. 最终完整执行模型 ```text User │ Agent │ Goal │ Planner │ Task │ ┌─────┴─────┐ │ │ Job A Job B │ │ └─────┬─────┘ │ Queue │ ┌─────┴─────┐ │ │ Worker A Worker B │ │ └─────┬─────┘ │ Action Runtime │ ┌──────┴──────┐ │ │ Plugin Core │ │ └──────┬──────┘ │ Execution │ Event │ ┌────────────┼────────────┐ │ │ │ UI Agent Workflow ``` --- # 156. Zcode 实现要求 必须新增/完善: ```text packages/task/ packages/job/ packages/queue/ packages/worker/ packages/scheduler/ packages/execution/ ``` 如果当前项目已经存在类似模块: > 不要重复创建第二套 Runtime,应将现有实现迁移/合并到统一 Runtime。 --- # 157. Zcode 禁止事项 禁止: ```text Plugin 自建 Queue Plugin 自建 Worker Agent 自建 Queue Agent 自建 Worker Workflow 自己执行长任务 Controller 直接执行 Action MCP 直接执行外部业务 UI 直接调用 Plugin 内部函数 Scheduler 直接执行业务逻辑 ``` 所有执行必须最终进入: ```text Action Runtime ``` --- # 158. 第一阶段必须完成 Zcode 第一阶段: ```text Task CRUD Job CRUD Execution Redis Queue Worker Retry Progress Cancel ``` 必须真正可运行。 --- # 159. 第二阶段 实现: ```text Scheduler Cron Event Trigger Job Dependency Parallel Jobs Batch Task Task Budget Concurrency Resource Group ``` --- # 160. 第三阶段 实现: ```text Outbox Lease Recovery Dead Letter Queue Replay Advanced Retry Worker Tags Worker Scaling Interface Artifact Retention Advanced Observability ``` --- # 161. 最小可运行 Demo 必须能够运行: ```text POST /api/tasks ``` 创建: ```text Task: Generate 10 test jobs ``` 系统: ```text Task ↓ 10 Jobs ↓ Redis Queue ↓ Worker ↓ Action ↓ 10 Executions ``` 最终: ```text Task: completed Progress: 100% Jobs: 10 / 10 Executions: 10 ``` --- # 162. Batch Demo 创建: ```text Task: Generate 100 items ``` 系统: ```text 1 Task 100 Jobs N Workers ``` 例如: ```text Worker 1 → Job 1-5 Worker 2 → Job 6-10 Worker 3 → Job 11-15 ... ``` 最终: ```text 100 completed ``` Agent 不参与每个 Job 的循环。 --- # 163. Retry Demo Job: ```text test.retry ``` 第一次: ```text fail retryable=true ``` 自动: ```text retry ``` 第二次: ```text success ``` 结果: ```text Job: completed Attempts: 2 Executions: 2 ``` --- # 164. Cancel Demo 创建: ```text 10 long-running Jobs ``` 用户: ```text Cancel Task ``` 系统: ```text queued Jobs → cancelled running Jobs → abort ``` 最终: ```text Task: cancelled ``` --- # 165. Scheduler Demo 创建: ```text Every minute ``` Scheduler: ```text Schedule ↓ Task ↓ Job ↓ Queue ↓ Worker ``` 每分钟自动创建任务。 --- # 166. Worker Recovery Demo 启动: ```text Worker A ``` 执行 Job。 强制杀掉: ```text Worker A ``` 等待 Lease: ```text expired ``` 启动: ```text Worker B ``` Job: ```text requeued ``` Worker B: ```text execute ``` --- # 167. 最终验收标准 以下全部成立才算完成: ```text [ ] Task 是统一任务模型 [ ] Job 是统一调度单位 [ ] Execution 是统一执行记录 [ ] Queue 不包含业务逻辑 [ ] Worker 不包含业务逻辑 [ ] Action Runtime 是唯一执行入口 [ ] Redis Queue 可工作 [ ] Worker Lease 可工作 [ ] Worker Heartbeat 可工作 [ ] Retry 可工作 [ ] Idempotency 可工作 [ ] Progress 可工作 [ ] Cancellation 可工作 [ ] Pause/Resume 可工作 [ ] Batch Task 可工作 [ ] Job Dependency 可工作 [ ] Scheduler 可工作 [ ] Cron 可工作 [ ] Event Trigger 可工作 [ ] Task Budget 可工作 [ ] Concurrency 可工作 [ ] Resource Group 可工作 [ ] Task Event 可工作 [ ] Audit 可工作 [ ] Agent 可以创建 Task [ ] Agent 不直接控制 Worker [ ] Plugin 可以创建 Task [ ] Plugin 不创建自己的 Queue [ ] Workflow 可以创建 Task [ ] MCP 创建的工作进入 Task/Action Runtime [ ] UI 可以实时观察 Task [ ] CLI 与 UI 使用同一 Task Runtime ``` --- # 168. DevOS 最终执行 Golden Rule 以后 DevOS 中任何需要: ```text 异步 批量 延迟 重试 定时 长时间 并发 后台 可恢复 可观察 可取消 ``` 的工作: **全部进入 Task Runtime。** 统一模型: ```text Task ↓ Job ↓ Queue ↓ Worker ↓ Action Runtime ↓ Execution ↓ Event ``` Agent: ```text 决定做什么 ``` Task: ```text 记录要做什么 ``` Job: ```text 定义具体工作单元 ``` Queue: ```text 决定什么时候做 ``` Worker: ```text 负责执行 ``` Action Runtime: ```text 负责如何安全地执行 ``` Execution: ```text 记录实际发生了什么 ``` Event: ```text 告诉系统发生了什么 ``` 这套模型必须成为 DevOS 所有 App、Plugin、MCP、Skill、Agent、Workflow、Scheduler 的**唯一异步执行基础设施**。