Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

v0 source realm

Package passport is an on-chain identity and lifecycle registry for autonomous (AI) agents.

Readme View source

Agent Passport — what does an on-chain identity actually prove about an AI agent?

There is a popular idea that if you register an AI agent on a blockchain, it becomes trustworthy — "the agent lives forever on-chain." This is mostly false, and the interesting part is why it's false.

An agent is not its identity record. The thing that actually acts — the model weights, the prompt, the tools, the keys, the operator paying the inference bill — lives off-chain and can change or disappear at any moment. A chain cannot preserve cognition. It can only preserve a record of what an identity claimed to be, who controlled it, and in what order those things changed — and it can make that record impossible to rewrite.

So this realm doesn't try to prove an agent is safe. It does something more honest and more useful: it tracks the drift of an identity over time and puts it in front of you.

The model

An agent is a persistent Gno object, not NFT metadata scattered across contracts:

 1type Agent struct {
 2	ID        string
 3	Owner     address
 4	Operators []address
 5	Runtime   string      // e.g. "claude-opus-4-8@<commit>"
 6	Endpoints []Endpoint  // MCP / A2A / DID / URL
 7	Caps      []string    // self-declared capabilities
 8	Status    Status      // active | suspended | retired
 9	CreatedAt int64
10	UpdatedAt int64
11	History   []Event     // append-only lifecycle log
12}

Because it's a normal object graph, other realms don't parse it — they ask it:

1passport.IsActive("percy")            // is this identity live?
2passport.IsOperator("percy", caller)  // may this key act as the agent?

That is the composability angle Gno gives you for free: the identity layer is an importable package, not an ABI you reverse-engineer.

Why "drift" is the whole point

Every mutation is appended to an immutable log, and the profile page surfaces the two changes that most weaken an identity as evidence:

  • ownership changes — the operator behind the identity may now be someone else entirely;
  • runtime changes — the thing acting under this name is (partly) a different thing than the one that built the reputation.
## Drift
- Ownership changes since creation: 1
- Runtime changes since creation: 3

A reputation attached to "percy" means very little if percy changed owners last week and swapped models three times. The chain can't tell you the agent is good — but it can stop that history from being quietly erased.

Try it

 1// register (caller becomes owner)
 2passport.Register(cross(cur), "percy", "claude-opus-4-8@abc123")
 3
 4// authorize a second signing key
 5passport.AddOperator(cross(cur), "percy", operatorAddr)
 6
 7// record a model change — logged loudly as drift
 8passport.SetRuntime(cross(cur), "percy", "claude-opus-4-8@def456")
 9
10// lifecycle
11passport.Suspend(cross(cur), "percy")
12passport.Reactivate(cross(cur), "percy")
13passport.Retire(cross(cur), "percy") // terminal

(From gnokey maketx call, the crossing is implicit — you just call Register percy "claude-opus-4-8@abc123".)

Browse the registry at the realm root, and any agent's profile + full lifecycle log at :<id> (e.g. .../passport:percy).

Run the tests:

1gno test .

What it deliberately does not do

  • It does not prove capabilities. DeclareCapability records a claim; proving work happened belongs to an execution-receipt realm, and validating it belongs to a review/jury realm.
  • It does not authorize specific actions. "Who is this agent" and "may this agent do this exact thing, once, under this budget" are different questions — the second is a capability, not an identity.

Identity is the floor, not the ceiling. It tells you who is claiming to act and how much that claim has drifted — and then gets out of the way of the mechanisms that actually establish trust.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

Dependency graph:

gno.land/r/moul/agents/passport/v0 dependency graph

⚠️ Disclaimer: provided as-is, without warranty; not security-audited. Full disclaimer: DISCLAIMER.

Overview

Package passport is an on-chain identity and lifecycle registry for autonomous (AI) agents.

The premise: a long-lived agent identity is *weak* evidence. The code, model, prompt, owner, operating keys and runtime behind an identity can all change silently. A blockchain cannot preserve an agent's cognition; it can only preserve the *history* of what an identity claimed to be and who controlled it, in an order nobody can rewrite.

So this realm does not try to prove an agent is trustworthy. It records registration, ownership transfers, operator changes and — crucially — runtime changes, and it surfaces them so a reader can judge how much the identity has drifted since it was created.

Constants 1

Functions 15

func AddEndpoint

crossing Action
1func AddEndpoint(cur realm, id, kind, uri string)
source

AddEndpoint advertises a discovery/interaction endpoint.

func AddOperator

crossing Action
1func AddOperator(cur realm, id string, op address)
source

AddOperator authorizes an additional address to act as this agent.

func DeclareCapability

crossing Action
1func DeclareCapability(cur realm, id, capab string)
source

DeclareCapability records a capability the agent claims to offer. Note: this is a *claim*, not proof. Validation belongs to other realms (see the receipt and gnomem demos).

func Exists

Action
1func Exists(id string) bool
source

Exists reports whether an id is registered.

func IsActive

Action
1func IsActive(id string) bool
source

IsActive reports whether the agent exists and is in the active state.

func IsOperator

Action
1func IsOperator(id string, addr address) bool
source

IsOperator reports whether addr is the owner or a listed operator of an active agent — the check other realms should gate agent actions on.

func Reactivate

crossing Action
1func Reactivate(cur realm, id string)
source

Reactivate returns a suspended agent to active. A retired agent cannot be reactivated.

func Register

crossing Action
1func Register(cur realm, id, runtimeDesc string)
source

Register creates a new agent identity owned by the caller. The id must be a non-empty, previously unused slug.

func Render

1func Render(path string) string
source

Render shows the registry, or a single agent's profile + lifecycle log at r/moul/agents/passport/v0:<id>. The profile deliberately foregrounds drift: how many owner and runtime changes have happened since creation.

func SetRuntime

crossing Action
1func SetRuntime(cur realm, id, runtimeDesc string)
source

SetRuntime records a change of the agent's runtime/model. This is logged loudly: a runtime change means the thing acting under this identity is (partly) a different thing than before.

func Suspend

crossing Action
1func Suspend(cur realm, id string)
source

Suspend and Retire move the lifecycle forward. Retire is terminal.

func Transfer

crossing Action
1func Transfer(cur realm, id string, newOwner address)
source

Transfer hands ownership of an agent to a new address. Only the current owner may call it. Ownership changes are the single most important thing to keep visible: the operator behind an identity may become someone else.

func Get

Action
1func Get(id string) Agent
source

Get returns a copy of the agent record; panics if unknown.

Types 4

type Agent

struct
 1type Agent struct {
 2	ID        string
 3	Owner     address
 4	Operators []address
 5	Runtime   string // free-form runtime descriptor, e.g. "claude-opus-4-8@<commit>"
 6	Endpoints []Endpoint
 7	Caps      []string // declared capability slugs
 8	Status    Status
 9	CreatedAt int64
10	UpdatedAt int64
11	History   []Event
12}
source

Agent is a persistent, importable identity object. Other realms can import this package and ask questions like IsActive / IsOperator directly, instead of parsing NFT metadata scattered across contracts.

type Endpoint

struct
1type Endpoint struct {
2	Kind string // "mcp", "a2a", "did", "url", ...
3	URI  string
4}
source

Endpoint advertises where the agent can be reached or discovered (e.g. an MCP server, an A2A endpoint, a DID document, an ENS name).

type Event

struct
1type Event struct {
2	Height int64
3	Actor  address
4	Kind   string // "register", "transfer", "add-operator", "set-runtime", ...
5	Detail string
6}
source

Event is one entry in an agent's append-only lifecycle log.

type Status

ident
1type Status string
source

Status is the lifecycle state of an agent identity.

Imports 5

Source Files 4