Developer Guide _

Documentation

Everything you need to understand, integrate, and build on the Bouclier protocol. From installation to deploying custom policies.

01 — Quick Start

Prerequisites

Node.jsv18+
Foundrylatest
Gitv2+
A walletwith Base Sepolia ETH
Terminal — Clone & Install
# Clone the monorepo
git clone https://github.com/incyashraj/bouclier.git
cd bouclier

# Install dependencies
npm install

# Build contracts
cd contracts
forge build

# Run tests
forge test
Terminal — Deploy to Base Sepolia
# Set environment variables
export BASE_SEPOLIA_RPC="https://sepolia.base.org"
export PRIVATE_KEY="your-deployer-private-key"

# Deploy the registry contract
forge script script/DeployRegistry.s.sol \
  --rpc-url $BASE_SEPOLIA_RPC \
  --private-key $PRIVATE_KEY \
  --broadcast

# Deploy a sample policy
forge script script/DeployTransferLimitPolicy.s.sol \
  --rpc-url $BASE_SEPOLIA_RPC \
  --private-key $PRIVATE_KEY \
  --broadcast
02 — Architecture Overview
  ┌─────────────────────────────────────────────┐
  │           AI Agent (any framework)          │
  │  LangChain · AutoGPT · CrewAI · Custom     │
  └──────────────────┬──────────────────────────┘
                     │ action request
                     ▼
  ┌─────────────────────────────────────────────┐
  │           Bouclier SDK                      │
  │  @bouclier/sdk · bouclier-rs · bouclier-py │
  └──────────────────┬──────────────────────────┘
                     │ validate()
                     ▼
  ┌─────────────────────────────────────────────┐
  │         Sentinel Network                    │
  │    Distributed policy verification nodes    │
  └──────────────────┬──────────────────────────┘
                     │ check policies
                     ▼
  ┌─────────────────────────────────────────────┐
  │       On-Chain Registry (Base L2)           │
  │  Agent IDs · Policy Bindings · Revocation   │
  └──────────────────┬──────────────────────────┘
                     │ settlement
                     ▼
  ┌─────────────────────────────────────────────┐
  │         Target Protocol / Contract          │
  │  DeFi · NFT · DAO · Any EVM Contract       │
  └─────────────────────────────────────────────┘

Registry Layer

On-chain identity and policy bindings on Base L2. Immutable contract state.

Verification Layer

Sentinel nodes intercept and validate agent actions against registered policies.

Policy Layer

Composable smart contract modules — each one defines a specific constraint.

03 — Core Concepts
Agent IDbytes32

A unique identifier derived from keccak256(abi.encodePacked(owner, metadata, salt)). This is the on-chain identity for an autonomous agent.

Policy ContractIBouclierPolicy

An immutable smart contract that implements a validate() function. Returns true if the agent action is permitted, false to block.

Policy Bindingmapping

The on-chain link between an Agent ID and an array of policy contract addresses. All policies must pass for an action to proceed.

Sentinel Nodeoff-chain

A verification node that monitors the Base L2 mempool, intercepts agent transactions, and runs policy checks before settlement.

Revocationtransaction

A single-call operation (revokeAgent) that globally deactivates an agent. All sentinel nodes stop processing its transactions immediately.

Validation Resultstruct

The response from a policy check: { valid: bool, reason: string }. On failure, the sentinel node blocks the action and logs the reason.

04 — Smart Contracts
IBouclierRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IBouclierRegistry {
    /// @notice Register a new agent with attached policies
    /// @param agentId Unique bytes32 identifier for the agent
    /// @param policies Array of policy contract addresses
    function registerAgent(
        bytes32 agentId,
        address[] calldata policies
    ) external;

    /// @notice Revoke an agent — stops all sentinel processing
    /// @param agentId The agent to revoke
    function revokeAgent(bytes32 agentId) external;

    /// @notice Check if an agent is currently active
    function isActive(bytes32 agentId) external view returns (bool);

    /// @notice Get all policies attached to an agent
    function getPolicies(
        bytes32 agentId
    ) external view returns (address[] memory);

    /// @notice Add a policy to an existing agent
    function addPolicy(bytes32 agentId, address policy) external;

    /// @notice Remove a policy from an agent
    function removePolicy(bytes32 agentId, address policy) external;

    event AgentRegistered(bytes32 indexed agentId, address indexed owner);
    event AgentRevoked(bytes32 indexed agentId);
    event PolicyAdded(bytes32 indexed agentId, address indexed policy);
    event PolicyRemoved(bytes32 indexed agentId, address indexed policy);
}
IBouclierPolicy.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IBouclierPolicy {
    /// @notice Validate an agent action against this policy
    /// @param agentId The registered agent identifier
    /// @param target The contract being called
    /// @param value The ETH value being sent
    /// @param data The calldata being executed
    /// @return valid Whether the action is permitted
    function validate(
        bytes32 agentId,
        address target,
        uint256 value,
        bytes calldata data
    ) external view returns (bool valid);
}
TransferLimitPolicy.sol — Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {IBouclierPolicy} from "./IBouclierPolicy.sol";

/// @title TransferLimitPolicy
/// @notice Enforces a maximum ETH transfer per transaction
contract TransferLimitPolicy is IBouclierPolicy {
    uint256 public immutable maxTransferWei;

    constructor(uint256 _maxTransferWei) {
        maxTransferWei = _maxTransferWei;
    }

    function validate(
        bytes32, /* agentId */
        address, /* target */
        uint256 value,
        bytes calldata /* data */
    ) external view override returns (bool valid) {
        return value <= maxTransferWei;
    }
}
05 — SDK Integration

The TypeScript SDK is in active development. Install from the monorepo while the npm package is being prepared.

install.sh
# From the monorepo root
cd sdk
npm install
npm run build

# Link for local development
npm link
register-agent.ts
import { BouclierClient } from "@bouclier/sdk";
import { createWalletClient, http } from "viem";
import { baseSepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

// Initialize the Bouclier client
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const bouclier = new BouclierClient({
  chain: baseSepolia,
  transport: http(process.env.BASE_SEPOLIA_RPC),
  account,
});

// Generate an agent ID
const agentId = bouclier.generateAgentId({
  name: "treasury-bot",
  version: "1.0.0",
  salt: "unique-salt-value",
});

// Register with policies
const tx = await bouclier.registerAgent({
  agentId,
  policies: [
    "0x...TransferLimitPolicy",
    "0x...ScopeRestrictionPolicy",
  ],
});

console.log("Agent registered:", tx.hash);
console.log("Agent ID:", agentId);
validate-action.ts
// Validate an action before execution
const result = await bouclier.validate({
  agentId,
  target: "0x...TargetContract",
  value: 0n,
  data: encodedCalldata,
});

if (result.valid) {
  // All policies passed — safe to execute
  const tx = await walletClient.sendTransaction({
    to: target,
    value: 0n,
    data: encodedCalldata,
  });
} else {
  console.error("Policy violation:", result.reason);
}

// Check agent status
const isActive = await bouclier.isActive(agentId);

// Get attached policies
const policies = await bouclier.getPolicies(agentId);

// Revoke in emergency
await bouclier.revokeAgent(agentId);
06 — Writing Custom Policies

Policy Design Rules

  • 01Policies must implement IBouclierPolicy with a pure/view validate() function
  • 02Policies should be stateless where possible — use immutable constructor params
  • 03validate() must return true to allow and false to block — no reverts
  • 04Multiple policies are checked in sequence — ALL must pass
  • 05Deploy as immutable contracts — no upgradeable proxies for trust guarantees
ScopeRestrictionPolicy.sol — Custom Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {IBouclierPolicy} from "./IBouclierPolicy.sol";

/// @title ScopeRestrictionPolicy  
/// @notice Restricts an agent to only interact with whitelisted contracts
contract ScopeRestrictionPolicy is IBouclierPolicy {
    mapping(address => bool) public allowedTargets;
    
    constructor(address[] memory _targets) {
        for (uint i = 0; i < _targets.length; i++) {
            allowedTargets[_targets[i]] = true;
        }
    }

    function validate(
        bytes32, /* agentId */
        address target,
        uint256, /* value */
        bytes calldata /* data */
    ) external view override returns (bool valid) {
        return allowedTargets[target];
    }
}
test/ScopeRestrictionPolicy.t.sol — Testing
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "forge-std/Test.sol";
import "../src/ScopeRestrictionPolicy.sol";

contract ScopeRestrictionPolicyTest is Test {
    ScopeRestrictionPolicy policy;
    address allowed = address(0xA);
    address blocked = address(0xB);

    function setUp() public {
        address[] memory targets = new address[](1);
        targets[0] = allowed;
        policy = new ScopeRestrictionPolicy(targets);
    }

    function testAllowedTarget() public view {
        bool valid = policy.validate(
            bytes32(0), allowed, 0, ""
        );
        assertTrue(valid);
    }

    function testBlockedTarget() public view {
        bool valid = policy.validate(
            bytes32(0), blocked, 0, ""
        );
        assertFalse(valid);
    }

    function testFuzz(address target) public view {
        bool valid = policy.validate(
            bytes32(0), target, 0, ""
        );
        assertEq(valid, target == allowed);
    }
}
07 — Sentinel Nodes
1

Monitor

Scans the Base L2 mempool for transactions from registered agents

2

Verify

Runs each pending action through the agent's attached policy contracts

3

Enforce

Blocks invalid transactions and logs violations to the on-chain audit trail

Terminal — Run a Testnet Node
# Clone and build
git clone https://github.com/incyashraj/bouclier.git
cd bouclier/node
cargo build --release

# Initialize configuration
./target/release/bouclier-node init --network base-sepolia

# Start the sentinel node
./target/release/bouclier-node start \
  --rpc $BASE_SEPOLIA_RPC \
  --registry 0x...RegistryAddress
08 — API Reference
MethodParametersReturns
registerAgentagentId, policies[]TransactionHash
revokeAgentagentIdTransactionHash
isActiveagentIdboolean
getPoliciesagentIdaddress[]
addPolicyagentId, policyTransactionHash
removePolicyagentId, policyTransactionHash
validateagentId, target, value, data{ valid, reason }
generateAgentIdname, version, saltbytes32

Start Building

Clone the repo, deploy to testnet, and register your first agent.

[SYS] BOUCLIER.ETH v0.1.0-alpha