Getting Started
Install Kanoniv Auth, generate a root keypair, delegate scoped authority to an agent, and verify your first action. The entire flow takes five minutes.
Install
pip install kanoniv-authcargo install kanoniv-agent-auth --features clinpm install @kanoniv/agent-authThe Python package includes both the library and the kanoniv-auth CLI. The Rust crate requires the cli feature flag for the binary.
Generate Root Keys
The root keypair is the master authority. Every delegation chain starts here.
kanoniv-auth init
# Root key generated.
# DID: did:agent:5e06a3...
# Path: ~/.kanoniv/root.key
#
# WARNING: Treat this like an SSH key. Don't share it.from kanoniv_auth import init_root
root = init_root() # Returns KeyPair, saves to ~/.kanoniv/root.key
print(root.did) # did:agent:5e06a3...use kanoniv_agent_auth::AgentKeyPair;
let root = AgentKeyPair::generate();
println!("{}", root.identity().did); // did:agent:5e06a3...import { generateKeyPair } from "@kanoniv/agent-auth";
const root = generateKeyPair();
console.log(root.identity.did); // did:agent:5e06a3...WARNING
The root key file at ~/.kanoniv/root.key contains your private key. Treat it like an SSH key. Do not commit it to version control or share it.
Delegate Authority
Issue a scoped, time-bounded delegation token. The --name flag gives the agent a persistent identity - same name produces the same DID across sessions.
kanoniv-auth delegate --scopes code.edit,test.run --ttl 4h --name my-agentfrom kanoniv_auth import delegate
token = delegate(
scopes=["code.edit", "test.run"],
ttl="4h",
name="my-agent",
)use kanoniv_agent_auth::{AgentKeyPair, Delegation, Caveat};
let root = AgentKeyPair::generate();
let agent = AgentKeyPair::generate();
let delegation = Delegation::create_root(&root, &agent.identity().did, vec![
Caveat::ActionScope(vec!["code.edit".into(), "test.run".into()]),
Caveat::ExpiresAt("2026-03-27T00:00:00Z".into()),
]).unwrap();import { generateKeyPair, createRootDelegation } from "@kanoniv/agent-auth";
const root = generateKeyPair();
const agent = generateKeyPair();
const delegation = createRootDelegation(root, agent.identity.did, [
{ type: "action_scope", value: ["code.edit", "test.run"] },
{ type: "expires_at", value: "2026-03-27T00:00:00Z" },
]);The token is a base64url-encoded JSON blob containing the delegation chain, agent DID, scopes, expiry, and the agent's embedded private key (for sub-delegation and signing). Tokens are saved automatically to ~/.kanoniv/tokens/.
Verify
Check whether a delegation token authorizes a specific action. Verification is offline - no server calls, no network required.
kanoniv-auth verify --scope code.edit
# VERIFIED
# Agent: did:agent:5e06a3...
# Root: did:agent:a1b2c3...
# Scopes: ['code.edit', 'test.run']
# Expires: 3.9h remaining
# Chain: 1 link(s)from kanoniv_auth import verify
result = verify(action="code.edit", token=token)
# Returns:
# {
# "valid": True,
# "agent_did": "did:agent:5e06a3...",
# "root_did": "did:agent:a1b2c3...",
# "scopes": ["code.edit", "test.run"],
# "expires_at": 1743091200.0,
# "ttl_remaining": 14399.5,
# "chain_depth": 1,
# }The CLI exits with code 0 on success and code 1 on denial. In Python, a denied action raises ScopeViolation:
from kanoniv_auth import verify, ScopeViolation
try:
verify(action="deploy.prod", token=token)
except ScopeViolation as e:
print(e) # scope 'deploy.prod' not granted. has: ['code.edit', 'test.run']INFO
Scopes are hierarchical. A token with git.push grants git.push.myrepo.main. A token with git.push.myrepo grants git.push.myrepo.main but not git.push.other. See Caveats for the full scope resolution rules.
Sign an Execution Envelope
After performing an action, sign a proof that records what happened. The envelope includes the action, target, result, and the agent's signature over the entire payload.
kanoniv-auth sign --action code.edit --target src/main.py --result successfrom kanoniv_auth import sign
envelope = sign(
action="code.edit",
token=token,
target="src/main.py",
result="success",
)The signed envelope is a base64url-encoded JSON structure containing the agent DID, action, target, result, timestamp, scopes, chain depth, signature, and the full delegation chain. Anyone with the agent's public key can verify it.
The Exec Shortcut
exec combines verify, execute, and sign into a single command. If the scope check fails, the command never runs. If it succeeds, the result is signed automatically.
kanoniv-auth exec --scope deploy.staging -- ./deploy.sh staging
# AUTHORIZED (deploy-bot)
# Scope: deploy.staging
# Agent: did:agent:5e06a3...
#
# $ ./deploy.sh staging
# Deploying to staging...
# Done.
#
# SIGNED (result=success)If the scope is not granted:
kanoniv-auth exec --scope deploy.prod -- ./deploy.sh prod
# DENIED
# scope 'deploy.prod' not granted. has: ['deploy.staging']The command never executes. Exit code 1.
Check Status
Quick check on the active delegation - agent name, scopes, and time remaining.
kanoniv-auth status
# ACTIVE
# Agent: my-agent
# DID: did:agent:5e06a3...
# Scopes: code.edit, test.run
# TTL: 3.8hIf the token has expired:
kanoniv-auth status
# EXPIRED
# Agent: my-agent
# Died: 23m ago
#
# Re-delegate:
# kanoniv-auth delegate --name my-agent --scopes code.edit,test.run --ttl 4hToken Resolution Order
When you run a CLI command without --token, the CLI resolves the token in this order:
--tokenflag (explicit token string)--agentflag (loads the most recent token for that named agent from~/.kanoniv/tokens/)KANONIV_TOKENenvironment variable~/.kanoniv/tokens/latest.token(the most recently issued token)
Next Steps
- Claude Code Skills - Five skills that scope-enforce Claude Code sessions
- Delegation Chains - Sub-delegation, chain depth, and authority flow
- Caveats - All six caveat types and scope narrowing rules
- Keypairs - Key management, named agents, and persistent identity
- Verification - How chain verification works offline
