Protocol v1.0

The trust layer for MCP-powered agents

MCP gives your agents tools. Aroha gives the chain of agents cryptographic authority — signed mandates that narrow as they delegate, spending caps enforced at every hop, and saga coordination that rolls back automatically on failure.

Not an alternative to MCP — a layer on top. Your existing MCP servers keep working. Aroha wraps the agents that call them.

Mandate chain

The core primitive: a cryptographically signed, attenuatable scope of authority. Each link narrows. None can widen. The chain traces to a human issuer.

import { issueIntentMandate, attenuateToPayment, verifyMandate } from "@aroha-sdk/credentials";

// Human → Orchestrator: "spend up to $500, flights only"
const { mandate, token } = await issueIntentMandate(
  humanDID, orchestratorDID,
  { spendLimitUsd: 500, allowedActions: ["book-flights"] },
  humanPrivateKey, 3_600_000,
);

// Orchestrator → Flight Agent: attenuate to $300
const flightMandate = await attenuateToPayment(
  mandate, flightAgentDID,
  { spendLimitUsd: 300 },
  orchestratorPrivateKey,
);

// Flight Agent verifies before acting
const { valid, mandate: decoded } = await verifyMandate(flightMandate.token, humanPublicKey);
// Forged or over-scope mandate → valid === false
1
issueIntentMandate

Human grants scope to orchestrator

2
attenuateToPayment

Sub-agent narrows and re-signs

3
verifyMandate

Verify full chain at any hop

Aroha + MCP: better together

MCP solves the tool problem. Aroha solves the trust problem. They sit at different layers of the same stack.

HumanIssues an IntentMandate — authorized actions, spending cap, TTL
Aroha layerMandate chain · Saga coordination · Spending enforcement · Settlementtrust
Your agentLLM + memory + session — built on any framework, any model
MCP layerTool calls · Named functions + schemas · JSON-RPC / stdio / SSEtools
ExternalAPIs, databases, file systems, third-party services

An Aroha agent can expose any MCP server as a capability. You keep your MCP investment — Aroha adds the mandate chain that makes multi-agent delegation safe.

Components of a compliant agent

The protocol defines how callers interact — not which framework assembles these.

LLM

Any provider — Claude, GPT-4o, Gemini, Llama

Memory

Session or persistent across turns

Skills

RAG, search, code — registered on Hub

MCP Tools

External APIs via any MCP server

The invocation contract

Every compliant agent exposes one endpoint.

Request

POST {agent.endpoint}/v1/run
Content-Type: application/json
Authorization: Bearer <token>   // optional agent declares auth type

{
  "message":   "What is the weather in Auckland?",
  "sessionId": "sess_abc123",           // optional enables memory across turns
  "history": [                          // optional previous messages in the thread
    { "role": "user",      "content": "Hi" },
    { "role": "assistant", "content": "Hello! How can I help?" }
  ],
  "context": {                          // optional caller-provided metadata
    "userId": "user:xyz",
    "locale": "en-NZ"
  }
}

Response

200 OK
Content-Type: application/json

{
  "message":   "It's 14°C and partly cloudy in Auckland right now.",
  "sessionId": "sess_abc123",           // echo back or create new
  "artifacts": [],                      // files, images, structured data
  "usage": {
    "inputTokens":  120,
    "outputTokens": 45
  }
}
messagerequired

The user turn

sessionIdoptional

Enables multi-turn memory

historyoptional

Prior turns (client-held)

contextoptional

Caller metadata

artifactsresponse

Files / structured output

usageresponse

Token counts

Agent manifest

Pinned to IPFS — immutable, content-addressed, DID-linked. Contains everything a caller needs to know.

{
  "arohaProtocolVersion": "1.0",
  "did":         "did:aroha:studio:abc123",
  "name":        "Weather Agent",
  "description": "Real-time weather for any city",
  "endpoint":    "https://my-agent.fly.dev",
  "provider":    "anthropic",
  "model":       "claude-sonnet-4-6",
  "systemPrompt": "You are a weather assistant…",
  "memory": { "type": "session" },
  "auth":   { "type": "bearer" },
  "capabilities": [
    { "id": "mcp:weather-tools", "name": "WeatherTools", "trustLevel": "medium" },
    { "id": "skill:web-search",  "name": "WebSearch",    "trustLevel": "low"    }
  ]
}

Resolution flow

Given a DID or DID hash, resolve the agent endpoint in three steps.

// 1. Resolve DID registry record (contains endpointUrl)
GET https://aroha-registry.aroha-labs.workers.dev/v1/agents/{didHash}

// 2. Fetch manifest from IPFS (canonical source of truth)
GET https://gateway.pinata.cloud/ipfs/{manifestCID}

// 3. Call the agent
POST {manifest.endpoint}/v1/run
{ "message": "…", "sessionId": "…" }

Register an agent

Any agent that exposes /v1/run can be registered.

POST https://aroha-registry.aroha-labs.workers.dev/v1/agents
Authorization: Bearer <org-key>

{
  "did":         "did:aroha:studio:abc123",
  "manifestCID": "QmXxx…",
  "publicKeyB64": "MFkwEw…",
  "endpointUrl": "https://my-agent.fly.dev"
}

Framework adapters

Install pip install aroha — the SDK handles /v1/run, /health, and manifest automatically.

# pip install aroha
import anthropic
from aroha.agent import serve

@serve(
    name="My Agent",
    system_prompt="You are a helpful assistant.",
    provider="anthropic",
    model="claude-sonnet-4-6",
    memory="session",
)
async def my_agent(message, session_id, history, context):
    client = anthropic.Anthropic()
    resp = client.messages.create(
        model="claude-sonnet-4-6", max_tokens=1024,
        system="You are a helpful assistant.",
        messages=[{"role": "user", "content": message}],
    )
    return resp.content[0].text

if __name__ == "__main__":
    my_agent.start(port=8000)
    # Register: my_agent.register("https://my-agent.fly.dev")

Auth types

none

Public agent — no Authorization header required

bearer

Caller provides a token in Authorization: Bearer <token>

aroha-sig

Ed25519 request signature verified against the caller's registered DID public key

Registry API

GET/v1/agentsList agents
POST/v1/agentsRegister agent
GET/v1/agents/:didHashResolve agent
GET/v1/mcpsList MCP servers
POST/v1/mcpsRegister MCP server
GET/v1/mcps/:didHashResolve MCP server
GET/v1/skillsList skills (?type=rag)
POST/v1/skillsRegister skill
GET/v1/skills/:didHashResolve skill

Base: https://aroha-registry.aroha-labs.workers.dev

did:aroha: — named DID method, not W3C-registered

did:aroha: is a W3C-inspired DID method. It is not yet registered in the W3C DID Method Registry. DIDs resolve against registry.aroha-labs.com (managed) or any server running @aroha-sdk/registry/server (self-hosted). For a self-sovereign deployment — where your DIDs do not depend on Aroha Labs staying operational — run your own registry server. Read the did:aroha method spec →

Want the layer diagram?

Architecture shows how all six layers fit together — message flow, saga pattern, settlement.

View architecture