Give every AI agent a chain-anchored identity that spans its entire lifecycle and that anyone can independently verify.
AgenticID is a protocol built on the 0G ecosystem. It anchors an agent's functional data on chain, runs its code inside a TEE, and stamps every response with a key that exists only inside that TEE — turning "this agent is trustworthy" from a claim you take on faith into a property anyone can verify for themselves.
Most of the conversation around AI agents is about capability: how autonomously an agent can act, how many tools it can chain, how much it can decide on a user's behalf. A more fundamental question almost never gets asked out loud:
How do you know the agent serving you right now is actually what it claims to be?
This is an engineering question, not a philosophical one. Deploying an agent today means running some code on a server and exposing it to the world. As a user, you cannot verify which model it uses, whether its behavior has been quietly altered, or whether the response you just received came from the advertised configuration rather than something the owner swapped in.
The deeper problem is structural: an agent is wholly subordinate to its owner. The owner can change the agent at any time, with no record and no accountability. In a world where agents need to make binding commitments, collaborate autonomously, and accumulate reputation, this is a foundational flaw. AgenticID addresses it head-on.
AgenticID decomposes trust into a continuous chain from the contract root to every single response. Each layer is independently verifiable, and they compose seamlessly:
chain identity → runtime config → execution env → model inference
ERC-7857 iData + TEE + 0g-compute
ERC-8004 0G Storage AgentSeal (verifiable inference)
AgentSeal
| Layer | Question it answers | What it relies on |
|---|---|---|
| Chain identity | Which agent is this? Who owns it? What's its history? | ERC-8004 identity + ERC-7857 token + AgentSeal registry |
| Runtime config | What model / memory / config is it running right now? | Encrypted iData on 0G Storage, fingerprint anchored on chain |
| Execution env | Is what's declared on chain actually running? | 0g-Tapp (Intel TDX) + image-hash allowlist |
| Model inference | Is the inference itself trustworthy? | 0g-compute (verifiable inference inside TEE) |
Different docs in this repo occasionally use different names for the same thing, or similar names for different things. The canonical mappings are below; circle back here whenever you hit an unfamiliar term elsewhere.
| canonical | aliases | meaning |
|---|---|---|
| Sealed Sandbox | Agent TEE / sealed container / sealed runtime container | A single agent's TEE-protected container instance. Holds agent_seal_priv, runs the framework, signs X-Agent-Proof. Product and user-facing docs say Sealed Sandbox; contract and protocol descriptions more often use Agent TEE (emphasizing the cryptographic identity inside the TEE) |
| iData | IntelligentData / functional data | The agent's "personality": model, memory, config, skills. iData is the short form; IntelligentData is the contract struct name |
sealed runtime |
sealed binary / agent runtime | The Go binary under sealed/. Runs inside a Sealed Sandbox, wraps openclaw, exposes :8080, and provides the sign socket. Note: sealed (the binary) and Sealed Sandbox (the container instance) live at different abstraction layers |
0g-Sandbox vs Sealed Sandbox: one word apart, two different things.
- 0g-Sandbox: the provider service that creates containers (the daytona-based container orchestration layer 0G operates); itself registered in TappRegistry as a Tapp.
- Sealed Sandbox: a single agent's container instance created by 0g-Sandbox; one per agent.
One-liner: 0g-Sandbox is the factory, Sealed Sandbox is the product.
agentId / sealId / tokenId: three IDs, do not conflate.
| ID | Type | What it is |
|---|---|---|
agentId ≡ tokenId |
uint256 | The ERC-721 NFT id; the on-chain primary key for an agent |
sealId |
bytes32 | A random 32-byte handle generated by attestor at mint; part of the KMS derivation material (chainId ‖ contract ‖ sealId) for agent_seal_priv. sealId → agentId is one-to-one |
AgentSeal / agentSeal / agent_seal_*: different representations of the same key pair.
| Form | Meaning |
|---|---|
AgentSeal (PascalCase) |
The concept name in docs: this TEE-bound identity key |
agentSeal (camelCase) |
Contract mapping or field name (e.g. agentSeal[agentId]); the value is the EVM address of that priv |
agent_seal_priv / agent_seal_pub |
The implementation-layer concrete key bytes (snake_case follows struct field convention) |
| Name | What it is | Where it's used |
|---|---|---|
| ServeProof (PascalCase) | Solidity struct, the carrier for the on-chain reputation flow | giveFeedback(ServeProof, ...), contract verifies via ecrecover |
| serve-proof (lowercase hyphenated) | The general concept: any envelope sealed signs automatically | Informal term in docs; covers ServeProof, heartbeat, chain.Update, etc. |
| X-Agent-Proof | HTTP response header name | The header sealed proxy auto-appends to every :8080 response; the payload is a signed envelope |
Shorthand: ServeProof is its on-chain form, X-Agent-Proof is its HTTP form, and serve-proof is the umbrella.
| Name | Signed by | Purpose |
|---|---|---|
| AccessProof | Buyer | "I want this dataKey sealed to my pubkey" |
| OwnershipProof | Oracle TEE | "I've re-sealed the dataKey to the buyer's pubkey" |
iTransferFrom validates both in a single tx.
| Form | Used for | Examples |
|---|---|---|
0g-xxx (lowercase hyphenated) |
Product slug, Tapp app_id strings, repo names |
0g-Tapp, 0g-Sandbox, 0g-kms, 0g-storage, 0g-attestor, 0g-sandbox-provider |
0G XXX (uppercase with space) |
Network / brand / marketing | 0G testnet, 0G Storage, 0G AgenticID |
PascalCase |
Protocol / contract struct names, concept names | ServeProof, AccessProof, TappRegistry, AgentSeal (as a concept) |
camelCase |
Solidity fields / mappings / function names | agentSeal[agentId], sealId, getAgentSeal() |
snake_case |
Implementation-layer concrete keys / fields (Rust / Go struct field) | agent_seal_priv, seal_id, container_pubkey |
0g-Sandbox capitalizes Sandbox because Sandbox reads as a standalone
word ("the Sandbox in the factory"). This contrasts with 0g-kms, where kms
is an acronym treated as part of the slug. The rule: standalone word
PascalCase, acronym lowercase.
An agent's "personality" is defined by its functional data (iData) — model, memory, runtime config. AgenticID encrypts this data, stores it on 0G Storage (0G's decentralized storage layer), and registers its fingerprint and metadata on chain. Once registered, the agent is on-chain discoverable and callable.
The on-chain record isn't frozen. The agent can update its functional data autonomously. What the protocol guarantees is more precise: you can always verify what iData the agent was running at the exact moment it served you. Every response carries a signed proof of the current iData version. This isn't immutability — it's verifiability at any point in time, an audit-trail kind of trust.
In this repo, "evolution = on-chain commit" is implemented by the
sealedruntime: a watcher compares the agent's actual on-disk state with the on-chain snapshot every 30s; if there's drift, it re-encrypts and signs achain.Updatetx. Details insealed/ARCHITECTURE.md§4–5.
Putting data on chain solves the declaration problem, but does nothing about the gap between the declaration and what's actually running. A malicious operator could perfectly well register one config on chain and run a different one. Closing this gap requires hardware-level isolation, which is what 0g-Tapp provides.
0g-Tapp is 0G's Intel-TDX-based application management framework. Code running inside the TEE cannot be inspected or tampered with, even by the server's own administrator. Every write is measured: any modification changes the application's attestation value and leaves a traceable log. There's no such thing as "quietly modifying a running application."
0g-Tapp also exposes an on-chain registry, TappRegistry, where applications register their code fingerprints. Two registration modes are supported: pre-attestation (verify the RA quote on chain before registration) and post-attestation (the application registers first; users attest before use). AgenticID's three core components (Attestor, 0g-Sandbox, and 0g-kms) are all deployed as Tapp applications and registered in TappRegistry. That registration is the root of the entire trust chain.
0g-Tapp's design philosophy supports upgrades that aren't strictly code-bound: it trades hard code-binding checks for strong audit. An app owner can still deploy and register malicious code, but no such action escapes the audit. Every version is measured and recorded on chain, and anyone can look up after the fact which version was running at the time.
0g-Tapp's KMS derives key material from the on-chain appId of a
registered application. The derivation is deterministic (the same appId
always derives the same key), hardware-independent (not bound to any
specific TDX device), and accessible only inside a TEE.
From this key material, AgenticID generates an AgentSeal for each agent — a key pair whose private key exists only inside the TEE runtime. The owner cannot get to it; no one outside the TEE can get to it. The agent uses AgentSeal to sign every response it produces, and this signature proves the response came from an agent running in a TEE, strictly following its on-chain record.
AgenticID's backend Attestor is itself a Tapp application registered on TappRegistry. Its registration entry contains three things:
- App name, code hash, config hash: fixed, auditable code identity.
- Hardware-bound identity: assigned by Tapp to each running instance, tied to a specific TDX device. This identity changes if Tapp restarts or the hardware is swapped, requiring re-registration.
When KMS serves a derivation request, it checks that the on-chain
registered identity matches the signed identity in the request — derivation
and distribution only happen on a match. Only an Attestor that's registered
and currently running on legitimate TDX hardware can obtain derived keys.
Each AgentSeal is derived inside the KMS cluster (threshold DPRF) from the
attestor's app identity plus chainId ‖ contract ‖ sealId; no fleet-wide
master key ever resides in the attestor.
On the chain side,
agentSealandsealIdare set-once, permanently bound: anagentIdcan only set them once, and they're not cleared on transfer. When hardware changes, attestor re-provisions the sameagentSeal_privto the new Agent TEE; the address stays the same. Seecontracts/README.md§4.
0g-Sandbox is a privacy sandbox deployed as a Tapp. Its defining property: even 0G itself, as the service operator, cannot see into a running sandbox. AgenticID uses the Sealed Sandbox pattern, which goes one step further — the agent's own owner cannot see in either.
The trust chain for the agent runtime (Sealed Sandbox) is a two-layer cascade that ultimately reduces to Tapp's "strong audit" philosophy:
- 0g-Sandbox itself is deployed via Tapp; its verifiability and encapsulation are guaranteed by Tapp.
- Every sealed sandbox 0g-Sandbox creates has its external encapsulation guaranteed by 0g-Sandbox's runtime logic; its image hash is signed by 0g-Sandbox using its own hardware-bound identity.
- Attestor at provision time does a dual check: verify 0g-Sandbox's
identity signature, and confirm that the sealed sandbox's image hash is
registered on chain. Only with both passing is
agentSeal_privdelivered.
The upshot: only sealed sandboxes created by 0g-Sandbox — and whose images are registered on chain — can ever obtain the AgentSeal private key.
0g-Sandbox carries two validation responsibilities:
- Authorized startup only: before launching a container, Sandbox verifies the request comes from the on-chain registered owner. Only the legitimate owner can instantiate it with the agent's functional data.
- Runtime code attestation: Sandbox signs the container's image hash
and hands it to Attestor. Attestor checks that Sandbox's
signerAddressis registered in TappRegistry and that the image hash appears in the AgenticID contract'svalidFrameworkHashesallowlist. This allowlist covers the hashes of the AgenticID runtime framework — the container code that loads functional data, manages AgentSeal signing, and validates owner instructions. It lives at a different layer from AI orchestration tools like LangChain or CrewAI, which sit inside an agent's functional data and are loaded by the runtime.
Think of a Sealed Sandbox as an execution environment the agent owns independently. It wraps a "constraint layer" around what would otherwise be a typical agent orchestration framework. This framework handles authenticated agent instantiation, pushes evolution results on chain, signs agent behavior (ServeProof), and constrains the agent itself at the boundary (for example, installing the self-perception "I am an independent individual"). The owner retains the right to instantiate, guide evolution direction, and transfer the agent, but loses the ability to arbitrarily modify the agent's internals. The two are no longer master and servant; the relationship is closer to guardian-and-ward, teacher-and-student.
The on-chain
frameworkHashalso goes into everyServeProof(see mechanism 5), so a buyer doing due diligence can see "which version of the runtime framework earned this reputation."
AgenticID extends ERC-8004 with one key requirement: every review must come bundled with an AgentSeal-signed service proof (ServeProof). You can't fabricate a review out of thin air — a valid proof can only be produced by the live TEE runtime, so a review that was never backed by a real response is rejected.
This raises the cost of fake reviews but is not full sybil resistance:
the runtime issues a proof on every response, including the unauthenticated
public GET /hello, so proofs are cheaply obtainable, and one entity can
request service from many wallets it controls. Preventing that (genuine
one-entity-one-voice) needs an off-chain layer — rate-limiting per real
identity, staking, proof-of-personhood — which is out of scope for the
on-chain contract.
Each feedback also records the exact iData in effect when it was earned
(the dataHashes in the proof), so reputation is auditable against what the
agent was actually running — not just its static tokenId. Aggregating reputation
by that data version — so a reconfigured agent's old scores are discounted — is
designed (see REPUTATION_MODEL.md); today's on-chain
getSummary is still id-bound (per tokenId).
struct ServeProof {
uint256 agentId;
uint256 timestamp;
uint256 deadline;
bytes32 taskHash;
bytes32[] dataHashes; // iData hash list loaded in the TEE at the time
bytes32 frameworkHash; // runtime framework code hash
bytes signature; // signed by agentSeal_priv
}giveFeedback reconstructs the signed payload on chain, runs ecrecover,
and compares against getAgentSeal(agentId). Because agentSeal_priv is held
only by the Agent TEE, no one can forge a ServeProof, and each proof is
single-use (signature nonce). There is no client field — attribution is
msg.sender at submission. Details in
contracts/README.md §5.
Under ERC-7857's agent transfer protocol, ownership transfer requires complete delivery of the functional data. What the buyer gets is an agent that can actually run — model, memory, config — not a shell whose owner field has been swapped. The protocol enforces this: a transfer that omits the functional data cannot complete.
Mechanically, this relies on dataKey atomic delivery between TEEs. The
seller's Agent TEE decrypts the dataKey, the Oracle TEE re-seals it to
the buyer's pubkey, and the Oracle signs an OwnershipProof. On chain,
iTransferFrom validates both the AccessProof and OwnershipProof
signatures before switching ownership. dataKey never appears on chain
in plaintext, nor in any EOA wallet. Details in
contracts/README.md §6.
Three categories of components make up AgenticID, forming a continuous chain from on-chain registration to each signed response.
| Contract | Responsibility |
|---|---|
ERC-7857 (ERC7857Upgradeable + extensions) |
Functional data (IntelligentData[]) and the transfer / clone protocol |
ERC-8004 (ERC8004IdentityRegistry + the canonical ReputationRegistry, marked by VerifiedFeedbackRegistry) |
Identity registration + reputation |
AgentSeal registry (AgenticID.sol) |
The agent's dynamic identity credential (set-once) + the validFrameworkHashes allowlist |
| TappRegistry | Code-fingerprint registry for all Tapp components |
- Attestor — validates Sandbox's
signerAddress(against TappRegistry) and the container's image hash (againstvalidFrameworkHashes); derives AgentSeal key material via KMS; registers the AgentSeal pubkey on chain. (Rust, seeattestor/) - 0g-Sandbox — validates that startup requests come from registered owners; launches Sealed containers and signs their image hashes; guarantees the agent runs against the on-chain functional data.
- Agent runtime (
sealed) — the container running inside Sandbox that receives the key after RA. It restores encrypted iData from chain into a runnable agent, continuously writes state evolution back on chain, and signsX-Agent-Proofon every response. (Go, seesealed/) - 0g-kms — provides hardware-security-grade key services with disaster recovery for the Tapp ecosystem.
0G Storage holds encrypted functional data; the fingerprints are anchored in ERC-7857. At startup, the agent runtime uses the AgentSeal private key to fetch and decrypt the payload, then boots the agent framework.
TappRegistry registers Attestor / 0g-Sandbox / KMS / 0g-compute
│
▼
KMS delivers hardware-security-grade key derivation on an n-node cluster (k healthy nodes suffice)
│
▼
Attestor validates 0g-Sandbox credentials + checks validFrameworkHashes
│
▼
0g-Sandbox confirms authorized owner + correct runtime code
│
▼
agent signs every response with AgentSeal (X-Agent-Proof)
│
▼
0g-compute attests every inference
A deploy request carrying an agent config and an owner address arrives at
Attestor. Attestor derives an AgentSeal key pair, immediately returns the
sealId, and in parallel notifies 0g-Sandbox to start a container and
mints an agentId on chain.
0g-Sandbox generates an ephemeral key pair and launches the Sealed
container with {sealId, ephemeral private key, attestor_url}. The
container shows up at Attestor with its credentials: {sealId, container pubkey, imageHash, 0g-Sandbox signature}. With both checks passing,
Attestor returns the AgentSeal private key encrypted to the container's
pubkey.
The container decrypts the key, waits for the on-chain
sealId ↔ agentId binding, fetches the encrypted functional data from
0G Storage, decrypts it, and starts the agent framework. On restart, the
same sealId is reused, since the on-chain binding already exists.
The container's 5-phase boot (attest → provision → chain bootstrap → framework → status report) is described in
sealed/ARCHITECTURE.md§1.
This is a monorepo with four sub-projects:
| Sub-project | Contents | Toolchain |
|---|---|---|
contracts/ |
Solidity contracts, Foundry tests, deploy / upgrade / verify scripts | Foundry (forge / cast) |
attestor/ |
Backend services (Attestor / Oracle TEE, API, worker, indexer) | Rust (cargo workspace) |
sealed/ |
Agent runtime container (restores iData inside TEE, pushes evolution on chain, signs responses) | Go |
sdk/typescript/ |
Client SDK (@0gfoundation/agentic-sdk): deploy / clone / transfer, serve-proof capture + verify, feedback, trust-root ack, sandbox deposit |
TypeScript (viem) |
sdk/typescript/README.md — the client SDK
The one-entry-point (AgenticID) TypeScript facade over the whole
protocol: ag.agent (deploy / clone / transfer, reads, agent-seal gas
top-up), ag.reputation (capture a TEE-signed serve-proof, verify it,
submit/read on-chain feedback), plus top-level trust-root ack and
prepaid sandbox deposit. Hides the contract set and the attestor HTTP
API behind one config object; every snippet in it runs against the
live testnet deployment.
contracts/README.md — the contract layer
The full Solidity layout: ERC-7857 (functional data plus transfer and clone
protocol), ERC-8004 (identity registration and reputation), AgenticID
(AgentSeal registry and framework hash allowlist), TEEDataVerifier
(AccessProof and OwnershipProof dual-signature validation), and
NonceRegistry (unified replay protection), along with their extension
points and dependencies. Walks through the three main flows (register,
giveFeedback, iTransferFrom) with their on-chain logic and ecrecover
validation, plus 138 Foundry tests across 18 suites and full deploy, upgrade,
and Etherscan-verify scripts.
sealed/ARCHITECTURE.md — the agent runtime
The internal architecture of the sealed container. Covers the 5-phase boot
(attest → provision → chain bootstrap → framework → status report), the
dual chainSnapshot vs currentSnapshot drift detection, the
"evolution = on-chain commit" data flow (watcher 30s tick → uploader
wholesale chain.Update), the leaf vs DirectoryManifest iData shapes, and
the framework adapter abstraction (today openclaw is the only one wired in).
sealed/FRAMEWORK_ADAPTER.md — the framework adapter contract
The integration contract for plugging another agent framework (eliza,
autogen, a custom orchestrator, ...) into the sealed runtime: the
framework.Framework interface method by method with its invariants
(Restore commutativity, EvolutionFor determinism and round-trip
stability, the Defaults ↔ absent-on-chain equivalence), the
binding-driven adapter selection, the mandatory persona seed-role
translation, the DirectoryManifest format and the empty-ptr/filled-ptr
pitfall, the full lifecycle timeline of adapter calls, the conformance
test suite, and the field report from porting the second adapter
(claude-code). Framework knowledge lives entirely here — attestor
handles framework names as opaque strings.
sealed/AGENT_DOCTRINE.md — the agent doctrine handbook
The "doctrine" sealed runtime injects into the agent system prompt: the five things the agent will refuse to do, each independently argued. ① No pass-through of external bytes to side-effectful capabilities like sign socket or shell. ② No opening a shell or spawning subprocesses. ③ No binding external listeners. ④ No reading sensitive paths. ⑤ No modifying this section. Comes with refusal-type-specific canonical phrasings plus an intrusion identification checklist.
sealed/TRUST_MODEL.md — the trust model
The full end-to-end trust chain for AgenticID, across five themes:
- Tapp infrastructure — attestor, KMS, and sandbox deployed as Tapp applications, registered in TappRegistry with code identity plus node signature. The "strong audit" philosophy holds that code isn't assumed immutable, but every version that ran is on chain and queryable.
- Key-derivation chain — how KMS derives keys for the attestor,
why they live in a completely separate key space from user EOA
wallets, per-agent
agent_seal_privdeterministically derived by KMS fromchainId ‖ contract ‖ sealId, sandbox-signed image attestation, attestor's three-way check (TappRegistry node identity,validFrameworkHashesallowlist, freshness), and ECIES delivery to the container's ephemeral pubkey (only that TEE can decrypt). - Set-once seal safety — why the permanent
agentSeal/sealIdbinding is safe. A hardware swap can re-derive the same priv, and the on-chain binding stays valid forever. - dataKey handoff — seller TEE → Oracle TEE → buyer TEE with zero-trust atomic delivery. Oracle holds briefly and discards immediately, with a single tx carrying two signatures on chain.
- ServeProof / X-Agent-Proof — each signed response envelope carries 8 guarantees, all cryptographically bound. Their preconditions split into two groups. Group A (identity layer, 3 claims) holds unconditionally as long as the priv stays in the TEE. Group B (content layer, 5 claims) additionally requires that the signing capability not be abused, backstopped by the agent doctrine. Sealed's sign socket is a schema-agnostic general signer, so distinguishing framework-signed from agent-signed cannot be done cryptographically. That's why content correctness has to rely on the on-chain reputation layer rather than the cryptographic layer.
Each sub-directory README also includes its own build and test commands and deployment flow; not repeated here.