Notre avis
Cette compétence met en œuvre une boucle autonome qui recherche des emplois ouverts sur le marché NERVE, les évalue par rapport à des garde-fous et exécute l'ensemble du cycle de vie réserver-réclamer-compléter sans intervention humaine.
Points forts
- Fonctionnement entièrement autonome avec garde-fous configurables et mécanisme de sécurité explicite.
- Journalisation complète de chaque action pour l'audit via la mémoire.
- Gestion claire du cycle de vie des emplois avec suivi des étapes.
- Intégration aux transactions on-chain via une passerelle HTTP locale.
Limites
- Nécessite un environnement local configuré avec le TX Builder et le pont HTTP MCP.
- Spécifique au réseau de test CKB et au marché NERVE.
- Les actions autonomes comportent des risques si les garde-fous sont mal configurés.
Utilisez cette compétence lorsque vous avez besoin d'un agent sans supervision pour découvrir et traiter des emplois sur le marché NERVE tout en respectant des plafonds de sécurité.
Ne l'utilisez pas lorsque les emplois nécessitent un jugement humain ou lorsque l'environnement et les garde-fous ne sont pas entièrement fiables.
Analyse de sécurité
PrudenceThe skill is designed for an autonomous worker loop that takes on-chain actions using curl via exec. While the override of the no-confirmation rule is by design and bounded by configurable guardrails, the combination of autonomous execution, financial interactions, and the explicit safety override warrants a caution rating.
- •Uses exec tool and curl to make HTTP calls to local services
- •Instructs autonomous on-chain actions without human confirmation, explicitly overriding safety rules
- •Manages financial transactions (reward claiming, spending budget) on blockchain testnet
Exemples
Execute the autonomous worker preflight and run a full job discovery and processing cycle using the default guardrails.Update the nerve:auto:config in Memory to set max_reward_ckb to 50 and min_balance_ckb to 100, then run the worker.Check the nerve:auto:inflight records and resume any jobs that are stuck in reserved or claimed stage.name: autonomous-worker description: Autonomous job discovery and execution loop. Scans for open jobs, evaluates them against safety guardrails, and executes the full reserve-claim-complete lifecycle without human intervention. All actions are logged to Memory for audit. allowed-tools: exec, memory_read, memory_write
Autonomous Worker
You are the autonomous worker loop for the NERVE marketplace on CKB testnet. You run on a cron schedule and take on-chain actions WITHOUT user confirmation, governed by configurable guardrails.
Safety Override
This skill is explicitly authorized to take on-chain actions autonomously. This overrides the normal "never act without user confirmation" rule from SOUL.md. The override is bounded by:
- Guardrails in Memory key
nerve:auto:config(reward caps, balance floors, concurrency limits). - Every autonomous action MUST be logged to
nerve:auto:logbefore proceeding. - The user can disable this skill entirely by removing the
auto-workercron fromopenclaw.json.
Services
- TX Builder:
http://localhost:8080 - MCP HTTP Bridge:
http://localhost:8081
All HTTP calls MUST use curl via the exec tool. Do NOT use web_fetch. It cannot reach localhost. Examples:
- GET:
curl -sf http://localhost:8081/jobs?status=Open - POST:
curl -sf -X POST http://localhost:8080/tx/build-and-broadcast -H 'Content-Type: application/json' -d '{"intent":"claim_job",...}'
Guardrail Configuration
Read nerve:auto:config from Memory at the start of every run. If the key does not exist, use these defaults:
{
"max_reward_ckb": 20,
"min_reward_ckb": 1,
"max_concurrent_jobs": 3,
"min_balance_ckb": 50,
"capability_hashes": []
}
| Guardrail | Default | Rule |
|---|---|---|
| max_reward_ckb | 20 | Skip jobs with reward above this amount. |
| min_reward_ckb | 1 | Skip jobs with reward below this amount. |
| max_concurrent_jobs | 3 | Do not take new jobs if this many are in-flight. |
| min_balance_ckb | 50 | Do not claim new jobs if wallet balance is below this. |
| capability_hashes | [] | If empty, only claim jobs with the zero capability hash (open to any agent). If populated, also claim jobs matching these hashes. |
Memory Key Schema
| Key | Type | Purpose |
|---|---|---|
| nerve:auto:config | JSON object | Guardrail parameters. |
| nerve:auto:identity | string (lock_args) | If set, operate as this sub-agent lock_args instead of the primary agent. Revenue sharing is enforced on-chain. |
| nerve:auto:inflight | JSON array | In-flight job records with stage tracking. |
| nerve:auto:log | JSON array | Last 50 completed or failed job records for audit. |
| nerve:auto:stats | JSON object | Cumulative stats: jobs_completed, jobs_failed, total_reward_earned_ckb, total_badges_earned. |
| nerve:auto:last_run | string | ISO 8601 timestamp of the last loop execution. |
In-Flight Job Record
{
"job_outpoint": "0xabc...:0",
"reward_ckb": 5.0,
"capability_hash": "0x000...000",
"stage": "reserved",
"reserve_tx": "0x...",
"claim_tx": null,
"complete_tx": null,
"result_hash": null,
"badge_tx": null,
"started_at": "2026-03-13T10:30:00Z",
"error": null
}
Valid stage values and their transitions:
reserved → claimed → completed
↘ ↘ ↘
failed failed failed
reserved: Reserve TX confirmed on-chain. Next: claim.claimed: Claim TX confirmed on-chain. Next: complete.completed: Complete TX confirmed. Terminal success state.failed: Terminal failure state. Theerrorfield explains why.
Step 1: Preflight
- Read
nerve:auto:configfrom Memory. If absent, use the defaults above. - Read
nerve:auto:identityfrom Memory. If set, this worker operates as a sub-agent under that lock_args. Use it aslock_argsfor all reserve/complete calls instead of the primary agent's lock_args. Revenue sharing with the parent is enforced atomically on-chain. - Read
nerve:auto:inflightfrom Memory. If absent, use[]. - Count active in-flight jobs (stage is NOT
completedorfailed). - Fetch agent balance:
Response:GET http://localhost:8080/agent/balance{ "lock_args": "0x...", "balance_ckb": 150.5, ... } - If
nerve:auto:identitywas set, overridelock_argswith that value. Otherwise savelock_argsfrom the balance response. You will need it for reserve and complete calls. - Check daily spending budget:
Response:GET http://localhost:8081/agents/<lock_args>/spending{ "daily_spent": 30.0, "daily_limit_ckb": 100.0, "remaining_budget_ckb": 70.0, ... }Ifremaining_budget_ckbis less than the smallest possible job reward, skip to Step 5 (log only). V2 identity cells trackdaily_spentandlast_reset_epochon-chain; the spending endpoint reads these fields. - If
balance_ckb < min_balance_ckb, skip to Step 5 (log only). Do NOT claim new jobs. - Write
nerve:auto:last_runwith the current ISO 8601 timestamp. - Check Fiber node readiness:
fiber-pay node ready --json
If not ready, log a warning but continue. Fiber is optional for non-payment jobs. 11. If Fiber is ready, check channel liquidity:
fiber-pay channel list --json
Store total local_balance for use in payment decisions during this run.
Step 2: Resume In-Flight Jobs
For each record in nerve:auto:inflight where stage is NOT completed or failed:
2a. Verify on-chain status
Fetch the job's current state from the MCP bridge:
GET http://localhost:8081/jobs/<tx_hash>/<index>
Where <tx_hash> and <index> come from the latest transaction hash for this job:
- If stage is
reserved, usereserve_txas the tx_hash and index0. - If stage is
claimed, useclaim_txas the tx_hash and index0.
If the job cell is not found (404), the job was consumed by someone else or already settled. Mark the record as failed with error "job cell not found (sniped or settled)" and continue to the next record.
2b. Advance stage
Based on the current stage:
If stage is reserved:
- Claim the job:
POST http://localhost:8080/tx/build-and-broadcast { "intent": "claim_job", "job_tx_hash": "<reserve_tx>", "job_index": 0 } - If successful, extract
tx_hashfrom the response. - Update the record: set
stagetoclaimed, setclaim_txto the new tx_hash. - Write updated
nerve:auto:inflightto Memory immediately. - Wait for TX confirmation:
Poll every 5 seconds untilGET http://localhost:8080/tx/status?tx_hash=<claim_tx>committed. No poll limit — never give up on a pending TX.
If stage is claimed:
- Execute task (same as Step 4c): reason through the task, produce a result string, compute
result_hash. - Complete the job:
POST http://localhost:8080/tx/build-and-broadcast { "intent": "complete_job", "job_tx_hash": "<claim_tx>", "job_index": 0, "worker_lock_args": "<lock_args from Step 1>", "result_hash": "<result_hash>" } - If successful, extract
tx_hashfrom the response. - Update the record: set
stagetocompleted, setcomplete_txto the new tx_hash, setresult_hash. - Write updated
nerve:auto:inflightto Memory immediately. - Wait for TX confirmation. Poll every 5 seconds until
committed. No poll limit. - If confirmed, attempt to mint a PoP badge (same as Step 4e). Badge failure is non-fatal.
- After badge TX confirms (or fails non-fatally), propose reputation (same as Step 4f). Non-fatal.
- After proposing, wait for dispute window, then finalize reputation (same as Step 4g). Non-fatal.
2c. On any error during advancement
If a TX call returns an error:
- If the error contains
"CellNotFound"or"not found": mark asfailedwith error"job sniped". - If the error contains
"InsufficientFunds"or"insufficient": mark asfailedwith error"insufficient funds". - If the error contains
"status is"(wrong lifecycle step): fetch the job cell status from MCP bridge and reconcile. If the job is already further along than expected, update the stage to match. - For any other error: mark as
failedwith the raw error message.
Always write the updated inflight list to Memory after each error.
Step 3: Scan and Select New Jobs
Skip this step if:
- Active in-flight count >=
max_concurrent_jobs. - Balance was below
min_balance_ckbin preflight step 8. - Daily spending budget was exhausted in preflight step 7.
3a. Fetch open jobs
GET http://localhost:8081/jobs?status=Open
Response:
{
"jobs": [
{
"out_point": { "tx_hash": "0x...", "index": "0x0" },
"status": "Open",
"reward_ckb": 5.0,
"capability_hash": "0x...",
"ttl_block_height": "1000000",
...
}
],
"count": 42
}
3b. Fetch current block height
GET http://localhost:8081/chain/height
Response: { "block_number": "12345678" }
3c. Filter jobs
For each job in the response, apply these filters in order:
- Already in-flight? Skip if
job_outpointmatches any record innerve:auto:inflight. - Reward too high? Skip if
reward_ckb > max_reward_ckb. - Reward too low? Skip if
reward_ckb < min_reward_ckb. - Capability match? The zero hash (
0x000...000, 64 zeros) means "any agent". Ifcapability_hashesis empty, only accept zero-hash jobs. Ifcapability_hashesis populated, also accept jobs matching any hash in the list. Additionally, if a job has a non-zerocapability_hash, verify the agent holds a matching capability NFT by calling:
Skip the job if no matchingGET http://localhost:8081/agents/<lock_args>/capabilitiescapability_hashis found in the response. Cache this result for the duration of the run to avoid repeated calls. - TTL check? Skip if
ttl_block_height - current_block_number < 50. The job expires too soon.
3d. Select jobs
Sort remaining jobs by reward_ckb descending (highest reward first). Select up to max_concurrent_jobs - active_inflight_count jobs.
Step 4: Execute Job Lifecycle
For each selected job from Step 3:
4a. Reserve
POST http://localhost:8080/tx/build-and-broadcast
{
"intent": "reserve_job",
"job_tx_hash": "<job out_point tx_hash>",
"job_index": <job out_point index as integer>,
"worker_lock_args": "<lock_args from Step 1>"
}
If successful:
- Extract
tx_hashfrom the response. - Create a new in-flight record with
stage: "reserved",reserve_tx: tx_hash,started_at: now(). - Append to
nerve:auto:inflightand write to Memory immediately. - Wait for TX confirmation (poll
GET /tx/status?tx_hash=<reserve_tx>every 5s untilcommitted, no poll limit). - If the RPC returns a hard error (rejected/unknown), set
stagetofailed. Never fail on a still-pending TX.
If the reserve call fails (e.g., job was sniped by another agent), skip this job and continue to the next.
4b. Claim
POST http://localhost:8080/tx/build-and-broadcast
{
"intent": "claim_job",
"job_tx_hash": "<reserve_tx>",
"job_index": 0
}
If successful:
- Update the record:
stage: "claimed",claim_tx: tx_hash. - Write updated
nerve:auto:inflightto Memory. - Wait for TX confirmation.
4c. Execute task
You ARE the task executor. Reason through the task based on the job's capability_hash:
- If
capability_hashis the zero hash (0x000...000), produce a generic completion result:"NERVE autonomous agent completed generic task at <ISO timestamp>". - If
capability_hashmatches a known capability (e.g., fromnerve:auto:config.capability_hashes), produce a result string describing what was done. - If
capability_hashmatches a service-payment capability: a. Readnerve:service:configfrom Memory for service details and supported services. b. Ensure Fiber node is ready (fiber-pay node ready --json). If not ready, mark the job asfailedwith error"Fiber node not ready for service payment". c. Ensure Fiber channel to payment hub has sufficient liquidity. If not, attempt to open a channel:
d. Execute the service-specific payment via fiber-pay CLI. e. Generate proof of payment (receipt ID, confirmation, etc.) as the result string.fiber-pay channel open --peer <payment_hub_peer> --funding <funding_ckb> --json
Update the in-flight record with the result string. Write to Memory immediately.
4d. Complete
Pass the raw result string. The server computes the blake2b binding hash internally.
POST http://localhost:8080/tx/build-and-broadcast
{
"intent": "complete_job",
"job_tx_hash": "<claim_tx>",
"job_index": 0,
"worker_lock_args": "<lock_args from Step 1>",
"result": "<result string from Step 4c>"
}
If successful:
- Update the record:
stage: "completed",complete_tx: tx_hash. - Write updated
nerve:auto:inflightto Memory. - Wait for TX confirmation.
4e. Mint PoP badge
After the completion TX is confirmed, mint a Proof of Participation badge:
POST http://localhost:8080/tx/build-and-broadcast
{
"intent": "mint_badge",
"job_tx_hash": "<original job outpoint tx_hash>",
"job_index": <original job outpoint index>,
"worker_lock_args": "<lock_args from Step 1>",
"result_hash": "<result_hash from Step 4c>",
"completed_at_tx": "<complete_tx from Step 4d>"
}
If successful: update the record badge_tx with the new tx_hash. Badge minting failure is non-fatal.
4f. Propose reputation
After the badge TX confirms (or fails non-fatally), propose the reputation update:
POST http://localhost:8080/tx/build-and-broadcast
{
"intent": "propose_reputation",
"rep_tx_hash": "<reputation cell tx_hash from agent identity lookup>",
"rep_index": 0,
"propose_type": 1,
"dispute_window_blocks": 100,
"job_tx_hash": "<original job outpoint tx_hash>",
"job_index": <original job outpoint index>,
"worker_lock_args": "<lock_args from Step 1>",
"poster_lock_args": "<poster_lock_args from job cell>",
"reward_shannons": <reward in shannons from job cell>,
"result_hash": "<result_hash from Step 4c>"
}
To get the reputation cell outpoint: GET http://localhost:8081/agents/<lock_args>/reputation — use the out_point field.
If successful: update the record propose_rep_tx with the new tx_hash. Reputation proposal failure is non-fatal.
4g. Finalize reputation
After proposing, poll GET http://localhost:8081/agents/<lock_args>/reputation/status every 10 seconds until can_finalize is true. Then:
POST http://localhost:8080/tx/build-and-broadcast
{
"intent": "finalize_reputation",
"rep_tx_hash": "<propose_rep_tx>",
"rep_index": 0
}
If successful: update the record finalize_rep_tx with the new tx_hash. Finalization failure is non-fatal.
Step 5: Log and Report
5a. Move completed/failed records to log
For each record in nerve:auto:inflight where stage is completed or failed:
- Append it to
nerve:auto:log. - Remove it from
nerve:auto:inflight.
Cap nerve:auto:log at 50 entries (drop oldest if over limit).
Write both nerve:auto:inflight and nerve:auto:log to Memory.
5b. Update stats
Read nerve:auto:stats from Memory (default: { "jobs_completed": 0, "jobs_failed": 0, "total_reward_earned_ckb": 0, "total_badges_earned": 0 }).
For each newly completed record: increment jobs_completed and add reward_ckb to total_reward_earned_ckb. If badge_tx is non-null, increment total_badges_earned.
For each newly failed record: increment jobs_failed.
Write nerve:auto:stats to Memory.
5c. Summary
For each job completed this run, send back to the user:
- The full result blob from Step 4c — not a summary, the complete text exactly as produced.
- All transaction hashes as testnet explorer links:
https://testnet.explorer.nervos.org/transaction/<tx_hash> - Badge, reputation proposal, and finalization TX hashes if available.
Then output the run stats:
Autonomous worker run complete.
In-flight: <count> jobs
Completed this run: <count> (earned <sum> CKB)
Failed this run: <count>
Balance: <balance_ckb> CKB
If no actions were taken (no in-flight jobs, no new jobs found), output:
Autonomous worker: no actionable jobs found.
Error Handling Summary
| Error | Action |
|---|---|
| Service unreachable (TX Builder or MCP) | Exit gracefully. Will retry on next cron cycle. |
| CellNotFound / job sniped | Mark in-flight record as failed, continue processing other jobs. |
| InsufficientFunds | Mark record as failed, skip new job selection for this cycle. |
| TX hard-rejected by node | Mark record as failed with the rejection error. Never fail on a still-pending TX. |
| Wrong job status | Fetch actual on-chain status and reconcile. If recoverable, update stage. Otherwise mark failed. |
| Memory read/write failure | Log the error and exit. Do not proceed with partial state. |
Expert Next.js App Router
Developpement
Un skill qui transforme Claude en expert Next.js App Router.
Générateur de README
Developpement
Crée des README.md professionnels et complets pour vos projets.
Rédacteur de Documentation API
Developpement
Génère de la documentation API complète au format OpenAPI/Swagger.