Only this pageAll pages
Powered by GitBook
1 of 19

Bitte

Agents

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Wallet

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Introduction

Welcome to the Open Agents documentation.

What are Open Agents?

Open Agents are essentially APIs that our runtime communicates with to perform tasks on behalf of users. These agents receive instructions, process data from both on-chain and off-chain sources, and execute transactions across multiple blockchain networks. Each agent is defined using the OpenAPI Specification, which standardizes how they expose their capabilities and interact with other components of the system.

By adhering to the OpenAPI spec, agents provide a clear, machine-readable interface that simplifies integration and ensures consistent communication with the runtime. Acting as intermediaries, these agents simplify complex blockchain interactions, making it easier for users to execute decentralized financial operations through an accessible API interface.

What is Bitte Runtime?

The Bitte Runtime is the core system that manages the execution and coordination of decentralized tasks across the Bitte Protocol. It acts as the intermediary between user requests, agents, and the underlying blockchain networks, ensuring that each task is routed to the appropriate agent for execution. The runtime handles task orchestration, data aggregation, and communication between agents, tools, and networks. Its primary role is to streamline the execution of multi-step transactions, ensuring seamless interactions across different blockchains, APIs, and smart contracts, all while maintaining efficiency and accuracy.

Getting Started

Getting Help

Talk to us at Bitte Dev Telegram chat.

Quick Start

How to get started in 3 minutes creating an Open Agent.

Make sure your make-agent package is running v0.3.1+

In this guide we will:

  1. Clone the agent template

  2. Generate and set API Key

  3. Develop the agent with make-agent

  4. Deploy your agent and go live!

1. Clone agent template

git clone https://github.com/BitteProtocol/agent-next-boilerplate.git
cd agent-next-boilerplate

To get started with your Open Agent project, first clone the Bitte Next Agent Template repository. You can use this ready-to-use template as a solid foundation for building your agent

2. Get API Key and Set Environment Variables

Get your api key at https://key.bitte.ai

change or copy the root file .env.example to .env and add your newly generate api key

BITTE_API_KEY="bitte_#####"

3. Start Coding

Install dependencies

pnpm i

Run boilerplate, this will automatically run the make-agent library + your agent server

pnpm dev

When you run your project, the UI launches in your console, allowing you to access the chat sandbox with local dev environment connections for EVM and NEAR wallets. By testing the boilerplate with a command like "Hey, can you do a coinflip for me", you'll trigger the coinflip tool, which generates a random value.

You can customize tools by modifying their route's return value and updating the ai-plugin route manifest to define and provide LLM instructions for tool usage. You can learn more about your manifest here: Manifest

To send transactions, return the transaction body in your route. In the manifest, specify that the route returns a valid transaction. The runtime will automatically detect this if you have the appropriate tools (generate-evm-tx or generate-transaction) defined, which are already set up in the boilerplate and prepare the transaction in the UI. Check the create-near-transaction and create-evm-transaction routes for examples

4. Go live!

Consider pushing your code to its own GitHub repository and hosting it in a easy to deploy service like Vercel. There are other alternatives, but we find Vercel very easy to work with.

Note that your deploy script includes make-agent deploy. This command will validate your API key, look into the deployment URL (for most common hosting providers) and automatically communicate any changes made to our registry.

In case you want to have more control over your deployment URL, you can set BITTE_AGENT_URL

BITTE_AGENT_URL=<YOUR_DESIRED_URL>

From your own repo

Install make-agent

make-agent is a CLI tool that was built to make the development of an Open Agent as easy as possible-

The templates should have these packages installed. But if you're trying to add this to an existing project, please install make-agent and concurrently.

npm i -D make-agent concurrently
pnpm i -D make-agent concurrently
bun add -D make-agent concurrently

Your package.json should look like this:

  "scripts": {
    "dev": "concurrently \"next dev\" \"make-agent dev --port 3000\"",
    "build": "next build && make-agent deploy",
    "start": "next start",
    "lint": "next lint"
  },

You can now run in development mode.

npm run dev
pnpm run dev
bun run dev

Learn more about the Manifest file by following the link below.

Manifest

Plugin Manifest

Make sure the plugin manifest file is accessible at /.well-known/ai-plugin.json on your domain. The URL should be similar to:

OpenAPI Bitte Extension

We have created an extension for the OpenAPI specification that allows you to include additional metadata.

Account ID (account-id)

• Description: Specifies the account ID associated with the plugin. This is typically the account ID on the NEAR blockchain that identifies the owner or operator of the API.

• Example: bitte.near

Agent Configuration (assistant)

Provides the configuration for the agent that will guide the user in interacting with the API. This section includes details about its behavior, and the tools it can use.

name

Instructions provided to the agent define its role or behavior. This helps tailor the agent’s responses according to specific requirements.

Example: "Weather Agent"

description

A general summary of the agent's functionalities and tools / endpoints.

instructions

Instructions provided to the agent define its role or behavior. This helps tailor the agent’s responses according to specific requirements.

Example: "You are a helpful agent. When using the get-weather tool make sure to know or ask for the user's location."

tools

A list of tools that the agent can use. Each tool is defined by its type and possibly other configurations.

Tool Type The type of tool that the agent can use. You can add any amount of primitives tools, by their name

  1. generate-transaction - Render a Near transaction payload for the user to review and sign.

  2. generate-evm-tx - Generate or format an EVM transaction payload for review in the UI.

  3. generate-sui-tx - Create a Sui transaction payload for validation and signing.

  4. submit-query - Generate and submit GraphQL queries to fetch data from the Mintbase Graph API.

  5. transfer-ft - Create fungible token transfer transactions on NEAR blockchain.

  6. generate-image - Generate images based on text prompts.

  7. get-portfolio - Retrieve portfolio information for blockchain accounts.

  8. sign-message - Create a message signing request for blockchain wallets.

  9. render-chart - Generate and render data visualizations and charts.

  10. get-swap-transactions - Get token swap transaction data from Ref Finance on NEAR.

  11. get-token-metadata - Retrieve metadata for tokens on the NEAR blockchain.

  12. get-sui-balances - Get token balances for a Sui blockchain address.

  13. sui-lst - Mint or redeem sSUI tokens using Spring protocol on Sui blockchain.

  14. aftermath-sui-swap - Execute token swaps on the Aftermath DEX on Sui blockchain.

image

Image URL for your agent (recommended: 256x256px or 512x512px square)

categories

Array of tags that categorize your agent.

Example: ["DeFi", "Meme", "Investing"]

chainIds

Array of evm chains your agent operates in. This makes it easier for other people to find your agent and adds context to the LLMs.

Example: [1, 100, 8453, 42161]

version

Track the version of your agent.

Example: "1.0.2"

Quick Start
Manifest
https://your-service/.well-known/ai-plugin.json
"x-mb": {
  "account-id": "bitte.near",
  "email": "[email protected]",
  "assistant": {
    "name": "agent-name",
    "description": "Shorter summary about the agent and it's capabilities",
    "instructions": "Detailed, specific instructions to be passed to AI Agent on it's funcitonality and tool usage.",
    "tools": [{ type: "generate-transaction" }, { type: "submit-query" }],
    // optional fields (recommended)
    "repo": "https://github.com/user-or-org/agent-project/",
    "image": "https://agent-image.example",
    "categories": ["tags","for","your","agent"],
    "chainIds": [1,8453],
    "version": "0.1.27"
  }
}

Bitte Next Agent Template

Cover

Telegram Integration

Integrating Bitte Wallet with Telegram Bot

This guide will walk you through integrating the Bitte Wallet into your Telegram bot. By the end, users will be able to interact with your bot and open the Bitte Wallet Web App directly from a Telegram message.

Prerequisites

Before starting, ensure you have:

  • A Telegram bot set up using the Telegram Bot API.

  • A working environment with Node.js and the node-telegram-bot-api package installed.

Integration Steps

Step 1: Set Up Your Bot

Ensure your Telegram bot is up and running. If you haven't created a bot yet, follow the official guide to create one and obtain your bot's API token.

Step 2: Install Required Package

Ensure you have the node-telegram-bot-api package installed in your Node.js project. If not, install it using npm:

pnpm install node-telegram-bot-api

Step 3: Implement the Command

In your bot's code, implement the /connect command to trigger the Bitte Wallet Web App. The command should look like this:

bot.on('message', (msg: any) => {
    const chatId = msg.chat.id;

    if (msg.text?.startsWith('/connect')) {

        const webAppUrl = `https://wallet.bitte.ai/account/new?password=true`;

        const opts = {
            reply_markup: {
                inline_keyboard: [
                    [{text: "Open Web App", web_app: {url: webAppUrl}}]
                ]
            }
        };
        bot.sendMessage(chatId, messageText, opts);
    } else {
        bot.sendMessage(chatId, 'Send connect to open wallet');
    }
});

All connections work through url schemes so check out #Bitte Wallet Integration via URL Schemes

Sign Messages

Bitte Wallet provides functionalities for signing and verifying messages. This documentation outlines the steps for using these features, including signing a message, verifying a message via the UI.

Sign Message

The sign message functionality allows you to sign a message using your Mintbase Wallet. The signed message can then be used for various verification purposes.

Endpoint

Parameters

  • message: The message you want to sign.

  • callbackUrl: The URL to which the signed message will be sent.

  • nonce: A unique identifier to prevent replay attacks.

Example

Always make sure to encode the parameters when redirecting

You can generate the nonce using this code snippet

Verify Message

The verify message functionality allows you to verify a signed message using the UI or API. Verification ensures that the message was signed by the rightful owner of the specified account.

Verify via UI

Endpoint

Parameters

  • accountId: The account ID of the signer.

  • publicKey: The public key of the signer in base58 format.

  • signature: The signature of the signed message in base64 format.

  • message: The original message that was signed.

  • nonce: A unique identifier used during signing.

  • recipient: The intended recipient (e.g., mainnet).

  • callbackUrl: The URL to which the verification result will be sent.

Example

Verify Message via API Endpoint

Endpoint

Parameters

  • accountId: The account ID of the signer.

  • publicKey: The public key of the signer in base58 format.

  • signature: The signature of the signed message in base64 format.

  • message: The original message that was signed.

  • nonce: A unique identifier used during signing.

  • recipient: The intended recipient (e.g., mainnet).

  • callbackUrl: The URL to which the verification result will be sent.

Example

URL:

URL:

URL:

https://wallet.bitte.ai/sign-message?message=hey&callbackUrl=https://wallet.bitte.ai&nonce=1
message=${encodeURIComponent}&callbackUrl......
const nonce = Buffer.from(randomBytes(32)).toString('base64')
https://testnet.wallet.bitte.ai/verify-message?accountId=faraday_stroud.mintbase.testnet&publicKey=ed25519%3A6533dMsJstJvNUFcCkvgdWPWFdbs4RDRtt4vaUc1gnZU&signature=sMPu%2BAnsM2OCXMTM1OeB19XaskFG%2Fg1cBXzCClW0IbDwPvowM3Uotq6iYOoX5Qxuti5rq01GnAeIAZQ6%2F0UCCA%3D%3D&message=hey&nonce=1&recipient=mainnet&callbackUrl=https://mintbase-wallet-git-signing-message-mintbase.vercel.app
https://wallet.bitte.ai/api/verify-message?accountId=faraday_stroud.mintbase.testnet&publicKey=ed25519%3A6533dMsJstJvNUFcCkvgdWPWFdbs4RDRtt4vaUc1gnZU&signature=sMPu%2BAnsM2OCXMTM1OeB19XaskFG%2Fg1cBXzCClW0IbDwPvowM3Uotq6iYOoX5Qxuti5rq01GnAeIAZQ6%2F0UCCA%3D%3D&message=hey&nonce=1&recipient=mainnet&callbackUrl=https://mintbase-wallet-git-signing-message-mintbase.vercel.app
https://wallet.bitte.ai/sign-message
https://wallet.mintbase.xyz/verify-message
https://wallet.bitte.ai/api/verify-message

Paymaster

Creating a Paymaster

Now you can enable your community to interact with your smart contracts freely. They will not need crypto to mint, vote on your DAOs, or receive free airdrops.

  1. Go to the Bitte Wallet

  2. Head to the APPs tab

  3. Click "New Paymaster"

  1. Enter the contract you want to sponsor on NEAR

  2. Functions will appear below that you can toggle to enable or disable functionalities you want your users to run for free.

  1. Fund your paymaster wallet with enough funds to sponsor gas for transactions

The paymaster is now successfully created and will automatically fund the transactions defined before!

Using the paymaster

There are currently 2 ways to use the paymaster, either directly through the wallet or via code.

Using Paymaster Via Wallet

In the previous example, I created a sponsorship for the contract blackdragon.tkn.near and selected the method "ft_transfer". Now, their gas fee will be sponsored whenever someone transacts that contract/method through the wallet.

This makes it easy to use, by adding a wallet connection to any application users can be redirected to Bitte to sign transactions at which point the sponsorship will take effect.

Currently, the sponsorship will affect all the transactions in the wallet. Still, the plan is for the following versions to allow for passing in certain parameters only to allow certain user bases to take advantage of it.

Using Paymaster with Code

To use the paymaster via code you must have access to accounts from within your application to be able to sign transactions to be sponsored.

Start by copying the relayer URL from the dashboard.

The next step involves building the transaction and sending it to that URL via a post request, you can check the official near docs for more information or use this simple wrapper library to get started

You can restrict access to your Paymaster by generating an api key in the dashboard. When using near relay you can add it to .env as BITTE_API_KEY. For direct HTTP requests, include the key in the headers as bitte-api-key.

pnpm i @near-relay/client
import { relayTransaction } from "@near-relay/client";

/**
 * Signs a transaction and sends it to a relayer to get dispatched
 *
 * @param {Action[]} action - The list of actions to include in the transaction.
 * @param {string} receiverId - The ID of the receiver.
 * @param {string} relayerUrl - Url for the relayer to which the tx will be sent
 * @param {Account?} account - Optionally pass in local account
 * @param {string?} network - 'mainnet | testnet'
 * @returns {Promise<any>} - Most likely a receipt (depends on format being returned by relayer).
 */

const receipt = await relayTransaction(action: Action | Action[], receiverId: string, relayerUrl: string, network: string, account: Account)

Managing paymaster

Go to your dashboard to review the account ID, API call URL, and the total sponsored amount. Then, click "Edit" to make any necessary changes.

Editing

Here you can change the smart contract you have selected or change the affected methods.

Deleting

At the bottom of the edit page, you will find a delete button that will allow you to delete the near account associated with the paymaster automatically giving all of the funds contained in it back to your account.

Managing Balance

When viewing the dashboard hit the manage balance button to deposit or withdraw funds, here you can toggle the top tab to fund or withdraw from the near account that is associated with the paymaster.

FAQ

Can I set spending limits on the gas fees my Paymaster covers?

Not directly. The way you would do that at this point would be to only fund the relayer with the amount you are willing to spend

Is it possible to sponsor specific users or groups using the Paymaster?

This feature is planned soon TM

What happens if my Paymaster wallet runs out of funds?

When the user tries to submit the transaction, they will be prompted to pay gas as normal.

Can I sponsor multiple contracts with a single Paymaster?

No. You can currently set this up by managing more than one Paymaster.

Can I track the transactions that have been sponsored by my Paymaster?

Yes, in the dashboard, you can see the amount that has been sponsored. Eventually, there could be better visualization tools.

Is there a limit to the number of transactions my Paymaster can sponsor?

Not currently but there is a limit for the amount of gas that can be sponsored before KYC is necessary.

Can I sponsor account creation?

Account creation is just a function call so technically, you could but at this point that would affect all users of the wallet, this will be possible to do more conveniently once you can limit usage to certain groups of users.

Quickstart

Welcome to Bitte Wallet, your gateway to seamless crypto transactions. Bitte Wallet prioritizes user-friendly onboarding and smooth functionality, bridging the familiarity of Web2 experiences with the innovation of Web3 technologies.

Key Features:

  • User-Friendly Onboarding: With passkeys and account abstraction, Bitte Wallet offers a seamless onboarding experience, often faster than traditional Web2 platforms.

  • Secure Custody of Assets: Utilizing biometric features such as Face ID or fingerprints, Bitte Wallet securely stores wallet keys in your chosen password manager, ensuring you have full control over your assets.

  • No Gas Fees: Leveraging account abstraction and meta-transaction technologies unique to the NEAR blockchain, Bitte Wallet facilitates transactions covering gas fees.

Contract To Agent

How to Use Contract to Agent

The contract-to-agent tool enables you to scaffold an agent based on a NEAR contract that has an ABI. This process makes integration with the NEAR protocol seamless by providing a structured template for agent development. Here's a step-by-step guide to get started:

  1. Scaffold the Agent: Run the following command to start creating your agent. You will be prompted for necessary inputs:

    • Contract ID: Provide the contract ID. Ensure the contract has a well-defined ABI.

    • Description: Offer a detailed description of the contract's functionalities, which will guide the behavior of the agent.

    • Optional Directory: Specify a directory where you want to generate the agent files, or leave it blank to use the default.

    If you just want to run your agent and don't want to know how it works then skip to 2. The rest of the flow will continue as described below, but before following that we can take a look at what was generated, if you open your index.ts you should see a simple express server

    This should contain endpoints for each of your smart contract methods regardless of if they are read of write calls, notice the writes return a valid transaction object that will be executed by the runtime using the "generate-transaction" tool

    The most important part is this endpoint:

    Here your Open API Spec will be handled. This is how your agent knows how to interact with your API. If your agent isn't able to use your api correctly even though its functional this is probably the issue. Make sure your instruction field is explicit, some prompt engineering will be necessary

  2. Generate an API Key: If everything went well you will see this window open. If you don't already have a wallet you will first be prompted to create one first. Once you have signed the message you will have an API Key automatically generated for you and put into your environment variables.

  1. Develop and Test Agent: After creating an API Key you will be booted into the agent playground where you can start testing your agent. Based on the instructions and the contract methods we can see the agent was able to understand what the available methods are and should be able to make view and write contract calls out of the box

  2. If you ever close the execution you can run everything again by running your server and make-agent again

NFT Drops

  1. Paste your link to your community

  2. We suggested claiming the first one so you can track it on your NFTs page.

You can learn more about it here If your contract is too complex for the scaffolding to work completely this will still work as very easy good starting point for your agent.

To create a token drop

Go to the

You can track all the claimers in the

npx make-agent contract
app.get('/api/ping', (req: Request, res: Response) => {
  return res.json({ message: "Pong" });
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});


app.post('/api/set_greeting', (req: Request, res: Response) => {
  const { greeting } = req.body as SetGreeting;

  if (typeof greeting !== 'string' || greeting.trim() === '') {
    return res.status(400).json({ error: 'Invalid greeting provided.' });
  }

  const functionCall: FunctionCallAction = {
    type: "FunctionCall",
    params: {
      methodName: "set_greeting",
      args: { greeting },
      gas: "30000000000000",
      deposit: "1"
    }
  };

  return res.json(functionCall);
});

app.get('/api/get_greeting', async (req: Request, res: Response) => {
  const methodName = "get_greeting";

  const requestBody = {
    jsonrpc: "2.0",
    id: "dontcare",
    method: "query",
    params: {
      request_type: "call_function",
      finality: "final",
      account_id: CONTRACT_ID,
      method_name: methodName,
      args_base64: Buffer.from(JSON.stringify({})).toString('base64')
    }
  };

  try {
    const response = await fetch('https://rpc.mainnet.near.org', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(requestBody)
    });

    const data = await response.json();
    let deserializedResult;

    if (Array.isArray(data.result.result)) {
      deserializedResult = String.fromCharCode(...data.result.result);
    } else {
      deserializedResult = data.result.result;
    }

    return res.json({ greeting: deserializedResult });
  } catch (error) {
    return res.status(500).json({ error: 'Failed to fetch data from NEAR RPC.' });
  }
});
app.get('/.well-known/ai-plugin.json', (req: Request, res: Response) => {
 "assistant": {
        "name": "Surgedev Assistant",
        "description": "An assistant designed to interact with the surgedev.near contract on the Near Protocol.",
        "instructions": "You are an assistant designed to interact with the surgedev.near contract on the Near Protocol. Your main functions are:\n\n1. [Set Greeting]: Use the /api/set_greeting endpoint to set a greeting. This endpoint will return a valid function call which you should be able to send. Ensure all required parameters are provided by the user as described in the paths section below.\n\n2. [Get Greeting]: Use the /api/get_greeting endpoint to retrieve the current greeting from the contract.\n\nWhen performing write operations:\n- Ensure all required parameters are non-empty and of the correct type.\n- Avoid using any special characters or formatting that might cause issues with the contract.\n- If the user provides invalid input, kindly ask them to provide valid data according to the parameter specifications.\n\nWhen performing view operations:\n- Simply use the appropriate /api/[function_name] endpoint and return the result to the user.\n\nImportant: For all write operations, the endpoints will return a function call object. You should clearly indicate to the user that this is a function call that needs to be sent to the blockchain, and not the final result of the operation.",
        "tools": [{
          "type": "generate-transaction"
        }]
      }
npx tsx ./index.ts & npx make-agent dev -p 8080
Manifest
like this one
NFT Drop Page
provenance on the token link.
Claim this token here.

Deploy Your Open Agent

This guide will walk you through how to deploy and test your Open Agent using the make-agent CLI tool. This method allows you to develop, test, and go live with your agent quickly.

1. Deploy Your Service to the Cloud

To take your Open Agent live, you can deploy it to a cloud provider such as Vercel, Google Cloud Platform (GCP), or Amazon Web Services (AWS). These services provide scalable hosting solutions and make your agent publicly accessible for real-world interactions.

Recommended cloud providers:

  • Vercel

  • Google Cloud

  • AWS

After deploying your service, ensure your agent's plugin manifest points to the publicly accessible URL of your deployment:

```typescript
"servers": [
    {
        "url": <YOUR_DEPLOYMENT_URL>
    },
],
```

2. Register (or update) with make-agent

Running make-agent deploy should take care of all the steps to validate your key, manifest and push updates within our registry. Include this in your CI/CD pipeline for ease of use.

npx make-agent deploy

Debug and Test Your Plugin

Once registered, you will receive a debug URL that will take you to the Playground to test your agent.

https://wallet.bitte.ai/smart-actions/prompt/hey?mode=debug&agentId=<agentId>

Note that your Agent ID is the deployed URL without the protocol scheme (no https). If you deployed to https://my-awesome-agent.com, your Agent ID is my-awesome-agent.com

Get Verified

When agents are registered, they will not be immediately available in the production registry. The verification process is manual for now.

Contact our team on Telegram to start the verification process when you're ready.

Cross Chain Signatures

Chain signatures enable NEAR to sign and execute transactions across multiple blockchains via an MPC (Multi-Party Computation) network. Fortunately, to implement this functionality in your DApp, you won't need to integrate MPC directly, as it's fully operational within Bitte Wallet. Building an EVM transaction is straightforward once you've established a basic connection with the wallet. Redirect to the wallet URL with the evmTx parameter and the wallet will handle the complexities of generating the EVM signature and sending the transaction.

Note: This functionality currently only works for the NEAR testnet.

// Build your favourite transaction!
const tx = {
  chainId: 11_155_111,
  to: "0xDEADBEEF00000000000000000000000000000000",
  value: 1n,
  data: "0x",
};

// Pass the transaction data to this url route.
const route = `https://wallet.bitte.ai/sign-evm?to=${tx.to}&value=${tx.value}&chainId=${tx.chainId}&data=${tx.data}&callback_url=https://yourdappurl.xyz`;

// Redirect to our wallet URL with the transaction to be sent, once successful user will be redirected to callback_url

Check out NEAR-CA if you would like to implement MPC directly without using a wallet, or to take advantage of its various utilities for interfacing between NEAR and EVM.

Sui Agent Building

Quick Start: Building Your Bitte Open Agent on Sui

Prerequisite: make-agent v0.3.1+ installed


1. Clone the Boilerplate & Install

This gives you the core agent framework, UI sandbox, and plugin manifest support.


2. Configure Your Bitte API Key

  1. Copy .env.example → .env and insert:


3. Wire Up Sui: Add Your Transaction Tool

In tools/, change any of the routes to return a sui transaction, check the sui ts sdk for more information on how to create Sui Transactions:


4. Declare Your Tool in the Plugin Manifest

Open ai-plugin/manifest.json (or wherever your manifest lives) and add the corresponding spec for your endpoint Since this is a next js project the route path will correspond to the folder


5. Add generate-sui-tx to the Tools Array

To enable the review transaction component in the frontend, add the generate-sui-tx primitive to the tools array in your configuration file:

This update ensures that the frontend can display the transaction review component appropriately.

6. Define Behaviour

To control how your agent behaves, customize its instructions—this is the equivalent of setting the system prompt. Use this to tailor the agent’s behavior to your tool’s needs. For example, you might instruct it to confirm addresses or amounts, adopt a specific tone or personality, or behave deterministically in certain scenarios.

If the transaction review screen isn’t appearing as expected, you can explicitly instruct the agent to show it after your tool call.

7. Run Locally & Test

  • The console UI opens your chat sandbox.

  • Ask the agent to build the transaction related to your tool

  • The agent will call your tool and then call generate-sui-tx to display the transaction signing component so you can try sending your transaction


7. Deploy Your Agent

  1. Push to GitHub.

  2. Deploy to vercel or any provider

  3. Update your URL env or hard code it in the spec

  4. Run:

This validates your key, registers your plugin URL, and you’re live!

Visit 🔑 and generate a key.

git clone https://github.com/BitteProtocol/agent-next-boilerplate.git
cd agent-next-boilerplate
pnpm install
dotenvCopyEditBITTE_API_KEY="bitte_YOUR_KEY_HERE"

  const { senderAddress, recipientAddress, amountInSui, network } = args;
  const tx = new Transaction();
  const MIST_PER_SUI = 1e9;
  const amountInMist = Math.floor(amountInSui * MIST_PER_SUI);

  if (amountInMist > Number.MAX_SAFE_INTEGER) {
    throw new Error('Amount exceeds safe integer limit');
  }
  
  const [coin] = tx.splitCoins(tx.gas, [tx.pure.u64(BigInt(amountInMist))]);
  tx.setSender(senderAddress);
  tx.transferObjects([coin], tx.pure.address(recipientAddress));

  const txBytes = await tx.build({ client: suiClientFor(network) });
  return { data: { suiTransactionBytes: Buffer.from(txBytes).toString('base64') } };
'/api/send-sui': {
  post: {
    summary: 'Send a Sui tokens',
    description: 'Accept the args and return a valid sui transaction in bytes to send tokens to an address',
    operationId: 'generateSuiTx',
    requestBody: {
      required: true,
      content: {
        'application/json': {
          schema: {
            type: 'object',
            properties: {
              senderAddress: {
                type: 'string',
                description: 'Address sending SUI',
              },
              recipientAddress: {
                type: 'string',
                description: 'Address receiving SUI',
              },
              amountInSui: {
                type: 'number',
                description: 'Amount of SUI to send',
              },
              network: {
                type: 'string',
                enum: ['mainnet', 'testnet', 'devnet'],
                default: 'mainnet',
                description: 'Which Sui network to use',
              },
            },
            required: ['senderAddress', 'recipientAddress', 'amountInSui'],
          },
        },
      },
    },
    responses: {
      '200': {
        description: 'Successful response',
        content: {
          'application/json': {
            schema: {
              type: 'object',
              properties: {
                success: {
                  type: 'boolean',
                  description: 'Whether the transaction was successfully built or validated',
                },
                data: {
                  type: 'object',
                  description: 'Additional result data',
                },
              },
            },
          },
        },
      },
      '500': {
        description: 'Error response',
        content: {
          'application/json': {
            schema: {
              type: 'object',
              properties: {
                error: {
                  type: 'string',
                  description: 'Error message',
                },
              },
            },
          },
        },
      },
    },
  },
},
{
  "tools": [
 tools: [
          { type: 'get-sui-balances' },
          { type: 'generate-sui-tx' },
        ],
pnpm dev
BITTE_AGENT_URL="https://my-sui-agent.vercel.app"
make-agent deploy
https://key.bitte.ai

MCP

Plug Bitte agents into your apps using MCP

Bitte MCP Server on Github

MCP Tools

Bitte agents

GOAT

Basekit

Add Bitte MCP server to Curser or other MCP

{
  "mcpServers": {
    "bitte-ai": {
      "url": "https://mcp.bitte.ai/sse"
    }
  }
}

Widget Component

Introduction

The BitteWidgetChat component is a React component that enables AI-powered chat interactions in your application. It supports both NEAR Protocol and EVM blockchain interactions through wallet integrations, allowing users to interact with smart contracts and perform transactions directly through the chat interface.

🔑 Before you begin, make sure you have:

  • A Bitte API Key - Get your beta BITTE_API_KEY here

Quick Start (<10min)

  1. Install package

  2. Add the Chat Component

  3. Setup API Route

  4. Wallet Connection

2. Install Package

pnpm install @bitte-ai/chat

2. Add the Widget Component

Import and use WidgetChat in your react app and select the agent that you would like to use, browse the available agents and their respective ids on the registry The apiUrl corresponds to a proxy to not expose your api key on the client. The historyApiUrl is needed to keep context and state of the chat.


import { BitteWidgetChat } from "@bitte-ai/chat";
import '@bitte-ai/chat/styles.css';

<BitteWidgetChat  
  agentId="your-agent-id"
  apiUrl="/api/chat"
  historyApiUrl="/api/history"
  widget={{
    widgetWelcomePrompts: {
      questions: [
        'What is the price of the NFT?',
        'Latest activity of a specific wallet',
        'Which tokens are trending?'
      ],
      actions: ['Buy NFT', 'Sell NFT', 'Swap NFT'],
    },
  }}
/>

3. Setup API Route

Create an API route in your Next.js application to proxy requests to the Bitte API to not expose your key

import type { NextRequest } from 'next/server';

const {
  BITTE_API_KEY,
  BITTE_API_URL = 'https://ai-runtime-446257178793.europe-west1.run.app/chat',
} = process.env;

export const dynamic = 'force-dynamic';
export const maxDuration = 60;

export const POST = async (req: NextRequest): Promise<Response> => {
  try {
    const data = await req.json();

    const requestInit: RequestInit & { duplex: 'half' } = {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${BITTE_API_KEY}`,
      },
      duplex: 'half',
    };

    const upstreamResponse = await fetch(`${BITTE_API_URL}`, requestInit);

    const headers = new Headers(upstreamResponse.headers);
    headers.delete('Content-Encoding');

    return new Response(upstreamResponse.body, {
      status: upstreamResponse.status,
      headers,
    });
  } catch (error) {
    console.error('Error in chat API route:', error);
    return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
      status: 500,
      headers: {
        'Content-Type': 'application/json',
      },
    });
  }
};

Create an history api route to keep the context of the widget chat.

import { type NextRequest, NextResponse } from 'next/server';

const { BITTE_API_KEY, BITTE_API_URL = "https://ai-runtime-446257178793.europe-west1.run.app" } =
  process.env;

export const dynamic = 'force-dynamic';
export const maxDuration = 60;

export const GET = async (req: NextRequest): Promise<NextResponse> => {
  const { searchParams } = new URL(req.url);
  const id = searchParams.get('id');
  const url = `${BITTE_API_URL}/history?id=${id}`;

  const response = await fetch(url, {
    headers: {
      Authorization: `Bearer ${BITTE_API_KEY}`,
    },
  });

  const result = await response.json();

  return NextResponse.json(result);
};

At this point the chat should already work but to be able to send transactions you will need to add a wallet connection

4. Add wallet connection

NEAR Integration

You can integrate with NEAR using either the NEAR Wallet Selector or a direct account connection. If you want to be able to send near transacitons through the chat you will need to define at least one of these

Using Wallet Selector

import { useBitteWallet, Wallet } from "@bitte-ai/react";
import { BitteWidgetChat } from "@bitte-ai/chat";
import '@bitte-ai/chat/styles.css';


export default function Chat() {
  const { selector } = useBitteWallet();
  const [wallet, setWallet] = useState<Wallet>();

  useEffect(() => {
    const fetchWallet = async () => {
      const walletInstance = await selector.wallet();
      setWallet(walletInstance);
    };
    if (selector) fetchWallet();
  }, [selector]);

  return (
    <BitteWidgetChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={{ near: { wallet } }}
    />
  );
}

Using Direct Account

import { Account } from "near-api-js";
// get near account instance from near-api-js by instantiating a keypair
<BitteWidgetChat
  agentId="your-agent-id"
  apiUrl="/api/chat"
  wallet={{ near: { account: nearAccount } }}
/>

EVM Integration

EVM integration uses WalletConnect with wagmi hooks:


import { useAppKitAccount } from '@reown/appkit/react';
import { useSendTransaction, useSwitchChain } from 'wagmi';

export default function Chat() {

  const { address } = useAppKitAccount();
  const { data: hash, sendTransaction } = useSendTransaction();
  const { switchChain } = useSwitchChain();
  
  return (
    <BitteWidgetChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={{
        evm: { address, hash, sendTransaction, switchChain },
      }}
    />
  );
}

SUI Integration

SUI integration uses WalletConnect with wagmi hooks:

import { useWallet as useSuiWallet } from '@suiet/wallet-kit';

export default function Chat() {

  const suiWallet = useSuiWallet();

  return (
    <BitteWidgetChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={ sui: { wallet: suiWallet },}
    />
  );
}

Example Usage

Here's how you might configure the BitteWidgetChat component, including some optional props and custom components:

          <BitteWidgetChat
            options={{
              agentImage: bitteAgent?.image,
              agentName: bitteAgent?.name,
              colors: chatColors,
            }}
            wallet={{
              near: {
                wallet: wallet,
              },
              evm: evmAdapter,
            }}
            agentId={searchParams.get('agentId') || bitteAgent?.id || 'bitte-assistant'}
            apiUrl="/api/chat"
            historyApiUrl="api/history"
            widget={{
              widgetWelcomePrompts: {
                questions: [
                  'What is the price of the NFT?',
                  'Latest activity of a specific wallet',
                  'Which tokens are trending?',
                ],
                actions: ['Buy NFT', 'Sell NFT', 'Swap NFT'],
              },
            }}
        />

Integrations

Developers can integrate Bitte Wallet either with wallet Selector or directly with callbacks

Bitte Wallet Integration via packages

  1. Using @bitte-ai/react You can check the readme here NPM:

    npm install @bitte-ai/react
    npm install @near-wallet-selector/modal-ui

    Yarn:

    yarn add @bitte-ai/react
    yarn add @near-wallet-selector/modal-ui

    PNPM:

    pnpm install @bitte-ai/react
    pnpm install @near-wallet-selector/modal-ui

    BitteWalletContextProvider

    the default way of interacting with Bitte Wallet is using the BitteWalletContextProvider

    properties:

    network : mainnet | testnet

    additionalWallets : WalletModuleFactory[] extra wallets setup

    import "@near-wallet-selector/modal-ui/styles.css";
    import { BitteWalletContextProvider } from  '@bitte-ai/react'
    
    <BitteWalletContextProvider
      network="mainnet"
    >
       <Component {...pageProps} />
    </BitteWalletContextProvider>

  2. Using @near-wallet-selector

The easiest way to use this package is to install it from the NPM registry, this package requires near-api-js v1.0.0 or above:

# Using Yarn
yarn add near-api-js

# Using NPM.
npm install near-api-js
# Using Yarn
yarn add @near-wallet-selector/bitte-wallet

# Using NPM.
npm install @near-wallet-selector/bitte-wallet

Then use it in your dApp:

import { setupWalletSelector } from "@near-wallet-selector/core";
import { setupBitteWallet } from "@near-wallet-selector/bitte-wallet";

const bitteWallet =  setupBitteWallet({
  networkId: 'mainnet',
  walletUrl: 'https://wallet.bitte.ai',
  callbackUrl: 'https://www.mywebsite.com',
  deprecated: false,
});

const selector = await setupWalletSelector({
  network: "testnet",
  modules: [bitteWallet],
});

Options

  • networkId: (string?): 'mainnet' or 'testnet' . Defaults to mainnet.

  • deprecated: (boolean?): Deprecated is optional. Default is false.

  • callbackUrl: (string?): Valid url to send your user after txn.

  • walletUrl: (string?): wallet url: https://wallet.bitte.ai for mainnet and https://testnet.wallet.bitte.ai for testnet.

License

This repository is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

Bitte Wallet Integration via URL Schemes

This guide explains how to interact with the Mintbase Wallet using URL schemes to perform operations like connecting or creating an account and signing transactions. Depending on your development environment, you can choose between the testnet and mainnet URLs.

Base URLs

Base URL
Network

testnet

mainnet

Connect or Create an Account

To connect or create an account, use the following endpoint. This action will redirect users to authenticate or create a new wallet account

  • Endpoint: /connect

  • URL: https://wallet.bitte.ai/connect

Parameters

  • success_url:

    The URL to which the wallet redirects after a successful login. It should be able to handle the incoming parameters.

    • Example: your_schema://`

Callback URL

The callback URL is defined in the success_url parameter. After successful authentication, the user will be redirected to this URL.

Parameters

  • account_id: The authenticated user's account ID.

  • public_key: The currently connected public key of the user's account.

Sign Transactions

To sign a transaction, direct the user to the sign transaction endpoint.

  • Endpoint: /sign-transaction

  • URL: https://wallet.bitte.ai/sign-transaction

Parameters

  • transactions_data: The encoded data for the transaction that needs to be signed. See this to learn how to format the transaction object. The transaction object should be URL encoded (`encodeURI(JSON.strinfigy(tx_data))`)

  • callback_url: The URL to redirect after the transaction signing process.

Callback URL

After signing the transaction, the wallet will redirect to the provided callback_url with additional transaction details.

Parameters:

  • transactionHashes: The hashes of the signed transactions.

Examples

1. Connect Account on Mainnet

https://wallet.bitte.ai/connect?success_url=https://mydapp.com

2. Sign Transaction on Mainnet

https://wallet.bitte.ai/sign-transaction?transactions_data=%5B%7B%22receiverId%22%3A%220.drop.proxy.mintbase.near%22%2C%22actions%22%3A%5B%7B%22type%22%3A%22FunctionCall%22%2C%22params%22%3A%7B%22methodName%22%3A%22mint%22%2C%22args%22%3A%7B%22metadata%22%3A%22%7B%5C%22media%5C%22%3A%5C%22C6iWEOxKqUHJ2eAr5_3i0jyiYPLCcpUdoxRvM38xViM%5C%22%2C%5C%22creatorAddress%5C%22%3A%5C%22aurora-ahghara.near%5C%22%2C%5C%22title%5C%22%3A%5C%22%5C%22%2C%5C%22description%5C%22%3A%5C%22%5C%22%7D%22%2C%22nft_contract_id%22%3A%22drops.mintbase1.near%22%7D%2C%22gas%22%3A%22200000000000000%22%2C%22deposit%22%3A%2213500000000000000000000%22%7D%7D%5D%7D%5D&callback_url=https://mintbase.xyz

https://testnet.wallet.bitte.ai
https://wallet.bitte.ai

Embeddable Chat Component

Bitte AI Chat

Introduction

The Bitte AI Chat component is a React component that enables AI-powered chat interactions in your application. It supports both NEAR Protocol and EVM blockchain interactions through wallet integrations, allowing users to interact with smart contracts and perform transactions directly through the chat interface.

🔑 Before you begin, make sure you have:

  • A Bitte API Key - Get your beta BITTE_API_KEY here


Quick Start (<10min)

  1. Install package

  2. Add the Chat Component

  3. Setup API Route

  4. Wallet Connection

1. Install Package

pnpm install @bitte-ai/chat

2. Add the Chat Component

Import and use BitteAiChat in your react app and select the agent that you would like to use, browse the available agents and their respective ids on the registry The apiUrl corresponds to a proxy to not expose your api key on the client


import {BitteAiChat} from "@bitte-ai/chat";
import '@bitte-ai/chat/styles.css';

<BitteAiChat  
  agentId="your-agent-id"
  apiUrl="/api/chat"
/>

3. Setup API Route

Create an API route in your Next.js application to proxy requests to the Bitte API to not expose your key. Nextjs app router implementation:

import type { NextRequest } from 'next/server';

const {
  BITTE_API_KEY,
  BITTE_API_URL = 'https://ai-runtime-446257178793.europe-west1.run.app/chat',
} = process.env;

export const dynamic = 'force-dynamic';
export const maxDuration = 60;

export const POST = async (req: NextRequest): Promise<Response> => {
  try {
    const data = await req.json();

    const requestInit: RequestInit & { duplex: 'half' } = {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${BITTE_API_KEY}`,
      },
      duplex: 'half',
    };

    const upstreamResponse = await fetch(`${BITTE_API_URL}`, requestInit);

    const headers = new Headers(upstreamResponse.headers);
    headers.delete('Content-Encoding');

    return new Response(upstreamResponse.body, {
      status: upstreamResponse.status,
      headers,
    });
  } catch (error) {
    console.error('Error in chat API route:', error);
    return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
      status: 500,
      headers: {
        'Content-Type': 'application/json',
      },
    });
  }
};

Nextjs page router implementation:

import type { NextApiRequest, NextApiResponse } from 'next';

const {
  BITTE_API_KEY,
  BITTE_API_URL = 'https://ai-runtime-446257178793.europe-west1.run.app/chat',
} = process.env;

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const data = req.body;

    const requestInit: RequestInit = {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${BITTE_API_KEY}`,
      },
    };

    const upstreamResponse = await fetch(`${BITTE_API_URL}`, requestInit);
    
    res.statusCode = upstreamResponse.status;
    
    for (const [key, value] of Object.entries(upstreamResponse.headers)) {
      if (key.toLowerCase() !== 'content-encoding') {
        res.setHeader(key, value as string);
      }
    }

    res.setHeader('Content-Type', upstreamResponse.headers.get('Content-Type') || 'application/json');
    
    if (!upstreamResponse.body) {
      return res.end();
    }

    const reader = upstreamResponse.body.getReader();
    
    async function readChunk() {
      const { done, value } = await reader.read();
      
      if (done) {
        return res.end();
      }
      
      res.write(value);
      await readChunk();
    }
    
    await readChunk();
    
  } catch (error) {
    console.error('Error in chat API route:', error);
    res.status(500).json({ error: 'Internal Server Error' });
  }
} 

At this point the chat should already work but to be able to send transactions you will need to add a wallet connection

4. Add wallet connection

EVM Integration

EVM integration uses WalletConnect with wagmi hooks:


import { useAppKitAccount } from '@reown/appkit/react';
import { useSendTransaction, useSwitchChain } from 'wagmi';

export default function Chat() {

  const { address } = useAppKitAccount();
  const { data: hash, sendTransaction } = useSendTransaction();
  const { switchChain } = useSwitchChain();
  
  return (
    <BitteAiChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={{
        evm: { address, hash, sendTransaction, switchChain },
      }}
    />
  );
}
import { Account } from "near-api-js";
// get near account instance from near-api-js by instantiating a keypair
<BitteAiChat
  agentId="your-agent-id"
  apiUrl="/api/chat"
  wallet={{ near: { account: nearAccount } }}
/>

SUI Integration

SUI integration uses WalletConnect with wagmi hooks:

import { useWallet as useSuiWallet } from '@suiet/wallet-kit';

export default function Chat() {

  const suiWallet = useSuiWallet();

  return (
    <BitteAiChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={ sui: { wallet: suiWallet },}
    />
  );
}

NEAR Integration

You can integrate with NEAR using either the NEAR Wallet Selector or a direct account connection. If you want to be able to send near transacitons through the chat you will need to define at least one of these

Using Wallet Selector

import { useBitteWallet, Wallet } from "@bitte-ai/react";
import { BitteAiChat } from "@bitte-ai/chat";
import '@bitte-ai/chat/styles.css';


export default function Chat() {
  const { selector } = useBitteWallet();
  const [wallet, setWallet] = useState<Wallet>();

  useEffect(() => {
    const fetchWallet = async () => {
      const walletInstance = await selector.wallet();
      setWallet(walletInstance);
    };
    if (selector) fetchWallet();
  }, [selector]);

  return (
    <BitteAiChat
      agentId="your-agent-id"
      apiUrl="/api/chat"
      wallet={{ near: { wallet } }}
    />
  );
}

Component Props

interface BitteAiChatProps {
  agentId: string; // ID of the AI agent to use
  apiUrl: string; // Your API route path (e.g., "/api/chat")
  historyApiUrl?: string; // Your history API route to keep context when signing transactions
  wallet?: WalletOptions; // Wallet configuration
  colors?: ChatComponentColors;
  options?: {
    agentName?: string; // Custom agent name
    agentImage?: string; // Custom agent image URL
    chatId?: string; // Custom chat ID
    prompt?: string // Custom Initial prompt
    localAgent?: {
      pluginId: string;
      accountId: string;
      spec: BitteOpenAPISpec;
    };
  placeholderText?: string;
  colors?: ChatComponentColors;
  customComponents?: {
    welcomeMessageComponent?: React.JSX.Element;
    mobileInputExtraButton?: React.JSX.Element; 
    messageContainer?: React.ComponentType<MessageGroupComponentProps>;
    chatContainer?: React.ComponentType<ChatContainerComponentProps>;
    inputContainer?: React.ComponentType<InputContainerProps>;
    sendButtonComponent?: React.ComponentType<SendButtonComponentProps>;
    loadingIndicator?: React.ComponentType<LoadingIndicatorComponentProps>;
    };
  };
  customToolComponents?: CustomToolComponent[];
}

export interface ReactToolComponent {
  name: string;
  component: React.ComponentType<CustomToolComponentProps>;
}

// Update CustomToolComponent type to align with BitteTool from primitives.ts
export type CustomToolComponent =
  | PortfolioTool
  | TransferTool
  | SwapTool
  | ReactToolComponent;

Custom Components

The BitteAiChat component provides several UI elements that can be customized via the customComponents under options prop. This enables full control over the appearance and behavior of key parts of the chat interface by passing in your own React components.

Available Custom Components

You can override the following built-in UI components:

customComponents?: {
  welcomeMessageComponent?: React.JSX.Element;
  mobileInputExtraButton?: React.JSX.Element;
  messageContainer?: React.ComponentType<MessageGroupComponentProps>;
  chatContainer?: React.ComponentType<ChatContainerComponentProps>;
  inputContainer?: React.ComponentType<InputContainerProps>;
  sendButtonComponent?: React.ComponentType<SendButtonComponentProps>;
  loadingIndicator?: React.ComponentType<LoadingIndicatorComponentProps>;
};

Component Types

Below are the expected prop types for each customizable component:

MessageGroupComponentProps

export interface MessageGroupComponentProps {
  message: SmartActionAiMessage;
  isUser: boolean;
  userName: string;
  children: React.ReactNode;
  style: {
    backgroundColor: string;
    borderColor: string;
    textColor: string;
  };
  uniqueKey: string;
}

ChatContainerComponentProps

export interface ChatContainerComponentProps {
  children: React.ReactNode;
  style?: {
    backgroundColor?: string;
    borderColor?: string;
  };
}

InputContainerProps

export interface InputContainerProps {
  children: React.ReactNode;
  style?: {
    backgroundColor?: string;
    borderColor?: string;
  };
}

SendButtonComponentProps

export interface SendButtonComponentProps {
  input: string;
  isLoading: boolean;
  buttonColor?: string;
  textColor?: string;
  onClick?: () => void;
}

LoadingIndicatorComponentProps

export interface LoadingIndicatorComponentProps {
  textColor?: string;
}

Example Usage

Here's how you might configure the BitteAiChat component, including some optional props and custom components:

<BitteAiChat
  agentId={searchParams.get('agentId') || bitteAgent?.id || 'bitte-assistant'}
  apiUrl="/api/chat"
  historyApiUrl="/api/history"
  options={{
    agentName: bitteAgent?.name,
    agentImage: bitteAgent?.image,
    colors: chatColors,
  }}
  wallet={{
    near: { wallet },
    evm: evmAdapter,
  }}
  customComponents={{
    welcomeMessageComponent: <CustomWelcome />,
    mobileInputExtraButton: <ExtraMobileButton />,
    messageContainer: CustomMessageGroup,
    chatContainer: CustomChatContainer,
    inputContainer: CustomInputContainer,
    sendButtonComponent: CustomSendButton,
    loadingIndicator: CustomLoadingIndicator,
  }}
/>

✅ Tip: All custom components are optional. If not provided, the default components will be used.

Custom Tool Components

The BitteAiChat component supports embedding interactive, data-driven tools directly into the chat UI through the customToolComponents prop. These tools allow users to interact with structured data returned by your agent’s API, such as portfolios, token swaps, or custom workflows.

How Tool Rendering Works

When your AI agent responds with a message that includes a data field , and that data matches a known type (like PortfolioResponse, TransferFTData, etc.), the chat interface can automatically render the corresponding tool component — as long as a tool is registered in customToolComponents with a matching name.

The name must match:

  • The operation name in your agent’s OpenAPI spec

  • The name field in the tool component configuration

There is no need to wrap the response in a tool object — the chat package dynamically maps the data to the corresponding component based on the configured name and type. Pre-Configured Tools

The @bitte-ai/chat package comes with built-in support for the following tools:

  • get-portfolio

  • swap

  • transfer-ft

As long as:

  • The agent's API response includes a data field that matches the correct type (PortfolioResponse, SwapFTData, or TransferFTData — all from @bitte-ai/types)

  • The OpenAPI spec defines the route using one of the above names (i.e. get-portfolio, swap, or transfer-ft as operation IDs or paths)

...then the matching tool UI will automatically be rendered — no manual configuration required.

These tools are auto-wired and will display a default UI out-of-the-box. You only need to use customToolComponents if you want to override these default UIs or add custom tools.

Example: Registering Tool Components

const customToolComponents = [
  {
    name: 'get-portfolio', // This should match the operationId or route name from your OpenAPI spec
    component: (props) => (
      <TokenList data={props.data as PortfolioResponse} />
    ),
  },
  {
    name: 'swap',
    component: (props) => (
      <Swap data={props.data as SwapFTData} />
    ),
  },
  {
    name: 'transfer-ft',
    component: (props) => (
      <Transfer data={props.data as TransferFTData} />
    ),
  },
  {
    name: 'my-custom-tool',
    component: (props) => <MyCustomComponent data={props.data} />,
  },
];

Then pass them into BitteAiChat:

<BitteAiChat
  agentId={searchParams.get('agentId') || bitteAgent?.id || 'bitte-assistant'}
  apiUrl="/api/chat"
  historyApiUrl="/api/history"
  wallet={{
    near: { wallet },
    evm: evmAdapter,
  }}
  options={{
    agentName: bitteAgent?.name,
    agentImage: bitteAgent?.image,
    colors: chatColors,
  }}
  customToolComponents={customToolComponents}
/>

Type Safety & Tool Interfaces

All tool types and data interfaces are available from @bitte-ai/types

Available Agents

Agent Name

Description

Category

Agent ID

CoWSwap Assistant

An assistant that generates transaction data for CoW Protocol Interactions

DeFi

near-cow-agent.vercel.app

Meme.cooking

Generates a transaction payload for creating a new memecoin on the meme.cooking platform

Memes

meme-cooking-bitte-agent.vercel.app

CoinGecko Agent

Provides real-time cryptocurrency data, including prices, market information, and charts

Investing

coingecko-ai.vercel.app

Ref Finance Agent

Provides token metadata and swaps tokens through Ref Finance

DeFi

ref-finance-agent.vercel.app

NEAR Roast Agent

Roasts a NEAR account based on their on-chain activity

Other

near-roast-agent.vercel.app

NEAR Staking

Stake, unstake, and see staking information

Other

staking-agent.intear.tech

Crypto Technical Analyst

Provides in-depth market analysis and sophisticated trading insights based on technical analysis

Investing

technical-analysis-agent.vercel.app

DAO Agent

Interacts with Sputnik DAO Contracts, query DAOs, create proposals, and vote on proposals

DAO

dao-agent.vercel.app

Safe Account Assistant

Manages Near{Safe} Account Structure

Wallet Management

near-safe-agent.vercel.app

Uniswap Assistant

Generates transaction data for Uniswap V3 Interactions

Other

near-uniswap-agent.vercel.app

GrowthMate Discovery

Discovers the ecosystem through relevant activities, news, and offers

Ecosystem

bitte-agent.vercel.app

Python Code Runner

A helpful assistant for running Python code snippets

Computational

bitte-wasmer-agent.fly.dev

PotLock Assistant

Helps users search projects and donations on PotLock platform and create projects

Other

potlockaiagent-hqd5dzcjajhpc3fa.eastus-01.azurewebsites.net

Delta Trade DCA Helper

Helps set up DCA plans to buy NEAR and other tokens

Investing

dcaagent.deltatrade.ai

SUI Defi Agent

check balances, swap, stake and more on SUI

Defi

bitte-sui-agent.vercel.app

Sui Explorer

Retrieve any blockchain data from SUI

Ecosystem

sui-explorer.vercel.app

Benqi Agent

Defi Agent for Benqi Protocol on Avalanche

Defi

benqi-agent.vercel.app

Bitte WETH Wraptor

Wrap and unwrap ETH.

Other

wraptor-agent.vercel.app

Bitte Distribute Tokens

Distribute tokens on EVM chains using csv files and more

Other

safe-airdrop-agent.vercel.app

Creating Custom Agents

Check out our docs for creating your own agent from an API

Example Projects

  • Bitte AI Chat Boilerplate

Styling

The component can be customized using the colors prop:

type ChatComponentColors = {
  generalBackground?: string; // Chat container background
  messageBackground?: string; // Message bubble background
  textColor?: string; // Text color
  buttonColor?: string; // Button color
  borderColor?: string; // Border color
};

Browser Redirects (Optional)

if you're having issues with your app or wallet containing redirects you can optionally use a history api to maintain context

Create an API route in your Next.js application that will allow your app if you want to save chat context when signing a transaction after getting redirected to the wallet.

import { type NextRequest, NextResponse } from 'next/server';

const { BITTE_API_KEY, BITTE_API_URL = 'https://wallet.bitte.ai/api/v1' } =
  process.env;

export const dynamic = 'force-dynamic';
export const maxDuration = 60;

export const GET = async (req: NextRequest): Promise<NextResponse> => {
  const { searchParams } = new URL(req.url);
  const id = searchParams.get('id');
  const url = `${BITTE_API_URL}/history?id=${id}`;

  const response = await fetch(url, {
    headers: {
      Authorization: `Bearer ${BITTE_API_KEY}`,
    },
  });

  const result = await response.json();

  return NextResponse.json(result);
};

make-agent

The swiss army knife for multi-chain AI agents

Make sure your make-agent package is running v0.3.1+

Make Agent CLI is a powerful command-line tool designed to streamline the management and deployment of AI agents across multiple chains. This tool simplifies the process of making your AI agents discoverable and registering them as plugins.

Running the CLI

To run the Make Agent CLI:

npx make-agent dev -p 3000

Available Commands

Currently, the CLI supports the following commands:

  1. dev: Make your AI agent discoverable and register the plugin

    npx make-agent dev -p <port_number>

    Options:

    • -p, --port <number>: Specify the local port to expose (required)

  2. deploy: Register or update your AI agent, making it discoverable as a plugin

    npx make-agent deploy [options]

    Options:

    • -u, --url <url>: The URL where your agent is hosted (optional)

    If no URL is provided, the command will attempt to determine the deployed URL automatically through environment variables.

  3. contract: Scaffold a basic agent from a NEAR contract that has an ABI

    npx make-agent contract

    You will be prompted to select a contractId, add a description with instructions on how the agent should use the contract and an output directory

  4. delete: Delete your AI agent plugin

    npx make-agent delete -u https://DEPLOYMENT_URL

    Options:

    • -i, --id <id>: Specify the plugin ID to delete (required)

  5. verify: Request your plugin's verification

    npx make-agent verify -u <url> -e <email> -r <repoUrl> -v <versionNumber> -c [cat1,cat2] -x [chainNum1,chainNum2]

    Options:

    • -u, --url <url>: (required) Specify the url of the deployed plugin

    • -e, --email <email>: (required) Provide an email so we can contact you regarding the verification process

    • -r, --repo <repoUrl>: (required) To verify a plugin we need the url for a public repository containing the plugin's code

    • -v, --version <versionNumber>: (optional) Specify the version of the plugin in case of an update

    • -c, --categories <categories>: (optional) List some categories that describe the type of plugin you're verifying.

    • -x, --chains <chainIds>: (optional) If your plugin works on specific evm chains, you can specify them so your plugin is easier to find.

    These options can also be defined in the agent spec in the "x-mb" object.

For more information about any command, you can use:

make-agent [command] --help

Example Usage

Development

This project was created using bun init in Bun v1.1.20. To start developing:

  1. Clone the repository

  2. Run bun install to install dependencies

  3. Modify the code in the commands and services directories as needed

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

make-agent speed run
npm: near-canpm
Logo