agentleFS
0gfoundation0gfoundation/0g-agent-skills/AGENTS.md

0g-agent-skills

AGENTS.md15 starsChanged 57 days agoMITView on GitHub

Master orchestration file for AI coding assistants. Defines activation triggers, workflow sequences, critical rules, and common mistakes for all 25 skills across 6 categories. SDK rename (breaking). @0glabs/0g-ts-sdk and @0glabs/0g-serving-broker are deprecated on npm. Use @0gfoundation/0g-storage-ts-sdk (^1.2.12) and @0gfoundation/0g-compute-ts-sdk (^0.9.0), and pin ethers to exactly 6.13.1.

  • Reads credentials

The file

We split this AGENTS.md into the rules it gives an agent

9 rules. About 0 are common, 3 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Use upload-file for all data storage

    line 97
  2. Very specific:

    After successful upload, automatically verify using merkle-verification

    line 98
  3. Very specific:

    Use download-file to retrieve data by root hash

    line 109
  4. Very specific:

    Use verified download (third param = true)

    line 110
  5. Distinctive:

    Run the specific inference skill based on request:

    line 123
  6. Very specific:

    Run fine-tuning workflow (testnet only)

    line 141
  7. Distinctive:

    Follow multi-step workflow in skill

    line 163
  8. Very specific:

    Run deploy-agent to mint (optionally provisioning a container)

    line 185
  9. Distinctive:

    Symptom: Import errors, undefined methods

    line 428

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

0G Agent Skills — Orchestration Guide

Master orchestration file for AI coding assistants. Defines activation triggers, workflow sequences, critical rules, and common mistakes for all 25 skills across 6 categories.

SDK rename (breaking). @0glabs/0g-ts-sdk and @0glabs/0g-serving-broker are deprecated on npm. Use @0gfoundation/0g-storage-ts-sdk (^1.2.12) and @0gfoundation/0g-compute-ts-sdk (^0.9.0), and pin ethers to exactly 6.13.1.

Skill Index

Storage Skills

SkillPathTriggers
Upload Fileskills/storage/upload-file/SKILL.md"upload file", "store on 0G", "ZgFile", "save to storage"
Download Fileskills/storage/download-file/SKILL.md"download file", "retrieve from 0G", "get file", "fetch from storage"
Merkle Verificationskills/storage/merkle-verification/SKILL.md"verify file", "merkle proof", "data integrity", "root hash"

Compute Skills

SkillPathTriggers
Provider Discoveryskills/compute/provider-discovery/SKILL.md"list providers", "find provider", "verify provider", "TEE"
Account Managementskills/compute/account-management/SKILL.md"deposit", "transfer funds", "refund", "check balance"
Streaming Chatskills/compute/streaming-chat/SKILL.md"chatbot", "inference", "LLM", "GLM", "Claude", "GPT", "AI chat"
Text to Imageskills/compute/text-to-image/SKILL.md"generate image", "text-to-image", "create image"
Image Editingskills/compute/image-editing/SKILL.md"edit image", "image-editing", "inpaint", "modify image"
Video Generationskills/compute/video-generation/SKILL.md"generate video", "text-to-video", "MiniMax", "Seedance"
Embeddingsskills/compute/embeddings/SKILL.md"embedding", "vector", "semantic search", "RAG"
Speech to Textskills/compute/speech-to-text/SKILL.md"transcribe", "speech-to-text", "Whisper", "audio transcription"
Fine-Tuningskills/compute/fine-tuning/SKILL.md"fine-tune", "train model", "LoRA", "adapter", "custom model"

Chain Skills

SkillPathTriggers
Scaffold Projectskills/chain/scaffold-project/SKILL.md"new project", "scaffold", "initialize", "create 0G app"
Deploy Contractskills/chain/deploy-contract/SKILL.md"deploy contract", "Solidity", "0G Chain"
Interact Contractskills/chain/interact-contract/SKILL.md"call contract", "read contract", "interact", "write contract"

Cross-Layer Skills

SkillPathTriggers
Storage + Chainskills/cross-layer/storage-plus-chain/SKILL.md"on-chain reference", "NFT metadata on 0G", "registry"
Compute + Storageskills/cross-layer/compute-plus-storage/SKILL.md"AI with storage", "generate and store", "AI pipeline"

Private Computer Skills

These configure Claude Code itself rather than building on 0G. Claude Code only.

SkillPathTriggers
Setupskills/private-computer/0g-pc-setup/SKILL.md"put this project on 0G", "connect Claude Code to 0G", "set up 0G PC", "接入 0G"
Switch Modelskills/private-computer/0g-pc-switch-model/SKILL.md"switch 0G model", "use a different 0G model", "换模型", "切到 glm-5.3"
Uninstallskills/private-computer/0g-pc-uninstall/SKILL.md"turn 0G off", "go back to Anthropic", "卸载 0G", "不用 0G 了"

AgenticID Skills

On-chain identity and reputation for AI agents (ERC-8004 + ERC-7857).

This category uses viem, not ethers. The SDK depends on viem ^2.21.0. The repo-wide "always ethers v6" rule is scoped to storage, compute, chain and cross-layer, and does NOT apply here. Do not translate these skills to ethers.

SkillPathTriggers
Deploy Agentskills/agentic-id/deploy-agent/SKILL.md"deploy an agent", "mint an agent", "agent identity", "ERC-7857", "ERC-8004"
Manage Agentskills/agentic-id/manage-agent/SKILL.md"stop an agent", "start an agent", "transfer an agent", "clone an agent"
Interact Agentskills/agentic-id/interact-agent/SKILL.md"call an agent", "chat with an agent", "agent services", "agent logs"
Agent Reputationskills/agentic-id/agent-reputation/SKILL.md"rate an agent", "agent reputation", "serve proof", "leave feedback"
Agent Accountsskills/agentic-id/agent-accounts/SKILL.md"fund an agent", "agent balance", "acknowledge trust root", "agent refund"

Workflow Sequences

1. Create New Project

Trigger: "new project", "scaffold", "initialize", "setup", "create app"

scaffold-project

Load skills/chain/scaffold-project/SKILL.md and follow project type selection.

2. Upload / Store Data

Trigger: "upload", "store", "save to 0G"

upload-file → AUTO: merkle-verification
  1. Use upload-file for all data storage
  2. After successful upload, automatically verify using merkle-verification
  3. Return root hash to user

3. Download / Retrieve Data

Trigger: "download", "retrieve", "get file", "fetch"

download-file → AUTO: merkle-verification
  1. Use download-file to retrieve data by root hash
  2. Use verified download (third param = true)
  3. Optionally verify with merkle-verification

4. Run AI Inference

Trigger: "chatbot", "inference", "generate image", "transcribe"

AUTO: provider-discovery → AUTO: account-management → streaming-chat | text-to-image | speech-to-text
  1. Auto-activate provider-discovery — find appropriate provider for service type
  2. Auto-activate account-management — verify balance, fund if needed
  3. Run the specific inference skill based on request:
    • Chat/LLM → streaming-chat (serviceType: chatbot)
    • Image from a prompt → text-to-image (serviceType: text-to-image)
    • Edit an existing image → image-editing (serviceType: image-editing)
    • Video → video-generation (serviceType: video-generation)
    • Embeddings / semantic search / RAG → embeddings (serviceType: embedding)
    • Audio → speech-to-text (serviceType: speech-to-text)

5. Fine-Tune Model

Trigger: "fine-tune", "train model", "custom model"

AUTO: provider-discovery → AUTO: account-management → fine-tuning
  1. Auto-activate provider-discovery — find fine-tuning providers
  2. Auto-activate account-management — fund fine-tuning sub-account
  3. Run fine-tuning workflow (testnet only)

6. Deploy Contract

Trigger: "deploy contract", "Solidity", "smart contract"

deploy-contract

Load skills/chain/deploy-contract/SKILL.md. Ensure evmVersion: "cancun".

7. Cross-Layer Application

Trigger: "on-chain reference", "AI with storage", "NFT metadata", "full pipeline"

storage-plus-chain | compute-plus-storage
  1. Determine if pattern is storage+chain or compute+storage
  2. Load appropriate cross-layer skill
  3. Follow multi-step workflow in skill

8. Manage Funds

Trigger: "deposit", "transfer", "refund", "balance", "withdraw"

account-management

Load skills/compute/account-management/SKILL.md.

9. Give an Agent an On-Chain Identity

Trigger: "deploy an agent", "mint an agent", "agent identity", "agent reputation", "AgenticID"

AUTO: agent-accounts -> deploy-agent -> manage-agent | interact-agent -> agent-reputation
  1. Auto-activate agent-accounts — ack the trust root and fund the sandbox balance; deploy() preflights both and fails without them
  2. Run deploy-agent to mint (optionally provisioning a container)
  3. Then, by intent: manage-agent for lifecycle, interact-agent to call it
  4. agent-reputation once there is a signed /api/* call to attest

This category is viem, not ethers. Testnet is the default target and reputation is testnet-only.


Manual handoffs (not auto-chained)

The sequences above chain automatically. The Private Computer skills do not, and must not: each one changes the user's configuration, and a user who asked for one did not ask for the others.

SituationSkill
First time putting a project on 0G0g-pc-setup
Already on 0G, wants a different model0g-pc-switch-model
Wants this project off 0G0g-pc-uninstall

0g-pc-setup does not run the installer itself and does not chain into the other two.

Route by the object of the request. A request to configure the client belongs here; a request to build something with the Compute SDK belongs to the inference skills, even when it names a model. "LLM", "Claude" or "GPT" on their own are not requests to rewrite a configuration — when the object is unclear, ask which is meant before changing anything.


Critical ALWAYS Rules

These rules must be followed in EVERY interaction. Violations cause bugs, data loss, or financial errors.

Compute — processResponse()

ALWAYS call processResponse() after EVERY inference request.
ALWAYS use correct parameter order: processResponse(providerAddress, chatID, usageData)
ALWAYS extract ChatID from ZG-Res-Key header FIRST, body (data.id) as fallback (chatbot only).

Param order reminder:

await broker.inference.processResponse(
  providerAddress, // 1st: provider address
  chatID, // 2nd: response identifier
  usageData, // 3rd: JSON-stringified usage (optional for images)
);

Compute — Provider Setup

ALWAYS call checkProviderSignerStatus(provider) BEFORE acknowledged(provider).
  acknowledged() reverts with AccountNotExists when no sub-account exists yet.
ALWAYS acknowledge provider before first use (acknowledgeProviderSigner).
ALWAYS fund provider sub-accounts with at least 1 0G.
ALWAYS check availableBalance (NOT totalBalance) before making inference requests.
ALWAYS verify TEE status for security-sensitive workloads (s.teeSignerAcknowledged).

Compute — Listing Services

ALWAYS page listService() in chunks of <= 50 — the contract reverts with LimitTooLarge above 50.
ALWAYS pass includeUnacknowledged explicitly when you need the full picture; it defaults to false.
ALWAYS use getProviderModels(provider) to enumerate a multi-model provider's catalog;
  the on-chain `model` field is only that provider's DEFAULT model.
ALWAYS pass the model id to getServiceMetadata(provider, model) when targeting a
  specific model on a multi-model provider.

Storage — File Handles

ALWAYS generate Merkle tree BEFORE uploading.
ALWAYS close file handles after operations (file.close()).
ALWAYS use try/finally to ensure handles are closed.
ALWAYS store root hashes — they are the ONLY way to retrieve files.

Chain — Compilation

PREFER evmVersion: "cancun" for 0G Chain contract compilation — it is supported on both
  mainnet and testnet and produces the smallest bytecode (it can emit MCOPY).
  This is a gas optimisation, NOT a compatibility requirement: shanghai, paris and
  london compile, deploy and execute correctly on 0G Chain as well.
ALWAYS use ethers v6 syntax (NOT v5).
ALWAYS wait for transaction confirmation (tx.wait()).

Which chain library applies where

The ethers rules below are scoped BY CATEGORY. There are two stacks in this repo
and mixing them is a real error, not a style preference:

  storage / compute / chain / cross-layer  ->  ethers v6, pinned to EXACTLY 6.13.1
  agentic-id                               ->  viem ^2.21.0

ALWAYS use viem in agentic-id skills; the SDK depends on it.
ALWAYS use ethers v6 everywhere else.
NEVER translate an agentic-id example into ethers, or an ethers example into viem.

AgenticID

ALWAYS let AgenticID.fromAttestor() supply contract addresses; never hardcode them.
ALWAYS check which network the attestor URL pins. https://agenticid.0g.ai is TESTNET (16602);
  mainnet is https://agenticid-mainnet.0g.ai (16661).
ALWAYS ack the trust root and fund the prepaid sandbox balance to >= 0.1 OG before deploying.
ALWAYS await waitForTransaction() after a bare write (ack / deposit / topUpAgentSeal) before
  reading state back.
ALWAYS call retry(sealId) to recover a failed deploy.
ALWAYS read frameworks from the attestor and models from listModels() at runtime.

NEVER call deploy() again to fix a failed deploy — it orphans the mint already paid for.
NEVER confuse deposit() (prepaid sandbox runtime) with topUpAgentSeal() (the agent's own gas).
NEVER assume reputation works on mainnet; reputation_registry_addr is testnet-only today.
NEVER expect a serve-proof from a chat or UI route; only signed /api/* services carry one.
NEVER mix up the three identifiers: agentId (bigint) for reads and transfers, sealId (bytes32)
  for runtime control, agentSeal (address) for the agent's own wallet.

Security

ALWAYS load private keys from .env files.
ALWAYS add .env to .gitignore.
ALWAYS use verified downloads in production (third param = true).

Critical NEVER Rules

Compute

NEVER skip processResponse() — causes fee settlement failure and potential fund lock.
NEVER reverse processResponse() parameter order.
NEVER skip provider acknowledgment — requests will fail.
NEVER call acknowledged() before the provider sub-account exists — it reverts.
NEVER call listService() with limit > 50 — the contract reverts with LimitTooLarge.
NEVER treat getLedger()[2] as availableBalance — index 2 is totalBalance.
NEVER assume a provider serves exactly one model — check getProviderModels().
NEVER use ethers v5 syntax (ethers.providers, ethers.utils, BigNumber).
NEVER install @0glabs/0g-ts-sdk or @0glabs/0g-serving-broker — both are deprecated.

Storage

NEVER forget to close ZgFile handles — causes memory leaks.
NEVER lose root hashes — data becomes irretrievable.
NEVER upload without generating Merkle tree first.

Chain

NEVER use ethers v5 patterns — they won't work with v6.
NEVER pin ethers with a caret range (^6.13.0) — the storage SDK requires EXACTLY 6.13.1.

Security

NEVER hardcode private keys in source code.
NEVER commit .env files to version control.
NEVER use unverified downloads for production data.

Common Mistakes & Fixes

#1: Missing processResponse()

Symptom: Funds locked, fee settlement fails

// WRONG
const data = await response.json();
return data.choices[0].message.content;

// RIGHT
const data = await response.json();
let chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
if (!chatID) chatID = data.id;
await broker.inference.processResponse(providerAddress, chatID, JSON.stringify(data.usage));
return data.choices[0].message.content;

#2: Wrong processResponse() Parameter Order

Symptom: Fee verification fails silently

// WRONG
await broker.inference.processResponse(chatID, providerAddress, usage);

// RIGHT — providerAddress FIRST
await broker.inference.processResponse(providerAddress, chatID, usage);

#3: ChatID from Wrong Source

Symptom: Verification mismatch

// WRONG — using body without checking header
const chatID = data.id;

// RIGHT — header first, body fallback (chatbot only)
let chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
if (!chatID) chatID = data.id; // Fallback for chatbot only

#4: Not pinning evmVersion

Symptom: larger bytecode and higher deploy gas than necessary

0G Chain supports Cancun, so targeting it lets solc emit MCOPY for memory copies. Measured on the same contract: cancun → 1437 bytes, paris → 1527 bytes. Older targets are not broken — they deploy and run correctly — so this is an optimisation, not a compatibility fix.

// SUBOPTIMAL — solc default target may be older than the chain supports
solidity: { version: "0.8.24" }

// BETTER — smallest bytecode on 0G Chain
solidity: {
  version: "0.8.24",
  settings: { evmVersion: "cancun" }
}

#5: ethers v5 Syntax

Symptom: Import errors, undefined methods

// WRONG (v5)
const provider = new ethers.providers.JsonRpcProvider(url);
const amount = ethers.utils.parseEther('1');

// RIGHT (v6)
const provider = new ethers.JsonRpcProvider(url);
const amount = ethers.parseEther('1');

#6: Unclosed File Handles

Symptom: Memory leaks, file locks

// WRONG
const file = await ZgFile.fromFilePath(path);
const [tree] = await file.merkleTree();
await indexer.upload(file, process.env.RPC_URL!, wallet);
// file.close() never called!

// RIGHT
const file = await ZgFile.fromFilePath(path);
try {
  const [tree, err] = await file.merkleTree();
  if (err) throw err;
  const [tx, uploadErr] = await indexer.upload(file, process.env.RPC_URL!, wallet);
  if (uploadErr) throw new Error(`Upload failed: ${uploadErr.message}`);
} finally {
  await file.close();
}

#7: Hardcoded Private Key

Symptom: Security vulnerability

// WRONG
const wallet = new ethers.Wallet('0xabc123...', provider);

// RIGHT
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

#8: Reading the Wrong Ledger Balance

Symptom: top-ups get skipped, then inference fails mid-run with an insufficient-balance error

getLedger() returns [user, availableBalance, totalBalance, additionalInfo]. Index 1 is available, index 2 is total. Reading index 2 as "available" over-reports spendable funds by whatever is already locked in provider sub-accounts.

// WRONG — this is totalBalance, which includes locked sub-account funds
const available = parseFloat(ethers.formatEther(account[2]));

// RIGHT — named access removes all doubt
const led = await broker.ledger.getLedger();
const available = parseFloat(ethers.formatEther(led.availableBalance));

#9: Unpaginated listService()

Symptom: providers silently missing from discovery; LimitTooLarge revert if you raise the limit

// WRONG — returns only the first 50, and hides unacknowledged providers
const services = await broker.inference.listService();

// WRONG — the contract reverts: LimitTooLarge(500, 50)
const services = await broker.inference.listService(0, 500, true);

// RIGHT — page in chunks of <= 50
const services = [];
for (let offset = 0; ; offset += 50) {
  const page = await broker.inference.listService(offset, 50, true);
  services.push(...page);
  if (page.length < 50) break;
}

#10: Destructuring fineTuning.getAccountWithDetail()

Symptom: TypeError: ... is not iterable at runtime

The inference broker's getAccountWithDetail() returns a tuple, but the fine-tuning broker's returns an object. They are not interchangeable.

// WRONG — fineTuning returns an object, not a tuple
const [account, refunds] = await broker.fineTuning.getAccountWithDetail(providerAddress);

// RIGHT
const { account, refunds } = await broker.fineTuning.getAccountWithDetail(providerAddress);
console.log(`Balance: ${ethers.formatEther(account.balance)} 0G`);

#11: Calling acknowledged() Before a Sub-Account Exists

Symptom: AccountNotExists revert on a provider's very first use

// WRONG — reverts when the user has never funded this provider
if (!(await broker.inference.acknowledged(providerAddress))) {
  await broker.inference.acknowledgeProviderSigner(providerAddress);
}

// RIGHT — checkProviderSignerStatus works before the sub-account exists
const status = await broker.inference.checkProviderSignerStatus(providerAddress);
if (!status.isAcknowledged) {
  await broker.inference.acknowledgeProviderSigner(providerAddress);
}

#12: Assuming One Model Per Provider

Symptom: you can only reach a provider's default model; its other models look unavailable

// INCOMPLETE — s.model is only the provider's on-chain DEFAULT
const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress);

// RIGHT — enumerate, then select
const { multiModel, models } = await broker.inference.getProviderModels(providerAddress);
const target = models.find((m) => m.id === 'openai/gpt-5.4')?.id;
const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress, target);

Pattern Documents

For deep architectural context, reference these pattern documents:

PatternPathWhen to Reference
Network Configpatterns/NETWORK_CONFIG.mdSetting up any 0G connection
Storagepatterns/STORAGE.mdAny storage operation
Computepatterns/COMPUTE.mdAny compute/inference operation
Chainpatterns/CHAIN.mdAny smart contract operation
Securitypatterns/SECURITY.mdKey management, TEE, data integrity
Testingpatterns/TESTING.mdWriting tests for 0G apps
AgenticIDpatterns/AGENTIC_ID.mdAgent identity, trust chain, viem

SDK Quick Reference

SDKImportVersion
Storageimport { ZgFile, Indexer } from '@0gfoundation/0g-storage-ts-sdk'^1.2.12
Computeimport { createZGComputeNetworkBroker } from '@0gfoundation/0g-compute-ts-sdk'^0.9.0
Compute (no-op)import { createReadOnlyInferenceBroker } from '@0gfoundation/0g-compute-ts-sdk'^0.9.0
Chainimport { ethers } from 'ethers'6.13.1

createReadOnlyInferenceBroker(rpcUrl) needs no wallet and no signing — use it for provider and model discovery before a user connects a wallet.

Live Service Types

Verified against 0G mainnet. Use these serviceType values when filtering listService():

serviceTypeSkill
chatbotskills/compute/streaming-chat/SKILL.md
text-to-imageskills/compute/text-to-image/SKILL.md
image-editingskills/compute/image-editing/SKILL.md
video-generationskills/compute/video-generation/SKILL.md
embeddingskills/compute/embeddings/SKILL.md
speech-to-textskills/compute/speech-to-text/SKILL.md

Model ids change frequently. NEVER hardcode a model name from documentation — discover it at runtime via listService() and getProviderModels().

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.