Skip to main content

Overview

An adapter is a Domain A component that bridges an AI agent framework to the ISCL secure signing layer. Adapters construct declarative TxIntent objects, call ISCL Core over HTTP, and present results back to the agent or user. They never touch private keys, never sign transactions, and never call the blockchain directly. Every adapter in the Clavion ecosystem follows the same four-step contract:
  1. Accept user/agent input (natural language, command, tool call).
  2. Build a TxIntent describing the desired on-chain action.
  3. Send the intent through the ISCL Core API for policy checks, simulation, approval, signing, and broadcast.
  4. Return the result to the caller.
This tutorial walks through building a new adapter from scratch using the patterns established by the four existing adapters.

Architecture Pattern

Every adapter sits between the agent framework and ISCL Core, acting as a translation layer. Component overview:
Detailed data flow for a fund-affecting operation:
The adapter never sees keys, never signs, and never contacts the blockchain. All chain access is mediated by ISCL Core.

Existing Adapters

All four adapters share the same core pattern: ISCLClient + buildIntent() + executeSecurePipeline(). The only differences are how they receive input and present output.
1

Package Setup

Create the package directory under packages/:

package.json

Only @clavion/types is needed from the monorepo. This package provides the TxIntent, ActionObject, and other shared interfaces. Never add Domain B packages (@clavion/signer, @clavion/policy, @clavion/audit, etc.) as dependencies. Doing so violates the trust domain boundary and will be caught by the domain-b-integrity.test.ts security test suite.

tsconfig.json

The references array only points at ../types. This enforces the Domain A boundary at the TypeScript project-reference level — the compiler will refuse to resolve imports from packages not listed here.
2

ISCLClient

Copy src/shared/iscl-client.ts from any existing adapter. The client is framework-agnostic and identical across all adapters. It wraps the ISCL Core REST API with typed methods.

Constructor

The constructor reads the base URL from three sources in priority order:
  1. options.baseUrl (explicit)
  2. ISCL_API_URL environment variable
  3. http://127.0.0.1:3000 (default)

Key Methods

Error Handling

All methods throw ISCLError on non-2xx responses:
Common error codes:
3

Intent Builder

The intent builder converts framework-specific parameters into a TxIntent object. Every adapter has one, and they are nearly identical.

Building Actions for Each Type

4

Handler Functions -- The 2-Step Pipeline

Every fund-affecting operation follows the same two-step pipeline:
  1. txApproveRequest(intent) — Sends the intent to ISCL Core, which runs policy checks, preflight simulation, and prompts the user for approval. This call blocks until the user approves or denies.
  2. txSignAndSend({ intent, approvalTokenId }) — If approved, sends the intent with the single-use approval token. ISCL Core verifies the token, signs the transaction, and broadcasts it.

Shared Pipeline Function

Extract this into src/shared/pipeline.ts so all handlers share the same logic:

Complete Handler Example

Read-Only Operations

Balance checks and transaction lookups do not require the approval pipeline:
5

Framework Integration

Each framework has its own way of registering tools, commands, or actions. Below are the patterns used by the four existing adapters.
Register tools on an McpServer instance. Each tool has a name, description, Zod schema, and async handler.
Key file: packages/adapter-mcp/src/server.ts
6

Testing

Unit Tests: Mock the ISCLClient

Test intent construction and handler logic without a running ISCL server:

Integration Tests: Real ISCL Server

For integration tests, spin up an ephemeral buildApp() server and test the full round-trip:
Pass promptFn: async () => true to buildApp() to auto-approve all transactions in tests. Without this, tests will hang waiting for interactive readline input.

Security Checklist

Every adapter must satisfy these five invariants. Violations break the trust model and will be caught by the domain-b-integrity.test.ts security test suite.

Complete Minimal Example

A self-contained adapter that works with any framework. This example implements a transfer handler in approximately 60 lines:
To integrate this with your framework, call transfer() from whatever command, tool, or action handler your framework provides.

Further Reading