Go SDK
The Go SDK is the reference implementation. Every other SDK is byte-for-byte compatible with it.
Install
Section titled “Install”go get github.com/identities-ai/ratify-protocol@v1.0.0-alpha.6The module is github.com/identities-ai/ratify-protocol. Go 1.25+ recommended.
Three minutes, end to end
Section titled “Three minutes, end to end”The example below is the entire protocol in 30 lines. Alice creates her root identity, signs a delegation to her agent, the agent builds a proof bundle, and a verifier runs the verifier algorithm. No HTTP, no servers — just function calls.
package main
import ( "fmt" "time"
"github.com/identities-ai/ratify-protocol")
func main() { // 1. Alice generates her hybrid root identity. alice, alicePriv, _ := ratify.GenerateHumanRootKeypair()
// 2. Her AI agent generates its own hybrid keypair. agent, agentPriv, _ := ratify.GenerateAgentKeypair("Alice's Scheduler", "custom")
// 3. Alice signs a delegation cert for the agent. cert := &ratify.DelegationCert{ Version: 1, IssuerID: alice.ID, IssuerPubKey: alice.PublicKey, SubjectID: agent.ID, SubjectPubKey: agent.PublicKey, Scope: []string{"meeting:attend", "meeting:speak"}, IssuedAt: time.Now().Unix(), ExpiresAt: time.Now().Add(7 * 24 * time.Hour).Unix(), } _ = ratify.IssueDelegation(cert, alicePriv)
// 4. Verifier issues a challenge. Agent signs it. challenge := ratify.GenerateChallenge() challengeAt := time.Now().Unix() challengeSig, _ := ratify.SignChallenge(challenge, challengeAt, agentPriv)
// 5. Agent assembles a proof bundle. bundle := &ratify.ProofBundle{ AgentID: agent.ID, AgentPubKey: agent.PublicKey, Delegations: []*ratify.DelegationCert{cert}, Challenge: challenge, ChallengeAt: challengeAt, ChallengeSig: challengeSig, }
// 6. Verifier runs the verifier. result := ratify.VerifyBundle(bundle, ratify.VerifyOptions{ RequiredScope: "meeting:attend", })
if result.Valid { fmt.Printf("✓ Authorized: %s, granted: %v\n", result.AgentID, result.GrantedScope) } else { fmt.Printf("✗ Rejected: %s — %s\n", result.IdentityStatus, result.ErrorReason) }}Run it: go run main.go. Output: ✓ Authorized: <agent-id>, granted: [meeting:attend meeting:speak].
The full sequence, illustrated
Section titled “The full sequence, illustrated” ┌─────────────┐ ┌─────────────┐ │ Alice │ 1. GenerateHumanRootKeypair │ Verifier │ │ │ 2. IssueDelegation(cert) │ │ │ private │ │ │ │ key on │ │ │ │ her dev │ │ │ └──────┬──────┘ └─────▲───────┘ │ │ │ cert (signed) │ 6. VerifyBundle ▼ │ → Valid + Scope ┌─────────────┐ ┌─────┴───────┐ │ AI Agent │ 3. GenerateAgentKeypair │ │ │ │ 4. SignChallenge(nonce) │ │ │ cert + │ 5. ProofBundle{...} │ │ │ own keys │ ────────────────────────────────▶│ │ └─────────────┘ └─────────────┘
Alice's private key never leaves her device. Agent never sees Alice's private key. Verifier never sees any private key — only public keys + signatures.Verifier-side
Section titled “Verifier-side”If you’re building a Ratify verifier (the receiving party that checks proofs), VerifyBundle
is the entire verifier algorithm in one call:
result := ratify.VerifyBundle(bundle, ratify.VerifyOptions{ RequiredScope: "meeting:attend", // What action is being attempted? RequiredCustomScope: "", // Optional custom: scope NowOverride: nil, // Use real time (test only) RevocationList: revList, // Optional signed revocation list})
// Branch on result.IdentityStatus:switch result.IdentityStatus {case ratify.StatusValid: // ✓ accept the requestcase ratify.StatusBadSignature: // ✗ cert was tampered after signingcase ratify.StatusExpired: // ✗ cert is past its expires_atcase ratify.StatusScopeDenied: // ✗ requested scope not in granted chaincase ratify.StatusRevoked: // ✗ matched a revocation list entrycase ratify.StatusReplay: // ✗ challenge is older than the freshness window}The verifier is fail-closed by default. Any error path returns “not valid” — you cannot accidentally accept a malformed bundle.
Constraints (geo / time / version)
Section titled “Constraints (geo / time / version)”If the delegation has constraints, pass the runtime context:
result := ratify.VerifyBundle(bundle, ratify.VerifyOptions{ RequiredScope: "physical:move", Context: &ratify.VerifyContext{ Location: &ratify.GeoPoint{Lat: 37.77, Lon: -122.41}, // Verifier's location Now: time.Now(), Version: "agent-fw-1.2.3", },})The verifier will reject the bundle if the agent is outside the allowed geo radius, outside the allowed time window, or running a version excluded by the constraint. See Constraints for the full constraint vocabulary.
Sub-delegation
Section titled “Sub-delegation”Agent-to-agent delegation is the same primitive. Agent-A delegates to Agent-B; the bundle just carries two certs:
// Agent-A signs a sub-delegation to Agent-BsubCert := &ratify.DelegationCert{ Version: 1, IssuerID: agentA.ID, IssuerPubKey: agentA.PublicKey, SubjectID: agentB.ID, SubjectPubKey: agentB.PublicKey, Scope: []string{"meeting:attend"}, // Subset of what A was given IssuedAt: now, ExpiresAt: now + 24*3600,}ratify.IssueDelegation(subCert, agentAPriv)
// Agent-B's bundle now has two delegations (the chain)bundle := &ratify.ProofBundle{ AgentID: agentB.ID, AgentPubKey: agentB.PublicKey, Delegations: []*ratify.DelegationCert{cert, subCert}, // chain: Alice → A → B Challenge: challenge, ChallengeAt: challengeAt, ChallengeSig: agentBSignature,}
// Verifier checks the WHOLE chain. Effective scope is the intersection.result := ratify.VerifyBundle(bundle, ratify.VerifyOptions{RequiredScope: "meeting:attend"})Effective scope is the intersection across all links. Agent-B can never get more than Agent-A was given, which can never be more than Alice gave Agent-A.
Running the conformance suite
Section titled “Running the conformance suite”cd ratify-protocolgo test ./...If you see ok github.com/identities-ai/ratify-protocol, all 59 fixtures passed and your
implementation is byte-for-byte interoperable with every other Ratify SDK.
The repo also ships a ratify CLI for human use — create identities, sign delegations,
verify bundles, list the canonical scopes:
go build -o /tmp/ratify ./cmd/ratify/tmp/ratify --helpCommon workflows:
# Create a HumanRoot identity (writes to ~/.ratify/)ratify init
# Generate an agent keypairratify agent-init
# Sign a delegationratify delegate \ --agent-pubkey-file agent-pubkey.json \ --scope "meeting:attend,meeting:speak" \ --days 7 \ --out delegation.json
# Verify a bundleratify verify bundle.json
# Print the canonical 52-scope vocabularyratify scopesWhere to next
Section titled “Where to next”- Protocol concepts — the deep dive on every primitive
- Constraints — geo/time/version gating
- Revocation — signed revocation lists
- Integration guides — surface-specific patterns