Skip to main content

Agents

An LLM agent that reads or writes Aleo state needs its capabilities described as tools: a name, a description the model reads to decide when to call it, a JSON Schema for its arguments, and a handler that actually runs when the model calls it. @provablehq/veil-core ships that description for its own read and write actions under a /agent subpath, and an MCP server binding under /mcp. @provablehq/shield-swap-sdk ships the same two subpaths for DEX actions, in a shape designed to sit alongside the core tools rather than replace them.

The tool shape

An AgentTool pairs a schema with the handler that executes it:

type AgentToolSchema = {
name: string
description: string
inputSchema: { type: 'object'; properties: Record<string, unknown>; required?: string[] }
}

type AgentToolHandler = (params: Record<string, unknown>) => Promise<unknown>

type AgentTool = { schema: AgentToolSchema; handler: AgentToolHandler }

This maps directly onto MCP's tool declaration and onto the tool/function shapes LangChain, the Vercel AI SDK, and the Claude and OpenAI APIs each use, so one set of schemas and handlers serves any of them — only the adapter that registers the tools and routes calls to handler changes.

Core tools

createAgentTools builds the full set of AgentTools for the base Aleo actions, gated by which clients are passed in: a PublicClient enables the read-only tools, a WalletClient enables the tools that sign and spend.

import { createPublicClient, http } from '@provablehq/veil-core'
import { createAgentTools } from '@provablehq/veil-core/agent'

const client = createPublicClient({
transport: http('https://api.provable.com/v2', { network: 'mainnet' }),
})

const tools = createAgentTools({ client })
ToolNeedsDescription
aleo_get_block_numberclientCurrent chain height
aleo_get_balanceclientPublic credits balance for an address
aleo_read_mappingclientRead a value from a program's public mapping
aleo_get_programclientFetch a deployed program's source
aleo_get_blockclientFetch a block by height or hash
aleo_get_transactionclientFetch a transaction by id
aleo_describe_programclientParse a program's functions, mappings, and closures
aleo_executewalletClientExecute a program function
aleo_transferwalletClientTransfer credits to an address
aleo_deploywalletClientDeploy a program

aleoAgentToolSchemas(config?) returns the schemas alone, filtered the same way, for a caller that wants to register tool descriptions with a model without wiring up execution yet. Every write tool signs, proves, and broadcasts when called — an agent with a walletClient configured pays fees on every aleo_execute, aleo_transfer, or aleo_deploy call the model makes.

Serving tools over MCP

createMcpServer adapts createAgentTools's output into an MCP server — a tool list plus a dispatcher. It is not a running process; the caller still wires the returned tools and handleToolCall into an MCP SDK server over whichever transport it uses (stdio, HTTP):

import { createMcpServer } from '@provablehq/veil-core/mcp'

const server = createMcpServer({ client })

const result = await server.handleToolCall('aleo_get_block_number', {})
// { height: '3082441' }

toMcpServer(tools) is the package-agnostic version underneath — it takes any AgentTool[], not core's specifically, which is how a caller combines tool sets from more than one package.

Shield Swap tools

@provablehq/shield-swap-sdk exposes the same two subpaths for its DEX actions. createShieldSwapAgentTools returns AgentTool[] in the identical shape core's createAgentTools returns, gated by which backing is configured: a client extended with shieldSwapActions enables on-chain reads and private-balance lookups, an api client enables the off-chain DEX API reads (pool listing, routing, token registry), and both together enable the tools that combine them. Money-moving writes — swap, mint, add or remove liquidity — are opt-in via includeWrites, since a model calling them can move funds. The write tools target the local-signer path: they auto-select records and auto-fetch the dynamic-dispatch program sources, so the agent supplies only amounts and token programs. walletClient below is the same wallet client used throughout the rest of the docs:

import { shieldSwapActions } from '@provablehq/shield-swap-sdk'
import { createShieldSwapAgentTools } from '@provablehq/shield-swap-sdk/agent'

const swapClient = walletClient.extend(
shieldSwapActions({ api: { baseUrl: 'https://amm-api.dev.provable.com' } }),
)

const tools = createShieldSwapAgentTools({
client: swapClient,
api: swapClient.api,
includeWrites: true,
})

createShieldSwapMcpServer({ client, api }) from @provablehq/shield-swap-sdk/mcp is the equivalent MCP binding, serving only the shield_swap_* tool set.

Combining tool sets

Because createAgentTools and createShieldSwapAgentTools both return AgentTool[], serving Aleo and DEX tools from one MCP server is a matter of concatenating the two arrays before calling core's toMcpServer. Reusing client from Core tools above and swapClient from Shield Swap tools:

import { createAgentTools } from '@provablehq/veil-core/agent'
import { toMcpServer } from '@provablehq/veil-core/mcp'

const coreTools = createAgentTools({ client, walletClient })
const swapTools = createShieldSwapAgentTools({ client: swapClient, api: swapClient.api })

const server = toMcpServer([...coreTools, ...swapTools])

const pools = await server.handleToolCall('shield_swap_list_pools', { limit: 5 })
const height = await server.handleToolCall('aleo_get_block_number', {})

The same AgentTool[] array registers directly with LangChain, the Vercel AI SDK, or a hand-rolled Claude or OpenAI tool-use loop — toMcpServer is only needed for the MCP transport specifically.