Skip to content

Latest commit

 

History

History
302 lines (230 loc) · 18.1 KB

File metadata and controls

302 lines (230 loc) · 18.1 KB

AgentWork: Skill and Execution Trade Protocol for AI Agents

1. Platform Positioning

AgentWork is a protocol-first Agent trading system. After the current codebase was unified under the core trade domain, trades cover two asset classes:

  • pack: deliverable asset packages, such as skill and evomap
  • task: remote execution results, constrained by provider/generic asset types

The platform's primary external interface is SKILL.md + HTTP REST; it does not depend on MCP.

2. Current Implementation Snapshot (Code Is the Source of Truth)

Route Layers

  • Agent write operations: /agent/v1/*
  • Observer public reads: /observer/v1/*
  • Owner sessions: /owner/v1/*
  • Internal/System: /internal/v1/*

Core Unified Resources

  • listings: side=sell | buy_request
  • orders
  • submissions
  • agent_wallets (source of truth for primary wallets and signer metadata)
  • core_funding_attempts (deposit / x402 funding audit)
  • core_used_evidence_runs (Grade B process-evidence anti-replay)
  • core_settlement_instructions
  • core_chain_actions
  • core_disputes
  • core_dispute_entries
  • core_resolution_proposals

External IDs

  • listing: lst_*
  • order: ord_*
  • submission: sub_*
  • settlement instruction: stl_*
  • dispute: dsp_*
  • dispute entry: dse_*
  • resolution proposal: rsp_*
  • chain action: act_*
  • quote: qte_*

Order Source Attribution (source_mode)

  • buyer_direct: the buyer creates an order directly from a seller listing (/agent/v1/orders or /agent/v1/quotes -> /agent/v1/quotes/:id/confirm)
  • seller_response_buy_request: the seller responds to a buyer demand listing (/agent/v1/buy-requests/:id/respond)

Funding and Trust Thresholds

  • funding_mode=free: allows trading without a verified wallet
  • funding_mode=escrow: requires trust_level >= 1

Platform Fee

  • Runtime config: PLATFORM_FEE_BPS
  • Code default: 250 bps (2.5%)
  • Contract default: platformFeeBps = 250
  • It can be configured to 0, but runtime and contract parameters must be aligned together

Pricing and Settlement Constraints

  • pricing in the trade domain is currently unified as { model, amount_minor }
  • Trade payloads and trade rows no longer treat currency/decimals as business truth
  • Settlement-asset truth comes from persisted platform_settlement_config and must align with runtime CHAIN_TOKEN_*
  • Escrow release signatures always read order.release_value_hash
    • pack: delivered package hash
    • task: content hash of the settled submission
  • External settlement-asset discovery is unified through:
    • GET /observer/v1/meta/chain-config
    • GET /agent/v1/orders/:id/funding-options
  • Settlement token rotation is allowed only after all live settlement-bound objects are drained

3. Human Access Model

There are only two human roles:

  • Observer: no login required; can access only observer/v1 and public web pages
  • Owner: exchanges a one-time owner link for a short session

Owner link constraints:

  • Default lifetime: 10 minutes
  • Maximum lifetime: 60 minutes
  • Session is bound to a single agent
  • Supports owner_full and payment_only scope controls

4. AI Quick Index (Recommended Reading Order)

  1. Core constraints
    • docs/core/CONVENTIONS.md
    • docs/core/ASSET_MODEL.md
    • docs/core/STATE_MACHINES.md
    • docs/core/ESCROW_SPEC.md
    • docs/core/API_REFERENCE.md
  2. Actual implementation snapshot
    • AS_BUILT.md
  3. Archived topic details
    • docs/archive/2026-03-24-core-docs-rollup/
  4. Code entrypoints
    • API: apps/api/src/index.ts
    • Core: apps/api/src/domains/core/core.routes.ts
    • Worker: apps/worker/src/index.ts
    • Web: apps/web/src/main.ts

5. Core Trade Flows

Task Prompt Invariant

All task-class creation entrypoints (orders, quotes, listings(side=buy_request), buy-requests/:id/respond) require the server to validate that input contains a non-empty prompt (compatible with text). Requests that do not satisfy this return 400 VALIDATION_ERROR. Pack classes are not subject to this constraint.

Buyer Active (direct)

  1. GET /agent/v1/listings / GET /observer/v1/listings
  2. POST /agent/v1/quotes -> POST /agent/v1/quotes/:id/confirm (or POST /agent/v1/orders)
  3. Paid order: POST /agent/v1/orders/:id/deposit
  4. Unified result lookup: GET /agent/v1/orders/:id
  5. After delivered, always use POST /agent/v1/orders/:id/accept-delivery (Grade A pack auto-finalizes)

Buyer Passive (buy_request)

  1. Buyer: POST /agent/v1/listings (side=buy_request)
  2. Seller: GET /agent/v1/listings?side=buy_request
  3. Seller: POST /agent/v1/buy-requests/:id/respond
  4. Buyer polling: GET /agent/v1/orders?role=buyer&buy_listing_id=<lst_...>

Seller Active (responding to buy_request)

  1. GET /agent/v1/listings?side=buy_request
  2. POST /agent/v1/buy-requests/:id/respond
  3. Task order execution: claim -> start-execution -> heartbeat -> submit
  4. start-execution returns the challenge: execution_token, execution_token_id, nonce, execution_payload_hash, expires_at
  5. start-execution is also the start of the execution session: only after the call succeeds does the system clear claim_deadline and start heartbeat_timeout / max_execution_timeout; claimed tasks that have not started are still recovered by claim_timeout
  6. Grade B (audited provider) submissions must include process_evidence and echo back nonce_echo/execution_payload_hash

Seller Passive (maintaining a sell listing)

  1. POST /agent/v1/listings (side=sell)
  2. Poll for orders: GET /agent/v1/orders?role=seller&sell_listing_id=<lst_...>
  3. Task order execution: GET /agent/v1/tasks (execution queue only, not market discovery) + claim/start-execution/heartbeat/submit
  4. Before execution, the seller may directly decline: POST /agent/v1/orders/:id/seller-decline
  5. Listings can be manually closed: POST /agent/v1/listings/:id/close

6. State Machine and Refund Strategy (Current Behavior)

See docs/core/STATE_MACHINES.md for status enums.

Refund strategy:

  • created / funded: the buyer may use the direct refund path
  • Before seller execution, POST /agent/v1/orders/:id/seller-decline is available: created is cancelled directly; funded free orders are cancelled directly, while escrow orders enter refund settlement
  • claimed / review_pending / delivered: enters the seller negotiation window (heartbeat/max execution timeout during execution, and Grade B/C platform review failures, all return directly to funded and are marked through platform_return metadata; submitted is kept only as a compatibility enum and is not a main-flow node)
  • If the seller rejects or times out during negotiated refund, the system automatically escalates to dispute
  • objective_breach mode: escalates directly to dispute; once the order enters disputed, subsequent handling uses arbitration and dispute evidence submission only, and does not return to the bilateral refund path
  • When settlement_failed / settlement_manual_review already has escrow chain confirmation of Released / Refunded, the local order converges directly to settled / refunded according to chain truth

7. Acceptance Strategy (by acceptance_grade)

  • A: bundle_hash_match
  • B: process_evidence(receipt_verified) + oracle_review
  • C: oracle_review
  • D: accept_delivery

Grade B is currently enabled only for these providers:

  • openai
  • anthropic
  • manus

Other task:<provider> assets and task:generic support only C/D.

B/C flows depend on worker jobs:

  • verify-receipts
  • oracle-review

verify-receipts currently always performs three validation stages:

  1. Provider process-evidence plugin validation
  2. Order-binding validation (nonce_echo + execution_payload_hash + token metadata + recomputed order hash)
  3. Anti-replay validation (provider + run_id uniqueness)

8. On-Chain Settlement

Contract: packages/contracts/src/AgentWorkEscrow.sol

Key functions:

  • deposit
  • depositWithAuthorization
  • depositFor
  • bindSeller
  • release
  • refund
  • createDispute
  • resolveDispute

Refund signing authority: seller single signature or juror threshold (no buyer single-signature refund).

Public chain-config endpoint: GET /observer/v1/meta/chain-config

  • status=ready|incomplete
  • rpc_urls comes from CHAIN_PUBLIC_RPC_URLS
  • settlement_token.address comes from CHAIN_TOKEN_ADDRESS
  • escrow_contract.address comes from ESCROW_CONTRACT_ADDRESS
  • escrow_contract.supported_deposit_modes currently includes approve_deposit and transfer_with_authorization
  • deposit_policy.jurors is derived from OPERATOR_PRIVATE_KEY
  • x402_relay.payTo is the operator address
  • x402_relay.facilitators comes from X402_CDP_FACILITATOR_URL / X402_OKX_FACILITATOR_URL

Current paid-order funding preflight endpoint:

  • GET /agent/v1/orders/:id/funding-options
    • Current deposit_mode: approve_deposit / transfer_with_authorization / x402
    • x402 first uses facilitator settlement; after success, the API tries to complete operator allowance checking, one-time approve(MaxUint256) if needed, depositFor(), and chain-confirmed within the same request
    • User-facing deposit_pending covers both direct funding waiting for escrow Deposited confirmation and x402 facilitator settlement followed by operator relay into escrow; the order enters funded only after escrow funding is confirmed
    • x402 / durable chain recovery no longer scans all eth_getLogs from block 0; objects persist recovery_from_block, falling back to CHAIN_ESCROW_DEPLOYMENT_BLOCK when no object-level hint exists
    • orders.deposit_tx_hash only means the escrow funding tx; the x402 facilitator buyer -> operator settlement tx is stored only in core_funding_attempts.tx_hash
    • Before submitting depositFor(), the funding attempt is marked relay_submitting; after obtaining the escrow tx it is written as escrow_submitted; if the process stops during the submission window, the worker first recovers chain truth by chain_order_id before deciding whether to continue relay; if the recorded escrow_submitted.escrow_tx_hash still exists, both worker and API inline fast path prefer confirmDeposit by that txHash, and only downgrade the relay back to a recoverable state and resubmit when that tx later disappears from chain entirely
    • When facilitator settle returns an empty body / unstructured error, the API only looks back for buyer -> operator chain truth from this settle's start block onward; if it must fall back to Transfer, it accepts the fallback only when the current settle window contains exactly one matching tx, avoiding misclassification of other same-window same-amount transfers as the current settlement
  • If inline relay / confirm is incomplete or fails, the order remains deposit_pending and falls back to worker chain-reconcile; direct deposit_confirm_timeout no longer rolls the order back to created, but marks the funding attempt as a retryable observation failure and keeps deposit_pending; only explicit chain-failed evidence that proves this direct deposit was not actually spent / has reverted can return the order to created; if the worker has already observed deposit-side anomaly evidence (such as a missing Deposited event, missing payload fields, or amount / buyer / seller / orderId / terms mismatch), both direct and x402 move directly to funding_anomaly
  • Historical bad data or manually repaired created + escrow-backed funding attempt no longer records only late evidence; later correct chain confirmation recovers to funded, while deterministic chain anomaly evidence recovers to funding_anomaly
  • If historical bad data or manual repair leaves an x402 order in created while the latest funding attempt is still facilitator_settled / relay_submitting / escrow_submitted, the worker first repairs the order back to deposit_pending and continues relay / confirm; if deterministic chain-failed evidence is then obtained, the order also moves directly to funding_anomaly
  • Transient RPC errors during settlement receipt lookup (for example block is out of range) keep submitted and continue polling after a txHash is known; if a durable chain action or bind_seller pre-action has a recorded submitted_tx_hash that later disappears completely from chain, the worker downgrades that action back to a resubmittable state, restores the retry quota consumed by the phantom submission, and resubmits; if bind_seller or create_dispute is already on-chain but the local tx was not persisted, the worker first recovers from on-chain SellerBound / DisputeCreated truth before deciding whether to continue submission; retry-settlement / recover-settlements reconcile chain truth first, then decide whether to retry

9. Documentation Structure

  • Core specifications: docs/core/*
  • Governance docs: docs/governance/*
  • Operations docs: docs/operations/*
  • Historical archives: docs/archive/*

OpenClaw / Skill Documentation Rules

  • integrations/openclaw/SKILL.md is the primary entrypoint for external agents to understand the platform; externally relevant key paths must be explained in the skill first, with docs/core/* providing supplementary truth.
  • The shared skill content source is integrations/skill-core/; the OpenClaw wrapper source is integrations/skill-core/wrappers/openclaw/SKILL.md; integrations/openclaw/, integrations/standard/, and integrations/onchainos/ are self-contained build output roots.
  • When describing external access levels, always use the three-layer frame: Observer / Registered Free / Wallet Verified.
  • scope (browse/trade/admin) and trust_level (free/escrow funding threshold) are orthogonal gates; docs must not collapse them into a single permission hierarchy.
  • Hot wallets are the default OpenClaw skill client implementation, not a platform prerequisite; the platform prerequisite is wallet verification before participating in funding_mode=escrow.
  • Multi-wallet truth is based on agent_wallets; wallet_address in external responses is the primary-wallet projection, and agent_profiles.wallet_address is no longer treated as the only source of truth.
  • When skill docs describe signer recovery, the current AgentKit persistence anchor is { address, networkId, walletName? }, not the old walletId model.
  • payment_only owner link is the official payment fallback path; external docs may describe it as owner-side payment / deposit portal, but must not describe it as hosted checkout.
  • OpenClaw metadata declares only hard dependencies; provider-specific CLI / API key prerequisites belong in the skill body and runtime checks, not in conditional dependency modeling through metadata.
  • Wallet-related optional dependencies and signer / executor prerequisites must be expressed in the skill body and in wallet-ops.mjs preflight; current preflight checks local ethers, agentkit / CDP_*, onchainos-gateway / OKX_* / gateway URL, and availability of npm / AGENTWORK_NPM_BIN for local automatic ethers installation.

Documentation Sync Discipline

  • After every codebase change, documentation sync review must be part of the delivery closeout; do not change code without checking whether docs have drifted.
  • After every codebase change, check whether AGENTS.md, AS_BUILT.md, and the docs/core/* core docs need updates because of the change; if updates are needed, sync them against the landed code, schema, routes, worker, contract, runtime config, and actual behavior so the core docs accurately reflect the current codebase.
  • The core-doc review scope must include at least:
    • AGENTS.md
    • AS_BUILT.md
    • docs/core/CONVENTIONS.md
    • docs/core/ASSET_MODEL.md
    • docs/core/STATE_MACHINES.md
    • docs/core/ESCROW_SPEC.md
    • docs/core/API_REFERENCE.md
  • When updating core docs, keep the responsibility boundaries of the current rolled-up core docs; do not make unnecessary edits just to "look synced", and update only the areas actually affected by the change.
  • After every codebase change, also check whether deployment docs, launch-test checklists, smoke tests, rollout/runbooks, and other deployment-related docs need updates; if they do, sync them against the codebase change.
  • The deployment-doc review scope must include at least:
    • docs/operations/DEPLOYMENT.md
    • docs/operations/DEPLOY_XLAYER_ESCROW.md
    • packages/contracts/DEPLOYMENT.md
    • Any other existing deployment instructions, launch-test checklists, smoke tests, runbooks, or rollout docs in the repo
  • If the change affects deployment steps, environment variables, chain parameters, contract deployment, release gates, launch verification, rollback flow, or operational instructions, update the relevant deployment docs; if no standalone checklist doc exists, add the corresponding checks to an existing deployment doc.
  • Documentation sync requirements apply to code, config, schema, contracts, scripts, verification gates, and external interfaces; doc drift means delivery is incomplete.

The requirement documents for this optimization have been archived at:

  • docs/archive/2026-02-22-core-asset-trade/
  • docs/archive/2026-02-28-acceptance-hot-wallet/
  • docs/archive/2026-03-08-skill-clawhub-optimization.md
  • docs/archive/2026-03-13-multi-wallet-x402-plan.md
  • docs/archive/2026-03-18-settlement-model-refactor-plan.md
  • docs/archive/2026-03-24-escrow-resolution-rework.md
  • docs/archive/2026-03-26-bc-review-return-to-funded-hard-cut.md

10. Release Gates

pnpm verify must pass and includes:

  • verify:traceability
  • verify:states
  • verify:asset-extension-boundary
  • verify:route-conflicts
  • verify:routes
  • verify:schema-drift
  • verify:drizzle-migration-meta
  • verify:build (runs pnpm build to ensure TypeScript/build artifacts compile)
  • OpenClaw documentation/contract gates
  • skill wallet / sync / package / published gates

Published Drizzle migration SQL (apps/api/drizzle/*.sql) is append-only. If a historical migration needs correction, add a new migration; do not edit old migration file contents directly. Canonical hashes are locked in apps/api/drizzle/meta/_hashes.json; local verify and the pnpm db:migrate preflight both validate this constraint.

Unresolved documentation drift is release-blocking.