{"slug": "aroha-signed-shrinking-permissions-for-ai-agents-checked-offline", "title": "Aroha – signed, shrinking permissions for AI agents, checked offline", "summary": "Aroha Labs released Aroha Mandates, a protocol that gives orchestrator agents cryptographically enforceable control over sub-agents through signed, narrowing permission chains verified offline. In the published example, a human issues an IntentMandate to an orchestrator capped at $500 and a 1-hour TTL for merchant category 4511 (airlines), and the orchestrator attenuates that to $300 for a flight agent; a link that widens scope or is signed by anyone other than its grantor fails verification. The protocol works alongside MCP, A2A and identity providers, pushes revocations to verifiers via a registry witness, and issues a signed receipt for every allowed or refused action.", "body_md": "**Cryptographically bounded authority for every agent in the chain.**\n\nAroha Mandates give orchestrators cryptographically enforceable control over every sub-agent they delegate to. No agent can exceed the scope it was granted.\n\n[Docs](https://www.aroha-labs.com/docs/) · [Support matrix](https://github.com/ArohaLabs/aroha-protocol/blob/main/docs/support-matrix.md) · [Local sandbox](https://github.com/ArohaLabs/aroha-protocol/blob/main/docs/sandbox.md) · [Support](https://github.com/ArohaLabs/aroha-protocol/blob/main/SUPPORT.md) · [Spec](https://github.com/ArohaLabs/aroha-protocol/blob/main/docs/spec/aroha-1.0.md)\n\n``` js\nimport { generateKeyPair, generateDid } from \"@aroha-sdk/core\";\nimport { issueIntentMandate, attenuateToPayment, verifyMandateChain } from \"@aroha-sdk/credentials\";\n\nconst human = await generateKeyPair();\nconst orchestrator = await generateKeyPair();\nconst flightAgent = await generateKeyPair();\n// Content-addressed DIDs (did:aroha:z…) commit to their own public key,\n// so a verifier needs no registry lookup to check signatures.\nconst humanDID = generateDid(human.publicKey);\nconst orchestratorDID = generateDid(orchestrator.publicKey);\nconst flightAgentDID = generateDid(flightAgent.publicKey);\n\n// Human issues an intent mandate to the orchestrator ($500, 1 hour TTL)\nconst intent = await issueIntentMandate(\n  humanDID, orchestratorDID,\n  { spendLimitUsd: 500, merchantCategory: \"4511\" }, // MCC 4511 = airlines\n  human.privateKey,\n  3_600_000,\n);\n\n// Orchestrator attenuates scope downward to the flight agent ($300 of the $500).\n// The child token embeds the signed chain back to the human.\nconst payment = await attenuateToPayment(\n  intent, flightAgentDID,\n  { spendLimitUsd: 300, merchantCategory: \"4511\" },\n  orchestrator.privateKey,\n);\n\n// Flight agent verifies every link back to the human root before acting\nconst result = await verifyMandateChain(payment.token, undefined, {\n  expectedRoot: humanDID,          // the human authority must come from\n  expectedGrantee: flightAgentDID, // the flight agent itself\n});\n// result.valid === true, result.chainVerified === true,\n// result.mandate?.constraints.spendLimitUsd === 300.\n// A link that widens scope, or is signed by anyone but its grantor, fails.\n```\n\nAgents now act for people and hand work to other agents and tools, often run by other companies. MCP and A2A connect them; identity providers name them. Nothing that travels with the work proves what each agent was allowed to do, stops the whole chain when the person changes their mind, or leaves a record anyone else can check.\n\n| Approach | What you get today | \n|---|---|\n| **Per-hop credentials** (API keys, OAuth tokens) | Each hop enforces its own key. The person's limit, purpose and expiry are lost along the way. | \n| **Framework guardrails** | Checks inside one codebase. Nothing survives the hop to another vendor's agent. | \n| **Aroha Mandates** | A signed chain back to the person. Scope can only narrow. Any verifier checks it offline; revocation is pushed; every action, allowed or refused, gets a signed receipt. | \n\nAroha answers four questions for every action: **who is acting, what were they allowed to do, can it be stopped, and what actually happened.** It works with MCP, A2A and your identity provider rather than replacing them. See [what Aroha is (and is not)](https://github.com/ArohaLabs/aroha-protocol/blob/main/docs/positioning.md).\n\n1. **Human issues a mandate** — signs an`IntentMandate` with authorized actions, a spending cap, and a TTL. Cryptographically bound to the orchestrator's DID.\n2. **Orchestrator attenuates** — delegates a strict subset of that scope to the next agent. The new mandate is signed by the orchestrator. Scope narrows, never widens.\n3. **Every agent verifies** — before acting, an agent verifies the mandate chain back to its human origin, offline. A forged, altered, widened or expired link fails verification.\n4. **Revoke and prove** — the person can revoke at any time; the registry witness pushes the revocation to verifiers. Every allowed or refused action produces a signed receipt.\n5. **Deploy in your existing stack** — bridges for MCP, LangChain, A2A, and Composio. Mandate verification drops in in two lines.\n\n```\nCore — the four questions\n├── @aroha-sdk/core           Identity (did:aroha), signed envelopes, receipts, conversation profile\n├── @aroha-sdk/credentials  ★ Start here — mandates, attenuation, chain verification, revocation\n├── @aroha-sdk/delegation     Multi-hop delegation with depth limits and stitched receipts\n└── @aroha-sdk/policy         Deterministic limits checked before any model sees a request\n\nAdapters (use Aroha from the stack you already run)\n├── @aroha-sdk/mcp-server     Remote MCP server (2026 authorization spec)\n├── @aroha-sdk/mcp-guard      Mandate checks in front of any MCP server\n├── @aroha-sdk/mcp-bridge     MCP ↔ Aroha  (includes wrapMcp() one-liner)\n├── @aroha-sdk/a2a-bridge     A2A ↔ Aroha\n└── @aroha-sdk/langchain-bridge  LangChain / OpenAI functions ↔ Aroha\n\nExtensions (maintained, optional; developed outside this repository)\n└── orchestrator (sagas) · settlement · commerce · reputation\n\nTooling\n├── @aroha-sdk/cli            scaffold · convert · doctor · dev sandbox\n└── create-aroha-agent        npx create-aroha-agent — zero-config scaffolder\njs\nimport { verifyMandateChain } from \"@aroha-sdk/credentials\";\n\n// In your agent's request handler. HUMAN_ROOT_DID is the human you accept authority from;\n// MY_DID is this agent's own DID. The mandate travels in the signed Aroha envelope body\n// (`credentialToken`); over MCP it travels in `_meta[\"aroha/mandate\"]` with a holder proof\n// (see @aroha-sdk/mcp-bridge). There is no mandate HTTP header.\nconst { valid, chainVerified, mandate, reason } = await verifyMandateChain(\n  envelope.body.credentialToken,\n  undefined, // default resolver: content-addressed did:aroha:z… DIDs\n  { expectedRoot: process.env.HUMAN_ROOT_DID, expectedGrantee: MY_DID },\n);\nif (!valid || !chainVerified) {\n  res.status(403).json({ error: reason });\n} else {\n  // mandate.constraints.spendLimitUsd, mandate.constraints.merchantCategory, etc.\n}\n```\n\n**Already have an MCP server?** Add one import:\n\n``` js\nimport { wrapMcp, registryPublicKeyResolver } from \"@aroha-sdk/mcp-bridge\";\n\nconst agent = await wrapMcp(server.listTools(), {\n  name: \"my-tools\",\n  price: 0.01,\n  resolvePublicKey: registryPublicKeyResolver(), // verifies who is calling\n  handlers: { search: async (args) => ({ content: [{ type: \"text\", text: await search(args) }] }) },\n});\nawait agent.start();\n// ✓ did:aroha:my-tools  →  http://localhost:3001\n```\n\n**Using LangChain?** Call any mandate-aware Aroha agent as a native tool:\n\n``` js\nimport { createArohaLangChainTool } from \"@aroha-sdk/langchain-bridge\";\n\nconst tool = await createArohaLangChainTool(\n  \"http://localhost:3001\",\n  \"search-flights\",\n  \"Search available flights by origin, destination, and date\"\n);\n// plug `tool` straight into AgentExecutor, createOpenAIFunctionsAgent, etc.\n```\n\n**Using an AI coding agent?** Point it at the [`aroha-integrate`](https://github.com/ArohaLabs/aroha-protocol/blob/main/skills/aroha-integrate/SKILL.md) Agent Skill (or [`docs/llms.txt`](https://github.com/ArohaLabs/aroha-protocol/blob/main/docs/llms.txt)): it picks the smallest integration path for your code, applies it, and checks that out-of-scope calls are refused.\n\n**Scaffold a new agent pre-wired for mandate verification:**\n\n```\nnpx create-aroha-agent my-agent\ncd my-agent && npm install && npm run dev\n# → [my-agent] did:aroha:my-agent  http://localhost:3001/aroha/v1  Ready ✓\naroha init my-agent              # interactive scaffold\naroha init my-agent --yes        # zero-config: picks all defaults, writes .env\naroha convert --from mcp --dir . # wrap existing agent\naroha doctor [endpoint]          # check environment + connectivity\naroha dev                        # local dev registry + dashboard\n```\n\nOne-click templates for fast deployment.\n\n**Note:** the Vercel and Cloudflare buttons clone from `github.com/ArohaLabs/aroha-protocol`. You can\nalso copy the template directory from a checkout and deploy it with the platform CLI.\n\n| Platform | Button | \n|---|---|\n| Vercel |  | \n| Cloudflare |  | \n| Railway | No published template yet; manual setup in [examples/railway](https://github.com/ArohaLabs/aroha-protocol/blob/main/examples/railway/README.md) | \n| Render | No one-click button (Render needs `render.yaml` at a repo root); Blueprint steps in[examples/render](https://github.com/ArohaLabs/aroha-protocol/blob/main/examples/render/README.md) | \n\n```\npackages/               SDK packages (@aroha-sdk/*)\nagents/mock-provider-agent/ Reference provider agent for interoperability tests\nexamples/               Deployment templates (Vercel, Cloudflare, Railway, Render)\nexamples/sandbox-agents/ Pre-built sandbox agents (flight, hotel, weather, web-search, summarizer)\ncontracts/              Solidity contracts (ArohaRegistry, ArohaEscrow, ArohaReputation)\ndocs/                   MkDocs documentation site\n```\n\nThe Aroha runtime (desktop app) is developed in a separate, private repository and has not been released. The saga, settlement, commerce and reputation extensions are also developed outside this repository; they stay published on npm.\n\n| Requirement | Version | \n|---|---|\n| Node.js | ≥ 22 | \n| npm | ≥ 10 | \n\nFoundry and Python are only needed for the smart contract demo and MkDocs docs site respectively.\n\nUse [GitHub Issues](https://github.com/ArohaLabs/aroha-protocol/issues) for bugs and feature requests and\n[GitHub Discussions](https://github.com/ArohaLabs/aroha-protocol/discussions) for questions and ideas,\nor email the maintainer listed in [MAINTAINERS.md](https://github.com/ArohaLabs/aroha-protocol/blob/main/MAINTAINERS.md).\nSee [CONTRIBUTING.md](https://github.com/ArohaLabs/aroha-protocol/blob/main/CONTRIBUTING.md) (commits need a DCO sign-off) and [SUPPORT.md](https://github.com/ArohaLabs/aroha-protocol/blob/main/SUPPORT.md).\nFor security issues, see [SECURITY.md](https://github.com/ArohaLabs/aroha-protocol/blob/main/SECURITY.md).\n\n```\nnpm install && npm run build && npm test\n```\n\n", "url": "https://wpnews.pro/news/aroha-signed-shrinking-permissions-for-ai-agents-checked-offline", "canonical_source": "https://github.com/ArohaLabs/aroha-protocol", "published_at": "2026-10-27 00:43:16+00:00", "updated_at": "2026-10-27 01:11:43.063673+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-safety", "developer-tools"], "entities": ["Aroha Labs", "Aroha Mandates", "Aroha", "MCP", "A2A", "@aroha-sdk/core", "@aroha-sdk/credentials"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/aroha-signed-shrinking-permissions-for-ai-agents-checked-offline", "markdown": "https://wpnews.pro/news/aroha-signed-shrinking-permissions-for-ai-agents-checked-offline.md", "text": "https://wpnews.pro/news/aroha-signed-shrinking-permissions-for-ai-agents-checked-offline.txt", "jsonld": "https://wpnews.pro/news/aroha-signed-shrinking-permissions-for-ai-agents-checked-offline.jsonld"}}