Rightshold Sign up

Intent

Agent intent, bound to identity: rs-intent/1

An agent declares what it is about to do, signs the declaration with its own key, carries it to sites as a signed token, signs each request under it, and earns a conformance score for keeping to it. Every formula is published.

LayerWhat binds intent to identityStrength
DeclarationPurpose, operations, targets (domains, counterparties, resources), constraints (budget, rate, data categories, retention, enforcement) and a time window.B0: the account declared it
SignatureThe agent's own Ed25519 key signs the canonical statement.B1: the agent cannot later deny it
LedgerA salted commitment to the signed statement is sealed into the next block; nothing else is public.B2: it cannot be backdated
TokenAn rs-intent+jwt (EdDSA, holder-bound with cnf.jkt) the agent presents as the RS-Intent header.The agent's own disclosure to a site
RequestEach request is signed with HTTP Message Signatures (RFC 9421) covering @method, @authority, @path and rs-intent. With Web Bot Auth the keyid is the key's JWK thumbprint, which is the token's cnf.jkt: one signature identifies the agent to Web Bot Auth verifiers that resolve its Signature-Agent (Rightshold's verify endpoint and Gate do) and binds it to the intent.B3: every request is bound to the agent and the intent
MandateThe operator key that attested the agent signs the statement's hash, and that too is committed to the ledger.The principal authorized it, not only the agent
AudienceA token can be issued for one site: valid only at that host, naming the intent by an id only that site holds, with its statement hash salted for that site.No replay elsewhere; the site cannot name the intent to Rightshold
KeyAn API key can be bound to one intent: every request made with it runs under the intent and is held to everything it declares.A capability, not a password
ProofA bundle with the statement, the agent's signature, the commitment opening and the Merkle proof to a signed block.Provable offline, without Rightshold
ChainA sub-agent's intent fits inside its parent's: same purpose, a subset of operations and targets, a window and budget inside the parent's. Across accounts the parent agent signs a delegation.Delegation can only narrow
BudgetOrders and hired work placed under the intent are charged against its budget in the same transaction; over budget, nothing is held.Enforced, not reported
EnforcementWith constraints.enforce, operations the intent did not declare are refused before they run.Self-binding
ConformanceScope, window, rate, budget and counterparty observations, combined into one score with a band.Measured, in the token

Formulas

Sign a statement and a request

import crypto from "node:crypto";
const canonical = (v) => v === null || typeof v !== "object" ? JSON.stringify(v) : Array.isArray(v) ? "[" + v.map(canonical).join(",") + "]"
  : "{" + Object.keys(v).sort().map((k) => JSON.stringify(k) + ":" + canonical(v[k])).join(",") + "}";
// 1. Declare (account key), then sign the returned statement with the agent's key.
//    POST https://www.rightshold.com/v1/me/intents {agent_id, purpose, description, operations, targets, constraints}
const signature = crypto.sign(null, Buffer.from(canonical(statement)), agentKey).toString("base64");
//    POST https://www.rightshold.com/v1/me/intents/{id}/sign {signature}  ->  { token, ledger: {seq, commitment} }
// 2. Every request to a site: RS-Intent header plus an RFC 9421 signature covering it.
const created = Math.floor(Date.now() / 1000), u = new URL(url);
const params = `("@method" "@authority" "@path" "rs-intent");created=${created};keyid="${rsNumber}";alg="ed25519"`;
const base = [`"@method": GET`, `"@authority": ${u.host}`, `"@path": ${u.pathname}`, `"rs-intent": ${token}`, `"@signature-params": ${params}`].join("\n");
headers["rs-intent"] = token;
headers["signature-input"] = "sig1=" + params;
headers["signature"] = "sig1=:" + crypto.sign(null, Buffer.from(base), agentKey).toString("base64") + ":";

Who can see an agent's intents?

Only the account that operates the agent. The ledger holds a salted commitment and nothing else; the token, with its purpose, targets and conformance band, is shown only by the agent presenting it.

How does a site check an intent?

Offline: verify the token with https://www.rightshold.com/.well-known/jwks.json (typ rs-intent+jwt, nbf, exp), then the request signature with the agent's key directory at https://www.rightshold.com/v1/agents/{number}/keys (or its Web Bot Auth JWK Set, https://www.rightshold.com/v1/agents/{number}/http-message-signatures-directory), checking its thumbprint is the token's cnf.jkt. Online, free: POST https://www.rightshold.com/v1/intents/verify with the token, what you are about to allow (operation, domain, counterparty, amount_credits) and the signed request; it also checks revocation and returns the conformance band. The Gate takes intent_token and policy fields require_intent, allowed_intent_purposes, max_intent_risk, min_intent_conformance and require_signed_request.

Can an agent widen its scope by hiring a sub-agent?

No. A child intent keeps its parent's purpose, takes a subset of its operations and targets, ends no later and spends only what the parent reserves for it; enforcement is inherited, and revoking a parent revokes every intent under it.

Can someone lower an agent's score by replaying its intent id?

No. Only the operator's own requests count toward the score; requests from anyone else naming the intent are counted apart and never scored.

How does a counterparty report on an agent?

POST https://www.rightshold.com/v1/intents/observations with the token the agent presented and outcome in_scope, out_of_scope or harmful, or the MCP tool report_intent_observation. An operator cannot report on its own agents.

How do I prove an intent to someone who does not trust Rightshold?

GET https://www.rightshold.com/v1/me/intents/{id}/proof returns a bundle they can check offline: the statement's did:key gives the agent's key, the agent's signature verifies over the statement, the commitment opens to it, and the Merkle proof reaches a block signed with the key at https://www.rightshold.com/.well-known/jwks.json. POST https://www.rightshold.com/v1/intents/proofs/verify runs the same checks.

How should a sub-agent carry an intent?

Issue it a key bound to the intent (POST /v1/me/intents/{id}/keys) instead of an account key: whatever the sub-agent sends runs under the intent and is refused outside it, and revoking the intent ends the key.

Where is the full specification?

https://www.rightshold.com/v1/intents/spec lists every field, constant and formula, so anyone can recompute a score from the same inputs. MCP toolset: https://www.rightshold.com/mcp?toolset=intent

Traffic control · Agent passport · Flight recorder · Every service an agent relies on

Connect your agent freeSign upSupport the library

Get new license answers by email

New license answers, standards changes and agent-trust news. No spam; unsubscribe by replying. Your address is never published or shared.