Task Breakdown: Agents
Feature ID: agents
Plan: ./plan.md
Status: Draft
Last updated: 2026-05-25
How to use
Tasks are grouped into phases mirroring plan.md §10. Tasks within a phase are sequential unless marked (parallel). File paths are absolute under the platform repo root. Mark tasks - [x] when the matching commit is on develop or its session branch.
Phases 1-3 land MVP (Agent entity + Instructions tab + heartbeat runtime). Phases 4-6 round out dashboards, task-driven runtime, and Mission Template integration.
Phase 1 — Data model + read-only API
- T1. Create entity file
packages/agent/src/entities/agent.entity.tsper plan.md §3.1. - T2 (parallel). Create entity file
packages/agent/src/entities/agent-run.entity.ts. - T3 (parallel). Create entity file
packages/agent/src/entities/agent-run-log.entity.ts. - T4 (parallel). Create entity file
packages/agent/src/entities/agent-budget.entity.ts. - T5 (parallel). Create entity file
packages/agent/src/entities/agent-membership.entity.ts. - T6. Register the new entities in
packages/agent/src/entities/index.tsand in the TypeORM datasource atapps/api/src/typeorm.config.ts. - T7. Generate migration:
cd apps/api && pnpm typeorm migration:generate -d typeorm.config.ts src/migrations/CreateAgentsTables. Inspect the generated SQL; replace any destructiveALTER/DROPwith the two-phase forward-only pattern perdocs/specs/architecture/database-migrations.md. - T8. Add
agentIdcolumn + index topackages/agent/src/entities/plugin-usage-event.entity.ts(nullable). Migration:AddAgentIdToPluginUsageEvents. - T9. Extend
ActivityActionTypeenum/string set with the 13 new event types listed in architecture §10. Update the API's activity-feed group-filter mapping inapps/api/src/activity-log/activity-log.controller.ts. - T10. Create repository
packages/agent/src/database/repositories/agent.repository.tswithfindById,findByUserIdScoped,findByUserIdAndSlug,findDueForHeartbeat,casUpdateStatus(id, from, to),incrementErrorCount. Test:packages/agent/src/database/repositories/__tests__/agent.repository.spec.ts. - T11. Create repositories for AgentRun, AgentRunLog, AgentBudget, AgentMembership. Same pattern. Tests per file.
- T12. Create DTO files under
apps/api/src/agents/dto/:create-agent.dto.ts,update-agent.dto.ts,list-agents-query.dto.ts,agent-response.dto.ts. Useclass-validator+ zod for cross-field rules (scope ⇔ targetId consistency). - T13. Create
apps/api/src/agents/agent.service.tswith methods:create,findOne,update,archive,list,validateScopeOwnership. Cross-user reads return 404. Test:apps/api/src/agents/__tests__/agent.service.spec.ts. - T14. Create
apps/api/src/agents/agent.controller.tscovering routes in plan.md §4 Phase-1 subset (GET, POST, PATCH, DELETE, list, pause/resume but no run-now yet). Use@CurrentUser()from existing auth module. Test: e2e inapps/api/test/agents.e2e-spec.ts. - T15. Wire
AgentsModuleintoapps/api/src/app.module.ts. - T16. Extend
packages/agent/src/works-config/services/works-config.service.tsZod schema with optionalagents+skillsarrays. Round-trip read/write test. - T17. Extend
packages/agent/src/missions/mission-template-manifest.service.tsZod schema same way. Round-trip test. - T18. Add i18n keys per spec.md §5.1 to
apps/web/messages/en.json. Runpnpm translate:messagesto populate other locales. - T19. Patch
apps/web/src/components/dashboard/DashboardSidebar.tsxto insert "Agents", "Tasks", "Skills" items in the correct order with lucide-react icons. Don't wire Tasks/Skills routes yet (Phase 1 only). - T20. Create the empty-state page
apps/web/src/app/[locale]/(dashboard)/agents/page.tsx(server component) with+ New AgentCTA wired to/agents/new.
Phase 2 — File storage + Instructions tab
- T21. Create
apps/api/src/agents/agent-file.service.ts. Methods:read(agentId, name),write(agentId, name, body, commitMessage). Branches by scope: Git mode viaGitFacadeServicefor Mission/Work-scoped; DB inline for Tenant-scoped (writes the matchingagent.{soulMd,agentsMd,heartbeatMd,toolsMd,agentYml}column). - T22. Add secret-scan regex helper
packages/agent/src/utils/secret-scan.tsand unit test. Reject onsk-,xoxb-,AKIA[A-Z0-9]{16,},ghp_[A-Za-z0-9]{36,},glpat-.... - T23. Add controller routes
GET /agents/:id/files/:nameandPUT /agents/:id/files/:name. Validatenameagainst['SOUL', 'AGENTS', 'HEARTBEAT', 'TOOLS', 'agent.yml']. Test: e2e read/write cycle for both Git and DB-inline modes. - T24. Update
agents.contentHashon everywrite. Hash is sha256 of the 5-file canonical concatenation. - T25. Add
AGENT_FILE_EDITEDactivity row on every successful write; includedetails: {name, prevHash, newHash, diff?}(truncate diff to 5 KB). - T26. Build the
/agents/[id]/instructionspage using the existingKbEditor.tsxTiptap component, but with a 5-tab strip on top (one tab per file). 800 ms autosave debounce. - T27. Add
apps/web/src/lib/api/agents.tsAPI client wrappers. - T28. Playwright test: create Mission-scoped agent → edit SOUL.md → verify commit landed on the Mission's
missionRepovia the GitHub API mock used in other e2e tests.
Phase 3 — Runtime
- T29. Create
packages/tasks/src/tasks/trigger/agent-heartbeat-dispatcher.task.ts. Cron:*/${AGENT_DISPATCH_INTERVAL_MINUTES} * * * *(default 1m). Same shape aswork-schedule-dispatcher.task.ts. - T30. Implement
AgentScheduleDispatcherService.dispatchDue()inpackages/agent/src/agents/agent-schedule-dispatcher.service.ts. CAS-claim viarepo.casUpdateStatus(agentId, ACTIVE, RUNNING); on success insertagent_runsrow +runs.trigger('agent-heartbeat', ...). Test: race two concurrent calls, expect exactly one to claim. - T31. Create
packages/tasks/src/tasks/trigger/agent-heartbeat.task.ts(one-shot,maxDuration: 30 * 60). Bootstrap NestJS via the existing helper, then callAgentRunService.execute({agentId, runId, kind: 'heartbeat'}). - T32. Implement
AgentRunService.execute()inpackages/agent/src/agents/agent-run.service.ts. Phases: load context → assemble prompt → resolve provider → enforce budget → AI call → handle response (file edits, task creates) → write summary → emit activity. Test: unit-test each phase with mocked facade. - T33. Extend
BaseFacadeService.resolvePluginto accept anagentIdhint that resolves viaagent.aiProviderId→ existing cascade. Default the call sites that don't passagentIdto current behavior. Test: facade unit tests get an additionalagentIdcase. - T34. Extend
BudgetGuardServiceto acceptownerType: 'work' | 'agent'. Reuses the polymorphic-owner SQL already inWorkBudgetRepository. AddAgentBudgetRepository.findByAgentIdandaggregateSpend(agentId, intervalStart). - T34a. [N6 override] Implement multi-interval aggregator in
BudgetService. New helpersgetCurrentPeriodStart(intervalUnit, intervalAnchor, now)andgetNextPeriodStart(intervalUnit, intervalAnchor, now)handling'hour' | 'day' | 'week' | 'month' | 'unlimited'.'month'keeps the existing calendar-month-UTC semantics;'hour' | 'day' | 'week'roll forward fromintervalAnchor(so an Agent created at 09:42 UTC withintervalUnit = 'hour'resets at 10:42, 11:42, …);'unlimited'returns sentinel never-reset. Aggregator queriesplugin_usage_events WHERE agentId = ? AND occurredAt >= periodStart. Test: per-interval-unit aggregation correctness on synthetic event series. - T35. Wire
AgentRunServiceinto the internal RPC channel — add it to thecreateRemoteProxy(client, 'AgentRunService')proxy table inapps/api/src/trigger/trigger-internal.controller.ts. - T36. Add
POST /agents/:id/run-nowcontroller action. Validates the agent isactive(ordraftand user opted in), inserts anagent_runsrow, callsruns.trigger. Returns the runId. Rate-limit 5 RPM/user. - T37. Add
POST /agents/:id/runs/:runId/cancel→ callsruns.cancel(triggerRunId)(same ascancel work generationflow). Writesagent_runs.status='cancelled'. - T38. Playwright test: create active agent with
manualheartbeat → press "Run heartbeat now" → poll untilagent_runsrow reachescompleted. - T39. Add
pauseAfterFailuresauto-pause: aftererrorCount >= pauseAfterFailures, status →errorandAGENT_PAUSEDactivity row emitted. - T40. Add budget-block path: when
BudgetGuardServicereturns block, setagent_runs.errorMessage='Budget exceeded', status='failed', emitAGENT_BUDGET_EXCEEDED.
Phase 4 — Dashboards, surfaces
- T41. Build
/agents/[id]/dashboardpage. Components:LiveStatusCard.tsx— current status + in-flight run row + cancel button.RunActivityChart.tsx— 30-day bar chart of run counts. Reuse Recharts (already a dep — checkpackage.json); if not present, follow data-management spec for chart library decision.TasksByPriorityChart.tsx— stacked column.RecentTasksList.tsx— 5 rows.CostSnapshotCard.tsx— current-interval spend, headroom, reset time.
- T42. Build
/agents/[id]/activitypage — reuseActivityFeedClient.tsxwith afilter={agentId}prop addition. - T43. Build
/agents/[id]/budgetspage. Form: intervalUnit dropdown, capCents number input, overage toggle, save button. Histogram of last 30 days fromplugin_usage_events. - T44. Build
/agents/[id]/settingspage. Forms: provider+model pickers, cadence (cron or "manual" radio),pauseAfterFailuresnumber, permissions toggle grid (8 toggles), "Archive Agent" with typed confirmation. - T45. Build the create-Agent page
/agents/newreusing form primitives from Work creation. - T46. Build the list page Cards + Table views. Default: Cards. Toggle stored in
localStorageasagents-view-mode. Filter chips: All/Active/Paused/Error. Scope filter dropdown. - T47. Add per-target tabs:
- Patch
apps/web/src/components/works/detail/WorkTabs.tsx— add "Agents", "Skills", "Tasks" (order: after Plugins, before Deploy). - Patch the Mission detail tab strip (path in the missions-ideas-works PR landing on develop) — add the same three.
- Patch the Idea detail tab strip — add "Agents", "Tasks".
- Patch
- T48. Build the per-target Agents tab listing (works/missions/ideas) — minor variant of
/agentslist filtered by scope+target. - T49. Dashboard tiles:
apps/web/src/components/dashboard/AgentsCountTile.tsx— count ofstatus='active'agents.apps/web/src/components/dashboard/TasksInProgressTile.tsx— counts.- Add to the tile row in the existing dashboard layout (additive).
- T50. Recent Tasks list block on the main dashboard page — below the existing "Recent Works" block.
Phase 5 — Task-driven runtime
Depends on task-tracking Phase 1 (
taskstable exists).
- T51. Create
packages/tasks/src/tasks/trigger/agent-task-execute.task.ts(one-shot,maxDuration: 60 * 60). CallsAgentRunService.execute({kind: 'task', taskId}). - T52. Create
packages/tasks/src/tasks/trigger/agent-chat-reply.task.ts(one-shot,maxDuration: 5 * 60). CallsAgentRunService.execute({kind: 'chat', chatMessageId}). - T53. Tool:
createTask— exposed via the existing tool-loop helper (agent-pipeline plugin pattern). Validatespermissions.canAssignTasks. Returns{taskId}or a structured error. - T54. Tool:
commentOnTask— validates the agent is assignee/reviewer/approver. Returns{messageId}. - T55. Tool:
editAgentFile— validates path under own subtree +permissions.canEditAgentFiles. Routes throughAgentFileService. - T56. Tool:
commitToRepo— validatespermissions.canCommitToRepo. Routes throughGitFacadeService.commit(). - T57. Tool:
createSubAgent— validatespermissions.canCreateAgents+ scope cascade. - T58. Add
agent-task-executedispatch hook ontasksstatus transitions: when a Task moves toin_progressand an assignee is an Agent, dispatch. - T59. Add
agent-chat-replydispatch hook ontask_chat_messagesinsert: when the body matches@<agent-slug>and the agent is on the task, dispatch. - T60. Playwright e2e: human posts
@ceo plan this→ CEO Agent's reply lands within 30 s.
Phase 6 — Mission Template integration
- T61. Extend the Mission scaffolder (location landed on develop with PR JJ) to also copy
.works/agents/and.works/skills/from the template repo into the new<slug>-missionrepo viaGitFacadeService. - T62. Insert matching
agents+skillsrows (status=draft) using the template's.works/mission.ymlagents/skillsarrays. - T63. Playwright e2e: instantiate a Mission Template that declares 2 agents → 2
draftagents appear in/missions/[id]/agents; their MD files are present in the new mission repo. - T64. Add a sample Mission Template (e.g.
ever-works/p2p-marketplace-mission-template) with a CEO + VP-Engineering agent under.works/agents/and apr-reviewskill under.works/skills/. Smoke-test instantiation.
Phase 6a — Single-Agent export + import [N5 operator override]
The bulk account-transfer flow lives in Phase 7. This phase adds a per-Agent quick export/import for sharing one Agent at a time without the GitHub-sync overhead.
- T64a. DTO
AgentExportEnvelopeinapps/api/src/agents/dto/agent-export.dto.ts— fields perfeatures/agents/spec.md §5.11. Includes optional inline base64 image bytes if avatar mode =image. - T64b.
AgentExportService.exportOne(agentId): AgentExportEnvelope— assembles the envelope. Inlines image bytes via the existing KB upload repository. - T64c. Controller route
GET /agents/:id/exportreturning the envelope (JSON body,Content-Disposition: attachment; filename="agent-<slug>.json"for browser download). - T64d.
AgentImportService.importOne(envelope, options): Agent— validates against the Zod schema fromagent-yml-manifest-schema.md; resolves conflict on(userId, scope, slug)per?onConflict=skip|overwrite|rename(defaultrename). Inline image bytes round-trip via existing KB upload pipeline. - T64e. Controller route
POST /agents/import?scope=...&missionId=...&onConflict=...acceptingAgentExportEnvelopebody. Returns the created Agent. - T64f. UI: "Export" button on Agent detail page header → triggers download. "Import Agent" CTA on
/agentslist page → file picker → preview modal → confirm-and-create. Conflict-resolution radio in the modal. - T64g. Activity events
AGENT_EXPORTED,AGENT_IMPORTED. - T64h. Playwright e2e: export an Agent with image avatar → re-import as
agent-2→ verify byte-equality of MD files and re-upload of image.
Phase 7 — Account-transfer (Export / Import / GitHub Sync) extension
Per ADR-008 §"v1 REQUIREMENT — extend existing Import / Export / Sync surfaces". Tenant-scoped Agents must round-trip through the existing
packages/agent/src/account-transfer/flow so users on the SaaS can already back up / migrate / Git-sync their Agents in v1, ahead of the dedicated tenant-control-repo feature in v2.
- T70. Extend
packages/agent/src/account-transfer/types.tswithExportedAgent(id, slug, scope, name, title, capabilities, aiProviderId, modelId, permissions, heartbeatCadence, MD-files inline body,agentBudgetnested,memberships). Tenant-scoped agents only (Mission/Idea/Work-scoped agents live in their owning repos already). - T71. Inject
AgentRepository/AgentBudgetRepository/AgentMembershipRepositoryintoAccountExportServiceconstructor. - T72. Implement
AccountExportService.exportAgents(userId, options)returningExportedAgent[]. Apply the existingmaskSecretSettingsposture to any secret-bearing metadata. - T73. Add
agents: ExportedAgent[]toAccountExportPayload. Bump payload version (version: 2) per the existing versioning posture. - T74. Implement
AccountImportServiceagents handler — create-or-update by(userId, scope, slug)UNIQUE key. Honor the existing conflict-resolution UI (skip / overwrite / merge). - T75. Update
GitHubSyncServicesynced layout: write tenant agents toagents/<slug>/agent.yml+ the 5 MD files +agent.ymlinside theever-works-configrepo. Reads pull them back. - T76. Add UI affordance on
/settings/import-exportpage: "Include Agents in export" checkbox (default ON for export, default ON for sync). Same shape as existing "Include works" toggles. - T77. Activity-log events
AGENT_EXPORTED,AGENT_IMPORTED,AGENT_SYNCEDemitted via the existing event chain. - T78. Round-trip Playwright test: create tenant Agent → export → reset DB → import → verify Agent state restored byte-for-byte (sans secrets).
Phase 8 — Default-on rollout
- T65. Wire
FEATURE_AGENTSenv flag. When off, the sidebar items + tabs are hidden. When on, full surface visible. - T66. Verify the new migrations apply cleanly on a staging DB snapshot.
- T67. Beta-test with internal users for ≥3 days; gather budget-spike incidents and runaway-loop reports.
- T68. Flip
FEATURE_AGENTSdefault totrue. - T69. Update
built-in-plugins.mdreference list (no new plugins, but mention the reservedtask-trackerinterface).
Definition of Done
- All Phase 1-6 task checkboxes ticked.
-
pnpm testgreen acrossapps/api,packages/agent,packages/tasks,packages/plugin,apps/web. -
pnpm lint+pnpm type-checkgreen. - No
synchronize: trueintroduced anywhere. - Migration applied + reversible on staging.
- Constitution checks in spec.md §9 confirmed.
- PR review-loop clean (CodeRabbit / Codex / Sonar / Snyk / Vercel Agent Review per workspace NN #14 + #18).
- Architecture doc
agents-skills-tasks.mdstatus flipped fromDrafttoActive.