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
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository26 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- agent-accountsSkill
- agent-reputationSkill
- deploy-agentSkill
- interact-agentSkill
- manage-agentSkill
- deploy-contractSkill
- interact-contractSkill
- scaffold-projectSkill
- account-managementSkill
- embeddingsSkill
- fine-tuningSkill
- image-editingSkill
- provider-discoverySkill
- speech-to-textSkill
- streaming-chatSkill
- text-to-imageSkill
- video-generationSkill
- compute-plus-storageSkill
- storage-plus-chainSkill
- 0g-pc-setupSkill
- 0g-pc-switch-modelSkill
- 0g-pc-uninstallSkill
- download-fileSkill
- merkle-verificationSkill
- upload-fileSkill
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
- Very specific: line 97
Use upload-file for all data storage
- Very specific: line 98
After successful upload, automatically verify using merkle-verification
- Very specific: line 109
Use download-file to retrieve data by root hash
- Very specific: line 110
Use verified download (third param = true)
- Distinctive: line 123
Run the specific inference skill based on request:
- Very specific: line 141
Run fine-tuning workflow (testnet only)
- Distinctive: line 163
Follow multi-step workflow in skill
- Very specific: line 185
Run deploy-agent to mint (optionally provisioning a container)
- Distinctive: line 428
Symptom: Import errors, undefined methods
≈ “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.
Files
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-sdkand@0glabs/0g-serving-brokerare deprecated on npm. Use@0gfoundation/0g-storage-ts-sdk(^1.2.12) and@0gfoundation/0g-compute-ts-sdk(^0.9.0), and pinethersto exactly6.13.1.
Skill Index
Storage Skills
| Skill | Path | Triggers |
| Upload File | skills/storage/upload-file/SKILL.md | "upload file", "store on 0G", "ZgFile", "save to storage" |
| Download File | skills/storage/download-file/SKILL.md | "download file", "retrieve from 0G", "get file", "fetch from storage" |
| Merkle Verification | skills/storage/merkle-verification/SKILL.md | "verify file", "merkle proof", "data integrity", "root hash" |
Compute Skills
| Skill | Path | Triggers |
| Provider Discovery | skills/compute/provider-discovery/SKILL.md | "list providers", "find provider", "verify provider", "TEE" |
| Account Management | skills/compute/account-management/SKILL.md | "deposit", "transfer funds", "refund", "check balance" |
| Streaming Chat | skills/compute/streaming-chat/SKILL.md | "chatbot", "inference", "LLM", "GLM", "Claude", "GPT", "AI chat" |
| Text to Image | skills/compute/text-to-image/SKILL.md | "generate image", "text-to-image", "create image" |
| Image Editing | skills/compute/image-editing/SKILL.md | "edit image", "image-editing", "inpaint", "modify image" |
| Video Generation | skills/compute/video-generation/SKILL.md | "generate video", "text-to-video", "MiniMax", "Seedance" |
| Embeddings | skills/compute/embeddings/SKILL.md | "embedding", "vector", "semantic search", "RAG" |
| Speech to Text | skills/compute/speech-to-text/SKILL.md | "transcribe", "speech-to-text", "Whisper", "audio transcription" |
| Fine-Tuning | skills/compute/fine-tuning/SKILL.md | "fine-tune", "train model", "LoRA", "adapter", "custom model" |
Chain Skills
| Skill | Path | Triggers |
| Scaffold Project | skills/chain/scaffold-project/SKILL.md | "new project", "scaffold", "initialize", "create 0G app" |
| Deploy Contract | skills/chain/deploy-contract/SKILL.md | "deploy contract", "Solidity", "0G Chain" |
| Interact Contract | skills/chain/interact-contract/SKILL.md | "call contract", "read contract", "interact", "write contract" |
Cross-Layer Skills
| Skill | Path | Triggers |
| Storage + Chain | skills/cross-layer/storage-plus-chain/SKILL.md | "on-chain reference", "NFT metadata on 0G", "registry" |
| Compute + Storage | skills/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.
| Skill | Path | Triggers |
| Setup | skills/private-computer/0g-pc-setup/SKILL.md | "put this project on 0G", "connect Claude Code to 0G", "set up 0G PC", "接入 0G" |
| Switch Model | skills/private-computer/0g-pc-switch-model/SKILL.md | "switch 0G model", "use a different 0G model", "换模型", "切到 glm-5.3" |
| Uninstall | skills/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, notethers. The SDK depends onviem ^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.
| Skill | Path | Triggers |
| Deploy Agent | skills/agentic-id/deploy-agent/SKILL.md | "deploy an agent", "mint an agent", "agent identity", "ERC-7857", "ERC-8004" |
| Manage Agent | skills/agentic-id/manage-agent/SKILL.md | "stop an agent", "start an agent", "transfer an agent", "clone an agent" |
| Interact Agent | skills/agentic-id/interact-agent/SKILL.md | "call an agent", "chat with an agent", "agent services", "agent logs" |
| Agent Reputation | skills/agentic-id/agent-reputation/SKILL.md | "rate an agent", "agent reputation", "serve proof", "leave feedback" |
| Agent Accounts | skills/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-projectLoad 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- Use
upload-filefor all data storage - After successful upload, automatically verify using
merkle-verification - Return root hash to user
3. Download / Retrieve Data
Trigger: "download", "retrieve", "get file", "fetch"
download-file → AUTO: merkle-verification- Use
download-fileto retrieve data by root hash - Use verified download (third param =
true) - 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- Auto-activate
provider-discovery— find appropriate provider for service type - Auto-activate
account-management— verify balance, fund if needed - 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)
- Chat/LLM →
5. Fine-Tune Model
Trigger: "fine-tune", "train model", "custom model"
AUTO: provider-discovery → AUTO: account-management → fine-tuning- Auto-activate
provider-discovery— find fine-tuning providers - Auto-activate
account-management— fund fine-tuning sub-account - Run
fine-tuningworkflow (testnet only)
6. Deploy Contract
Trigger: "deploy contract", "Solidity", "smart contract"
deploy-contractLoad 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- Determine if pattern is storage+chain or compute+storage
- Load appropriate cross-layer skill
- Follow multi-step workflow in skill
8. Manage Funds
Trigger: "deposit", "transfer", "refund", "balance", "withdraw"
account-managementLoad 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- Auto-activate
agent-accounts— ack the trust root and fund the sandbox balance;deploy()preflights both and fails without them - Run
deploy-agentto mint (optionally provisioning a container) - Then, by intent:
manage-agentfor lifecycle,interact-agentto call it agent-reputationonce 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.
| Situation | Skill |
| First time putting a project on 0G | 0g-pc-setup |
| Already on 0G, wants a different model | 0g-pc-switch-model |
| Wants this project off 0G | 0g-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:
| Pattern | Path | When to Reference |
| Network Config | patterns/NETWORK_CONFIG.md | Setting up any 0G connection |
| Storage | patterns/STORAGE.md | Any storage operation |
| Compute | patterns/COMPUTE.md | Any compute/inference operation |
| Chain | patterns/CHAIN.md | Any smart contract operation |
| Security | patterns/SECURITY.md | Key management, TEE, data integrity |
| Testing | patterns/TESTING.md | Writing tests for 0G apps |
| AgenticID | patterns/AGENTIC_ID.md | Agent identity, trust chain, viem |
SDK Quick Reference
| SDK | Import | Version |
| Storage | import { ZgFile, Indexer } from '@0gfoundation/0g-storage-ts-sdk' | ^1.2.12 |
| Compute | import { createZGComputeNetworkBroker } from '@0gfoundation/0g-compute-ts-sdk' | ^0.9.0 |
| Compute (no-op) | import { createReadOnlyInferenceBroker } from '@0gfoundation/0g-compute-ts-sdk' | ^0.9.0 |
| Chain | import { 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():
serviceType | Skill |
chatbot | skills/compute/streaming-chat/SKILL.md |
text-to-image | skills/compute/text-to-image/SKILL.md |
image-editing | skills/compute/image-editing/SKILL.md |
video-generation | skills/compute/video-generation/SKILL.md |
embedding | skills/compute/embeddings/SKILL.md |
speech-to-text | skills/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().
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
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.

