@navalabs/sdk
Nava Guardian verifies an exact proposed transaction against the active policy for its registered agent. It returns a structured verdict. The integrating application owns any signing and protocol submission after approval.
Install
npm install @navalabs/sdk
Requires Node.js >= 18.
Which package to install
@navalabs/sdk is protocol-neutral: it carries the runtime, the nava binary,
the nava-mcp server, and the six base operations (verification plus advisory
policy/state reads). Protocol operations live in adapters, which depend on
this package and ship their own nava and nava-mcp — so an adapter is a
complete install on its own.
| You want | Install |
|---|---|
Guardian verification, bootstrapGuardian, the base CLI/MCP tools |
@navalabs/sdk |
| Uniswap V3/V4 | @navalabs/uniswap-adapter |
| Hyperliquid perps | @navalabs/hyperliquid-adapter |
| Both protocols | both adapters |
Adapters remain optional peer dependencies of this package, which is what keeps
dynamic sibling loading legal under strict resolvers. Several packages declare
the nava and nava-mcp bin names; which one a package manager links varies
and is not warned about, so every copy dispatches every installed protocol.
Run a protocol command whose adapter is not installed and it fails with:
The uniswap adapter is not installed or could not be loaded: <import error>
Over MCP the same gap is not a failure. nava-mcp starts with the base tools
plus every installed protocol. With NAVA_PROTOCOLS unset it stays silent about
protocols you never installed; name one explicitly and it reports the missing
adapter. nava --help lists only the protocols the running binary registers,
so a bare @navalabs/sdk lists none and prints an install hint.
Do not pin the SDK and an adapter to one shared version — they version independently.
Zero-install
Nothing has to be installed first; packages can be fetched per run.
pnpm --package=@navalabs/sdk dlx nava check-verification-status --request-hash 0x…
pnpm --package=@navalabs/uniswap-adapter \
dlx nava uniswap get-quote --protocol v3 --currency-in USDC.e --currency-out WETH --amount-in 1
A protocol run needs only that protocol's adapter — it depends on
@navalabs/sdk and ships its own nava. Other package managers:
npx -p @navalabs/uniswap-adapter nava uniswap <operation>, yarn dlx -p …
the same way, or for bun bun add @navalabs/uniswap-adapter then bunx nava ….
Subpath exports
| Import | Contents |
|---|---|
@navalabs/sdk |
NavaClient, GuardianClient, GuardianVerdictClient, bootstrapGuardian. Start here. |
@navalabs/sdk/escrow |
Agent-execution bootstrap: bootstrapAgentExecution, createAgentClient, signAgentTransaction, the KeyStore adapters, P-256 helpers. |
@navalabs/sdk/mcp |
startServer, createMCPServer, the protocol registrar plumbing — what nava-mcp runs. |
@navalabs/sdk/cli |
runCli and the argv helpers — what nava runs, and what an adapter's CLI module plugs into. |
@navalabs/sdk/surface |
The ProtocolSurface descriptor framework: defineProtocolSurface, defineOperation, createCliModule. |
import { NavaClient } from '@navalabs/sdk';
import { bootstrapAgentExecution } from '@navalabs/sdk/escrow';
import { startServer } from '@navalabs/sdk/mcp';
import { defineProtocolSurface } from '@navalabs/sdk/surface';
These five paths and the two bins (nava, nava-mcp) are the stable public
contract. Legacy moduleResolution: "node" consumers resolve the subpath types
through typesVersions rather than exports.
Verify an action
import { NavaClient } from '@navalabs/sdk';
const nava = new NavaClient({
apiKey: process.env.NAVA_API_KEY!,
walletAddress: process.env.WALLET_ADDRESS!,
// Omit `baseUrl` to use https://internal.navalabs.dev/api
});
const created = await nava.requestVerification({
prompt: 'Swap WETH for USDC on Uniswap',
proposedTx: {
protocol: 'uniswap',
chainId: 11155111,
to: '0x...',
data: '0x...',
value: '0',
},
});
const verdict = await nava.checkVerificationStatus(created.requestHash!);
if (verdict.verdict?.outcome !== 'approved') throw new Error('Not approved');
// The application may now decide whether to sign and submit this exact action.
When baseUrl is omitted, the client talks to
https://internal.navalabs.dev/api. Set baseUrl or NAVA_BASE_URL for another
environment.
proposedTx.chainId is required and must be a chain the registry supports —
requestVerification throws at the SDK boundary otherwise.
Manage Guardian agents and policies
import { bootstrapGuardian } from '@navalabs/sdk';
const context = await bootstrapGuardian({
bearerToken: process.env.NAVA_MANAGEMENT_TOKEN!,
agentName: 'Treasury Agent',
walletAddress: process.env.WALLET_ADDRESS!,
chainId: 11155111,
policy: { presetId: 'spot-swapper' },
});
Policy writes use the nested overlay (shared + venues), not
flat Uniswap fields. For payments on Base USDC:
import {
bootstrapGuardian,
buildErc20TransferProposedTx,
PAYMENTS_CHAIN_ID,
PAYMENTS_USDC_ADDRESS,
} from '@navalabs/sdk';
const context = await bootstrapGuardian({
bearerToken: process.env.NAVA_MANAGEMENT_TOKEN!,
agentName: 'Payments Agent',
walletAddress: process.env.WALLET_ADDRESS!,
chainId: PAYMENTS_CHAIN_ID,
policy: {
presetId: 'payments',
venues: {
payments: {
perPaymentCapUsd: 1,
spendCapPerPeriod: { capUsd: 5, period: 'hour' },
vendorAllowlist: [],
},
},
},
});
const proposedTx = buildErc20TransferProposedTx({
chainId: PAYMENTS_CHAIN_ID,
token: PAYMENTS_USDC_ADDRESS,
to: '0x2222222222222222222222222222222222222222',
amount: 500_000n,
});
Use GuardianClient for agent, wallet, API-key, policy, and verdict-history
management. Use GuardianVerdictClient with an agent API key for submissions
and verdict polling.
CLI and MCP
Six base operations exist on both surfaces, under the same names — as
nava <command> on the CLI, and as unprefixed MCP tools:
| Operation | CLI | MCP tool |
|---|---|---|
request-verification |
nava request-verification |
request-verification |
await-verification |
nava await-verification |
await-verification |
check-verification-status |
nava check-verification-status |
check-verification-status |
get-user-address |
nava get-user-address |
get-user-address |
get-agent-policy |
nava get-agent-policy |
get-agent-policy |
get-agent-state |
nava get-agent-state |
get-agent-state |
get-agent-policy and get-agent-state are advisory: an agent that
self-rejects based on these reads and never submits leaves no verdict and no
audit trail. They need only NAVA_API_KEY. NAVA_BASE_URL is optional and
defaults to https://internal.navalabs.dev/api. Verification commands still
need NAVA_WALLET_ADDRESS / WALLET_ADDRESS.
Protocol operations are nava <protocol> <operation> on the CLI and
<protocol>.<operation> over MCP, kebab-case on both. Every level answers
--help; the bundled skill's references remain the full parameter reference.
Start the MCP server with the protocols you want:
NAVA_PROTOCOLS=uniswap,hyperliquid nava-mcp
Note the CLI's --reason flag is sent to the API as prompt.
The bundled agent skill
@navalabs/sdk ships an agent skill at
node_modules/@navalabs/sdk/skills/nava/. It is the canonical, hand-maintained
description of the CLI and MCP surface: a SKILL.md entrypoint that routes to
one reference per protocol plus base.md (the six base operations) and
guardian.md (the verification contract, authentication states, and verdict
handling).
Install it into an agent that reads skills from disk by copying or symlinking the directory:
mkdir -p .claude/skills
cp -R node_modules/@navalabs/sdk/skills/nava .claude/skills/nava
# or, to track upgrades of the package automatically:
ln -s ../../node_modules/@navalabs/sdk/skills/nava .claude/skills/nava
Point any other agent runtime at
node_modules/@navalabs/sdk/skills/nava/SKILL.md as the entrypoint; the
references are relative links from it and load on demand.
The references are hand-maintained and describe the CLI and MCP surface of this package.
Guides
- Integration guide — the six-step verification flow, from agent creation to execution.
License
MIT