- Agent provides a directory to deploy.
- Support start/stop deployment actions.
- Keep Vercel-like semantics, but simpler.
- Every deployment run uses a brand new sandbox.
Using repoUrl/branch is unnecessary in this product. The deploy unit is the current filesystem content prepared by the agent.
So the system should deploy from a directory snapshot, not from git.
export type DeploymentTarget = 'preview' | 'production'
export type DeploymentSpec = {
id: string
agentId: string
name: string
sourceDir: string // absolute path inside source agent sandbox, e.g. /config/miniapps/my-app
installCommand: string // optional, default: ""
buildCommand: string // required for most apps
startCommand: string // required
runtimePort: number // default: 3000
env: Record<string, string>
targetDefault: DeploymentTarget
createdAt: number
updatedAt: number
}export type SourceSnapshot = {
id: string
agentId: string
specId: string
sourceDir: string
artifactPath: string // host path, content-addressed tarball
contentHash: string // sha256 of file tree content
fileCount: number
sizeBytes: number
createdAt: number
}export type DeploymentStatus =
| 'queued'
| 'capturing'
| 'provisioning'
| 'building'
| 'starting'
| 'ready'
| 'failed'
| 'stopping'
| 'stopped'
export type DeploymentRun = {
id: string
agentId: string
specId: string
specSnapshot: DeploymentSpec
snapshotId: string
sandboxId: string
status: DeploymentStatus
target: DeploymentTarget
url: string | null
createdAt: number
updatedAt: number
stoppedAt?: number
error?: string
}startMUST create a newDeploymentRunand newsandboxId.- No in-place restart for a run.
stoponly stops one run.- A run always references an immutable
snapshotId.
Input: sourceDir from spec.
- Validate
sourceDirexists in source agent sandbox. - Create a tarball snapshot from
sourceDir. - Save tarball to host artifact store.
- Compute
contentHash. - Create
SourceSnapshotrecord.
- Create a new deployment sandbox (never reused).
- Copy/extract snapshot artifact into sandbox work dir (e.g.
/workspace/app).
- Run install/build/start commands in order.
- On success, expose run URL and mark
ready. - On failure, mark
failedand persist logs.
- Stop target run sandbox.
- Mark run
stopped.
The system still does "copy out then copy in", but through a first-class snapshot artifact layer.
Benefits:
- Reproducible runs (each run tied to exact snapshot).
- Auditable (
contentHash, file count, snapshot time). - Easy future rollback (redeploy older snapshot to new sandbox).
- Better UX for run history.
Artifact store:
- Host path:
data/deployments/artifacts/<agentId>/<contentHash>.tar.zst - Metadata store tracks
snapshotId -> contentHash -> artifactPath.
Capture strategy:
- Fast path: if
sourceDiris backed by a known host mount, package directly on host. - Fallback path: create archive inside source sandbox, write to shared staging mount, then move to artifact store.
- Both paths produce the same
contentHashandSourceSnapshot.
Suggested ignore defaults while capturing:
.git/node_modules/.next/cache/dist/build/*.log
Safety and scale guards:
- Max snapshot size (v1):
1 GiBcompressed. - Max file count (v1):
100,000. - Reject symlinks escaping source root.
- Per-agent deploy concurrency: 1 active start pipeline at a time.
GET /api/agents/:id/deployments/spec
- Returns current deployment spec.
PUT /api/agents/:id/deployments/spec
- Upserts spec.
- Required:
name,sourceDir,buildCommand,startCommand.
GET /api/agents/:id/deployments
- List runs (newest first).
POST /api/agents/:id/deployments/start
- Body:
{
"target": "preview",
"note": "optional message"
}- Behavior:
- load spec,
- capture source snapshot,
- create run,
- provision fresh sandbox,
- build/start.
POST /api/agents/:id/deployments/:runId/stop
- Stop one run.
GET /api/agents/:id/deployments/:runId/logs
- Get logs for details panel.
GET /api/agents/:id/deployments/snapshots
- Optional in v1.1; useful for debugging and future rollback UX.
sourceDirmust be absolute sandbox path.sourceDirmust not contain path traversal.sourceDirmust be under allowed roots (for safety), for example:/config/miniapps/config/memory/projects
startCommandrequired.buildCommandrequired (can be"true"for static/no-build apps).runtimePortmust be in safe range (1024-65535).
queued -> capturing -> provisioning -> building -> starting -> ready
queued -> capturing -> provisioning -> building -> failed
queued -> capturing -> failed
ready -> stopping -> stopped
failed -> stopping -> stopped
- Add
Deploymentstab to agent profile modal. - Tabs:
Profile,Deployments,Computer.
- Spec Header
- Spec status chip (
Configured/Missing). Edit specaction.Start deploymentprimary action.
- Runs List (left on desktop, top on mobile)
- Run status, target, created time.
- Snapshot hash short id.
- Sandbox short id.
- Run Details (right on desktop, bottom on mobile)
- URL (when ready).
- Commands used (from spec snapshot).
- Live logs.
Stopbutton for active runs.
- Name
- Source directory (required)
- Install command
- Build command
- Start command
- Runtime port
- Target default (
preview/production) - Env vars key/value
Footer:
Save specSave and deploy
┌────────────────────────────────────────────────────────────────────┐
│ Spec: Configured (/config/miniapps/foo) [Edit spec] [Start] │
├───────────────────────────────┬────────────────────────────────────┤
│ Runs │ Run details │
│ [ready] preview 2m │ Status: ready │
│ snapshot: sha_7a12 │ URL: https://... │
│ sandbox: sbx_92f1 │ Snapshot: sha_7a12 │
│ │ Sandbox: sbx_92f1 │
│ [building] production 20s │ Logs │
│ snapshot: sha_b3d4 │ > capturing source... │
│ sandbox: sbx_ab18 │ > provisioning sandbox... │
│ │ > pnpm build │
│ │ │
│ │ [Stop] │
└───────────────────────────────┴────────────────────────────────────┘
Add websocket events:
deployment:run:newdeployment:run:updatedeployment:log:appenddeployment:snapshot:created(optional)
- One spec per agent.
- Start/stop only.
- No rollback UI yet.
- No custom domains.
- Always new sandbox per run.
- Deploy source is always a directory path.
- "Redeploy this snapshot" button.
- Diff between two snapshots.
- Auto-detect commands (
npm,pnpm, static build). - Promote preview run to production alias.