Back to Docs

Framework Bridges

Aroha agents can be called from — and can call into — any major agent framework. Bridges are pure adapters: they translate message formats without changing Aroha protocol semantics.

Overview

Hermes Agent
@aroha-sdk/hermes-bridge
MCP stdio server — Hermes forks it as a subprocess
ZeroClaw
@aroha-sdk/hermes-bridge
Same MCP bridge — ZeroClaw uses identical MCP config
OpenClaw
@aroha-sdk/openclaw-bridge
Bidirectional: skills ↔ capabilities
Composio / TrustClaw
@aroha-sdk/composio-bridge
Register as Composio custom actions
LangChain
@aroha-sdk/langchain-bridge
LangChain Tool and OpenAI function format
AutoGen
@aroha-sdk/langchain-bridge
OpenAI function format (same package)
MCP (generic)
@aroha-sdk/mcp-bridge
Bidirectional MCP ↔ Aroha capability mapping
Google A2A
@aroha-sdk/a2a-bridge
A2A message format ↔ Aroha envelopes

Hermes Agent (Nous Research)

Hermes Agent supports MCP servers as external tool integrations. The @aroha-sdk/hermes-bridge package runs as an MCP stdio server — Hermes forks the process and pipes JSON-RPC messages through stdin/stdout.

npm install @aroha-sdk/hermes-bridge

Step 1: Add to Hermes config

// ~/.hermes/config.json  (or wherever Hermes reads its MCP server list)
{
  "mcpServers": {
    "aroha-travel": {
      "command": "npx",
      "args": [
        "@aroha-sdk/hermes-bridge",
        "--endpoint", "http://travel-agent.example.com",
        "--agent-did", "did:aroha:travel-agent"
      ]
    },
    "aroha-payments": {
      "command": "npx",
      "args": [
        "@aroha-sdk/hermes-bridge",
        "--endpoint", "http://payment-agent.example.com",
        "--agent-did", "did:aroha:payment-agent"
      ]
    }
  }
}

Step 2: That's it

Hermes will start the bridge as a subprocess when it boots. Each Aroha capability appears as a tool named aroha_<capability_id> in Hermes's tool list. The bridge fetches the agent's capability manifest automatically at startup.

The bridge logs which capabilities it registered to stderr: [aroha-hermes-bridge] Connected to did:aroha:travel-agent — 5 capabilities registered as MCP tools

Programmatic use

import { createHermesMcpServer } from "@aroha-sdk/hermes-bridge";

// Build the MCP server manually (e.g. for a custom transport)
const server = await createHermesMcpServer({
  endpoint: "http://travel-agent.example.com",
  agentDID: "did:aroha:travel-agent",
});

console.log(server.tools);   // McpToolDefinition[]

// Serve over any stream pair
await server.serve(process.stdin, process.stdout);

// Or call a tool directly without the stdio layer
const result = await server.handleToolCall("aroha_search_flights", { from: "JFK", to: "LHR" });

ZeroClaw

ZeroClaw is a Rust-based personal agent that uses the same MCP server configuration format as Hermes. Use the same @aroha-sdk/hermes-bridge package.

# zeroclaw.toml
[[mcp_servers]]
name    = "aroha-travel"
command = "npx @aroha-sdk/hermes-bridge --endpoint http://travel-agent.example.com --agent-did did:aroha:travel-agent"

[[mcp_servers]]
name    = "aroha-payments"
command = "npx @aroha-sdk/hermes-bridge --endpoint http://payment-agent.example.com --agent-did did:aroha:payment-agent"

OpenClaw

OpenClaw is a local personal AI assistant (Node.js/npm) that extends via skills — named functions the LLM can call from any chat channel. The bridge is bidirectional.

npm install @aroha-sdk/openclaw-bridge

Aroha capabilities → OpenClaw skills

// aroha-travel-plugin.mjs  (register in OpenClaw's plugins directory)
import { createArohaOpenClawPlugin } from "@aroha-sdk/openclaw-bridge";
import { generateKeyPair, generateDid } from "@aroha-sdk/core";

const { privateKey, publicKey } = await generateKeyPair();
const myDID = generateDid(publicKey);

export default createArohaOpenClawPlugin("aroha-travel", [
  {
    capabilityId: "search-flights",
    endpoint: "http://travel-agent.example.com",
    agentDID: "did:aroha:travel-agent",
    callerDID: myDID,
    callerPrivateKey: privateKey,
    description: "Search for available flights between two airports",
    parameters: {
      from: { type: "string", description: "Origin IATA code, e.g. JFK" },
      to:   { type: "string", description: "Destination IATA code, e.g. LHR" },
      date: { type: "string", description: "Departure date in YYYY-MM-DD format" },
    },
  },
  {
    capabilityId: "book-hotel",
    endpoint: "http://hotel-agent.example.com",
    agentDID: "did:aroha:hotel-agent",
    callerDID: myDID,
    callerPrivateKey: privateKey,
    description: "Book a hotel room for given city and dates",
    parameters: {
      city:     { type: "string", description: "City name" },
      checkin:  { type: "string", description: "Check-in date YYYY-MM-DD" },
      checkout: { type: "string", description: "Check-out date YYYY-MM-DD" },
    },
  },
]);

OpenClaw skills → Aroha agent (bidirectional)

import { openClawSkillToArohaHandler, arohaCapabilityToOpenClawSkill } from "@aroha-sdk/openclaw-bridge";
import { ArohaServer } from "@aroha-sdk/core";

// Expose an existing OpenClaw skill as an Aroha MessageHandler
// so other Aroha agents can call your OpenClaw logic via signed envelopes
const weatherSkill = {
  name: "get-weather",
  description: "Get current weather for a city",
  async execute({ city }) {
    const res = await fetch(`https://weather-api.example.com/${city}`);
    return JSON.stringify(await res.json());
  },
};

const server = new ArohaServer({
  agentDID: myDID,
  port: 3001,
  onMessage: openClawSkillToArohaHandler(weatherSkill),
  resolvePublicKey: async (did) => registry.lookup(did),
});

await server.start();

Composio / TrustClaw

Composio is the integration platform behind TrustClaw. By registering Aroha capabilities as Composio custom actions, they become available to any Composio-connected LLM: TrustClaw, Claude, GPT-4, Gemini, and more.

npm install @aroha-sdk/composio-bridge composio-core

Register capabilities

import { Composio } from "composio-core";
import { registerArohaCapabilities } from "@aroha-sdk/composio-bridge";
import { generateKeyPair, generateDid } from "@aroha-sdk/core";

const composio = new Composio({ apiKey: process.env.COMPOSIO_API_KEY });
const { privateKey, publicKey } = await generateKeyPair();
const myDID = generateDid(publicKey);

await registerArohaCapabilities(composio, [
  {
    endpoint: "http://travel-agent.example.com",
    agentDID: "did:aroha:travel-agent",
    capabilityId: "search-flights",
    description: "Search for available flights between two airports on a given date",
    callerDID: myDID,
    callerPrivateKey: privateKey,
    parameters: {
      from: { type: "string", description: "Origin IATA code" },
      to:   { type: "string", description: "Destination IATA code" },
      date: { type: "string", description: "Departure date YYYY-MM-DD" },
    },
    required: ["from", "to", "date"],
  },
]);

// → Registered as action "aroha_travel_agent_search_flights" in Composio
// → Available to all LLMs connected via Composio (TrustClaw, Claude, GPT-4, Gemini)

Without Composio SDK (standalone handler)

import { buildComposioActionHandler } from "@aroha-sdk/composio-bridge";

// Returns a Map<actionName, executeFn> — use with any tool router
const handler = buildComposioActionHandler([
  { capabilityId: "search-flights", endpoint: "...", agentDID: "...", /* ... */ }
]);

const execute = handler.get("aroha_travel_agent_search_flights");
const result  = await execute({ from: "JFK", to: "LHR", date: "2026-08-01" });
console.log(result.data);       // { flights: [...] }
console.log(result.successful); // true

LangChain / AutoGen / Semantic Kernel

npm install @aroha-sdk/langchain-bridge
import {
  arohaCapabilityToLangChainTool,
  arohaCapabilityToOpenAITool,
  langChainAgentToArohaProvider,
} from "@aroha-sdk/langchain-bridge";

// ── Aroha → LangChain tool ──────────────────────────────────────────────────
const flightTool = arohaCapabilityToLangChainTool("search-flights", {
  endpoint: "http://travel-agent.example.com",
  agentDID: "did:aroha:travel-agent",
  callerDID: myDID,
  callerPrivateKey: privateKey,
  description: "Search available flights between airports",
});

// ── Aroha → OpenAI function (AutoGen / Semantic Kernel) ─────────────────────
const flightFn = arohaCapabilityToOpenAITool("search-flights", { /* same opts */ });

// ── LangChain tools → Aroha provider (expose your LangChain agent to others) ─
const server = langChainAgentToArohaProvider(
  [flightTool, hotelTool],           // your existing LangChain tools
  {
    agentDID: myDID,
    agentPrivateKey: privateKey,
    port: 3000,
    resolvePublicKey: async (did) => registry.lookup(did),
    didDocument: myDIDDoc,
  }
);
await server.start();

MCP (Model Context Protocol)

npm install @aroha-sdk/mcp-bridge
import {
  arohaAgentToMcpTools,
  mcpToolsToArohaCapabilities,
} from "@aroha-sdk/mcp-bridge";

// ── Aroha agent → MCP tool definitions ─────────────────────────────────────
// Use when your MCP client (Claude Desktop, etc.) should call an Aroha agent
const { tools, handleToolCall } = arohaAgentToMcpTools(
  discoveredAgent,       // from registry.find()
  orchestratorDID,
  orchestratorPrivKey,
  client,
  newCorrelationId()
);

// Register tools with your MCP server
mcpServer.addTools(tools);
mcpServer.onToolCall(handleToolCall);

// ── MCP tools → Aroha capability manifest ────────────────────────────────────
// Use when you want to expose an MCP server's tools as an Aroha agent
const capabilities = mcpToolsToArohaCapabilities(mcpServer.getTools());
registry.register({ did: myDID, endpoint: "http://...", capabilities });

Google A2A

npm install @aroha-sdk/a2a-bridge
import { a2aToAroha, arohaToA2a, arohaStreamToA2aStatus } from "@aroha-sdk/a2a-bridge";

// ── Receive an A2A message, convert to Aroha, dispatch ──────────────────────
app.post("/a2a/tasks/send", async (req, res) => {
  const a2aMsg = req.body;

  // Convert to Aroha envelope (trust level 1 — no Ed25519 proof from A2A)
  const envelope = a2aToAroha(a2aMsg, "did:aroha:a2a-gateway", myAgentDID);
  await arohaClient.send(agentEndpoint, envelope);

  res.json({ id: a2aMsg.taskId, status: { state: "submitted" } });
});

// ── Respond in A2A format ────────────────────────────────────────────────────
const arohaReply = await arohaClient.send(endpoint, requestEnvelope);
const a2aReply   = arohaToA2a(arohaReply);

// ── Stream events → A2A task status ─────────────────────────────────────────
const statusUpdate = arohaStreamToA2aStatus(streamEnvelope);
// { status: { state: "working" | "completed" } }