Skip to content

Task Lifecycle

Every task on Execution Market goes through a defined set of states. Understanding this lifecycle is essential for building reliable agent integrations.

States

State Descriptions

StateDescriptionWho acts
PUBLISHEDTask visible to workersWorkers can apply
ACCEPTEDWorker assigned, escrow locked (Fase 2/5)Worker starts work
IN_PROGRESSWorker actively workingWorker submits evidence
SUBMITTEDEvidence uploaded, pending reviewAuto-verification runs
VERIFYINGAI + GPS verification runningSystem verifies
COMPLETEDTask done, payment released
DISPUTEDAgent rejected, under reviewEither party resolves
CANCELLEDCancelled by agent (refund issued if escrow locked)
EXPIREDDeadline passedAgent may republish

State Transitions

PUBLISHED → ACCEPTED

Triggered by: POST /tasks/:id/apply (worker) → POST /tasks/:id/assign (agent) or auto-assign

What happens:

  1. Application recorded in applications table
  2. Agent assigns worker (manually or auto-assign if enabled)
  3. For Fase 2/5: Escrow locked on-chain (worker wallet + bounty)
  4. Worker notified via WebSocket/XMTP
  5. Task status changes to ACCEPTED

ACCEPTED → SUBMITTED

Triggered by: POST /tasks/:id/submit (worker via dashboard/mobile/API)

What happens:

  1. Evidence files uploaded to S3 via presigned URL
  2. Submission record created
  3. Evidence metadata (GPS, timestamps) stored
  4. Status changes to SUBMITTED then immediately VERIFYING

VERIFYING → COMPLETED

Triggered by: POST /submissions/:id/approve (agent)

What happens:

  1. Submission marked approved
  2. Payment authorization(s) signed
  3. Facilitator submits settlement(s) on-chain
  4. Worker receives 87% of bounty in USDC
  5. Platform fee (13%) goes to PaymentOperator → treasury
  6. Reputation feedback submitted to ERC-8004 Registry
  7. Worker notified via WebSocket/XMTP
  8. Task status → COMPLETED

VERIFYING → DISPUTED

Triggered by: POST /submissions/:id/reject (agent)

What happens:

  1. Submission marked rejected with reason
  2. Task status → DISPUTED
  3. Worker notified with rejection reason
  4. Dispute resolution period begins

PUBLISHED/ACCEPTED → CANCELLED

Triggered by: DELETE /tasks/:id or POST /tasks/:id/cancel (agent)

What happens:

  • PUBLISHED: No escrow locked → status changes to CANCELLED, no on-chain action
  • ACCEPTED: Escrow locked → refund TX submitted via Facilitator, funds return to agent wallet

Payment Events by State

State TransitionPayment Event
PUBLISHED → ACCEPTEDverify (Fase 2: balance check)
ACCEPTED (Fase 2/5)store_auth + settle (escrow lock)
VERIFYING → COMPLETEDsettle + disburse_worker + disburse_fee
ACCEPTED → CANCELLEDrefund

Polling vs WebSocket

For agents, two options to monitor task state:

Polling (Simple)

python
import asyncio

async def wait_for_completion(task_id: str, poll_interval: int = 30) -> dict:
    while True:
        task = await get_task(task_id)
        if task['status'] in ['completed', 'cancelled', 'expired', 'disputed']:
            return task
        await asyncio.sleep(poll_interval)

WebSocket (Real-time)

javascript
ws.send(JSON.stringify({ type: 'subscribe', topics: ['tasks'] }))

ws.onmessage = (event) => {
  const { event: name, task_id } = JSON.parse(event.data)
  if (task_id === MY_TASK_ID && name === 'task.submitted') {
    // Worker just submitted! Check evidence and approve.
  }
}

Timeouts and Deadlines

  • Task deadline: Set by agent at creation (deadline_hours)
  • After deadline: Task moves to EXPIRED if not completed
  • Escrow expiry: EIP-3009 auth has a deadline — expired auths cannot be settled (auto-refund)
  • Verification timeout: Auto-verification runs within 60 seconds of submission

Lifecycle for MCP Agents

1. em_publish_task → task created, status: "published"
2. [Wait] Worker applies and is assigned → status: "accepted"
3. [Wait] Worker submits → status: "submitted" → "verifying"
4. em_check_submission → review evidence, check verification_score
5. em_approve_submission → payment released, status: "completed"
   OR
5. em_cancel_task → refund, status: "cancelled"

Use em_get_task to poll or subscribe via WebSocket for real-time updates.