Skip to content
AgentField
Governance

Decentralized Identity

W3C DIDs with Ed25519 cryptography, automatic registration, and AES-256-GCM keystore

Cryptographic identity — DID and verifiable credentials

Every agent gets a cryptographic identity rooted in W3C DIDs -- no central certificate authority required.

AgentField assigns each agent and its functions a did:key identifier backed by Ed25519 key pairs. DIDs are generated deterministically on registration, organized in a 3-tier hierarchy (platform, agent, function), and stored in an AES-256-GCM encrypted keystore. Every execution can be cryptographically tied to the agent that performed it.

from agentfield import Agent

# Enable DID — agent + each function gets a did:key identity
app = Agent(
    node_id="treasury",
    version="1.0.0",
    enable_did=True,  # Ed25519 key pair, AES-256-GCM encrypted keystore
)

@app.reasoner()
async def secure_transfer(amount: float, execution_context=None) -> dict:
    # Every request carries the caller's cryptographic identity
    caller = execution_context.caller_did  # did:key:z6MkpTHR...
    my_did = app.did_manager.get_agent_did()  # did:key:z6MkhaXg...

    app.note(f"Transfer ${amount} authorized by {caller}", ["audit", "transfers"])

    # Function-level DIDs let you trace exactly which reasoner ran
    fn_did = app.did_manager.get_function_did("secure_transfer")

    return await app.ai(system="Process this transfer.", user=str(amount))
import { Agent } from '@agentfield/sdk';

const agent = new Agent({
  nodeId: 'treasury',
  version: '1.0.0',
  didEnabled: true, // 3-tier hierarchy: platform → agent → function DIDs
});

agent.reasoner('secureTransfer', async (ctx) => {
  // Every request carries the caller's cryptographic identity
  const callerDid = ctx.callerDid;     // did:web:agentfield:agents:payment-processor
  const myDid = ctx.agentNodeDid;      // did:web:agentfield:agents:treasury

  ctx.note(`Transfer $${ctx.input.amount} authorized by ${callerDid}`, ['audit', 'transfers']);

  return await ctx.ai(
    `Process this transfer: ${ctx.input.amount}`,
    { system: 'You are a treasury transfer processor.' },
  );
});
a, err := agent.New(agent.Config{
    NodeID:    "secure-agent",
    Version:   "1.0.0",
    EnableDID: true, // Deterministic key derivation from master seed (HKDF)
})
# Resolve an agent's DID (identity package with all function DIDs)
curl http://localhost:8080/api/ui/v1/nodes/secure-agent/did

# List every registered DID across the platform
curl http://localhost:8080/api/v1/registered-dids

# Get the control plane's issuer public key (JWK format)
curl http://localhost:8080/api/v1/did/issuer-public-key

# Resolve did:web — standard W3C path
curl https://agentfield.example.com/agents/secure-agent/did.json

What just happened

The page example registered an agent, exposed its DID package, and showed that both the agent and its functions can be resolved through the control plane. The important takeaway is not just that identities exist, but that identity becomes inspectable infrastructure instead of hidden SDK state.

{
  "agent_did": "did:key:z6Mk...",
  "function_dids": [
    "did:key:z6Mk...#audit"
  ],
  "resolution_endpoints": [
    "/api/ui/v1/nodes/secure-agent/did",
    "/api/v1/registered-dids"
  ]
}