πŸ§™β€β™‚οΈ/agent

The /agent endpoint is a new feature of the Brian API designed to build chat-like apps or integrate chat features within existing apps.

The /agent endpoint has the capabilities of /transaction and /knowledge, which means that you can ask for both transactions (/transaction) and web3 info (/knowledge).

Understanding /agent

The existing /transaction and /knowledge endpoints allow users to send a single prompt and get a response (either a transaction or textual information). However, these endpoints do not maintain chat history context β€” each prompt is handled independently, without awareness of previous requests.

The new /agent endpoint introduces session-based context, allowing developers to maintain a conversation history between the user and Brian within the same session. This means that previous messages and responses generated by Brian can be "remembered", for more dynamic and powerful interactions.

Why message history matters

Being able to have a message history significantly improves the capabilities of the Brian API by combining the functionalities of /transaction and /knowledge. With this, developers can build more powerful chat-like use cases, such as:

  • user: β€œi want to swap 100 usdc on Base”

  • brian: β€œok, what is the token to buy for the swap operation?”

  • user: β€œeth”

  • brian: generates the executable transaction for swapping 100 usdc to eth on base

or:

  • user: β€œwhen vitalik.eth expires on ethereum?”

  • brian: β€œoctober 20 2040…”

  • user: β€œgot it, renew it for another 4 years on ethereum”

  • brian: generates the executable transaction for renewing vitalik.eth for 4 years on ethereum

or users can ask both questions and transactions using the same /agent endpoint:

  • user: β€œwhat is uniswap v4 hooks?”

  • brian: β€œuniswap v4 is ……..”

  • user: β€œok now bridge 1 eth from arbitrum to zk sync”

  • brian: generates the executable transaction for bridging 1 eth from arbitrum to zk sync

How /agent works

POST https://api.brianknows.org/api/v0/agent

Allows you to send a chat history to Brian.

The currently available actions are those supported by /transaction and /knowledge.

Headers

NameTypeDescription

x-brian-api-key*

String

Brian API key.

Content-Type*

application/json

Body content type.

Request Body

NameTypeDescription

prompt*

String

User input prompt.

address*

String

Address that will send the transactions.

chainId

String

Chain ID of the user. Can be specified here or in the messages parameter.

messages

array object[]

messages exchanged between the user and Brian (conversation history). It represents the chat history.

*mandatory parameters

If you don't pass the chainId in the body, the source chain will be deducted from the chat history, if available. Otherwise, it will throw an error.

Request Example

fetch('<https://api.brianknows.org/api/v0/agent>', {
  method: 'POST',
  headers: {
    'X-Brian-Api-Key': 'API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    prompt: 'ethereum',
    address: 'vitalik.eth',
    messages: [
      {
        sender: 'user',
        content: 'when vitalik.eth expires?'
      },
      {
        sender: 'brian',
        content: 'The ENS domain vitalik.eth.eth (0xd8dA...6045) expiration is Thu Nov 29 2040 08:36:18 GMT+0100 (Central European Standard Time).'
      },
      {
        sender: 'user',
        content: 'ok, renew it'
      },
      {
        sender: 'brian',
        content: 'What is the chain you would like to perform this operation on?'
      }
    ]
  })
})

Response example

{
  "result": [
    {
      "solver": "Brian",
      "action": "ENS Renewal",
      "type": "write",
      "data": {
        "description": "You are about to renew the ENS domain \\"vitalik.eth\\" for 12 months. The ENS \\"vitalik.eth\\" renewal cost for 12 months is 0.0021 ETH ($5.006591677699126).",
        "steps": [
          {
            "chainId": 1,
            "blockNumber": 20734848,
            "from": "0x1358155a15930f89eBc787a34Eb4ccfd9720bC62",
            "to": "0x253553366Da8546fC250F225fe3d25d0C782303b",
            "value": "2347997171390886",
            "data": "0xacf1a84100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000001e133800000000000000000000000000000000000000000000000000000000000000007766974616c696b00000000000000000000000000000000000000000000000000",
            "gasLimit": "200000"
          }
        ],
        "fromChainId": 1,
        "fromAmount": "2347997171390886",
        "fromToken": {
          "address": "0x0000000000000000000000000000000000000000",
          "chainId": 1,
          "symbol": "ETH",
          "decimals": 18,
          "name": "ETH",
          "coinKey": "ETH",
          "logoURI": "<https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png>",
          "priceUSD": "2345.51"
        },
        "fromAddress": "0x1358155a15930f89eBc787a34Eb4ccfd9720bC62",
        "toChainId": 1,
        "finalEnsPriceString": "2347997171390886",
        "toAmountMin": "2347997171390886",
        "toToken": {
          "address": "0x0000000000000000000000000000000000000000",
          "chainId": 1,
          "symbol": "ETH",
          "decimals": 18,
          "name": "ETH",
          "coinKey": "ETH",
          "logoURI": "<https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png>",
          "priceUSD": "2345.51"
        },
        "toAddress": "0x253553366Da8546fC250F225fe3d25d0C782303b"
      }
      "extractedParams": {
        "action": "ensrenewal",
        "address": "vitalik.eth",
        "duration": "365",
        "chain": "ethereum"
      },
      "conversationHistory": [
        {
          "sender": "user",
          "content": "when vitalik.eth expires?"
        },
        {
          "sender": "brian",
          "content": "The ENS domain vitalik.eth.eth (0xd8dA...6045) expiration is Thu Nov 29 2040 08:36:18 GMT+0100 (Central European Standard Time)."
        },
        {
          "sender": "user",
          "content": "ok, renew it"
        },
        {
          "sender": "brian",
          "content": "What is the chain you would like to perform this operation on?"
        },
        {
          "sender": "user",
          "content": "ethereum"
        },
        {
          "sender": "brian",
          "content": "You are about to renew the ENS domain \"vitalik.eth\" for 12 months. The ENS \"vitalik.eth\" renewal cost for 12 months is 0.0020 ETH ($5.010546811623313)."
        }
      ]
    }
  ]
}

Integrating /agent

Body request

As shown in the example above, the body parameters are:

  • prompt: the last user prompt request.

  • address: the address (EOA/smart contract) requesting a transaction.

  • chainId: optional chainId. If you don't provide it, the source chain will be deducted from the chat history, if available.

  • messages: chat history between the user and Brian.

Handle body requests in the session

  • First message of the session: In the first request, the prompt field should be populated with the user's input, while the messages[] array should be empty. This marks the beginning of the session, so there are no prior messages to include.

Example of how the session request should be built on the first message:

{
  "prompt": "I want to swap 100 USDC on Base",
  "address": "0xYourAddressOrEns",
  "messages": []
}
  • Subsequent messages in the session: From the second message onwards, the messages[] array should contain the conversation history between the user and Brian. In these cases, the prompt field will hold the new user request, while messages[] will include the previous exchanges between Brian and the user.

Example of how the session request should be built from the second message onwards:

{
  "prompt": "ETH",
  "address": "0xYourAddressOrEns",
  "messages": [
    {
      "sender": "user",
      "content": "I want to swap 100 USDC on Base"
    },
    {
      "sender": "brian",
      "content": "OK, what is the token for the swap operation?"
    }
  ]
}

Storing messages

When integrating the /agent endpoint, developers have the flexibility to decide how to store the conversation history (messages[]) of a user session. Possible approaches include:

  • In-memory storage: Store the messages in temporary memory (e.g., a JavaScript array) and reset them when the session ends.

  • Database storage: Store messages in a database for long-term persistence and reset them when the session ends.

  • Key-value storage: Store messages in a key-value store (eg. Redis), which can handle quick access to active sessions and reset them when the session ends.

  • Other solutions: for example, when integrating /agent within an XMTP bot (try brian-agent.eth on Converse client), the messages are already stored as part of the XMTP chat history. In such a scenario, there's no need for additional storage, as the XMTP SDK can retrieve the messages at runtime.

Step-by-step procedure on how to create body requests during the session

This paragraph explains step-by-step how to construct body requests for API calls to /agent during a chat session from a developer's point of view.

It is fundamental to understand that the /agent endpoint returns:

  • 200: only when a transaction or info request can be generated from the prompt + messages (chat history).

  • 400: when a transaction or info request cannot be generated from the prompt + messages because certain parameters are missing. Consequently, the developer during the session must take the error message returned by Brian and add it to the messages array parameters for the next request

Let's make an example:

1) User writes "swap 100 usdc".

The request should be:

fetch('<https://api.brianknows.org/api/v0/agent>', {
  method: 'POST',
  headers: {
    'X-Brian-Api-Key': 'API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    prompt: 'swap 100 usdc',
    address: 'limone.eth',
    messages: []
  })
})

The /agent response is a 400 with the following error:

{
  "error": "Hey there! I see you're looking to make a swap. Could you let me know which token you'd like to buy? That way, I can help you out better. Thanks!",
  "extractedParams": [
    {
      "action": "swap",
      "chain": "",
      "token1": "usdc",
      "token2": "",
      "address": "",
      "amount": "100"
    }
  ],
  "conversationHistory": [
    {
      "sender": "user",
      "content": "swap 100 usdc"
    }
  ]
}

2) The user writes "to ETH".

The request should contain the new prompt along with the previous error message:

fetch('<https://api.brianknows.org/api/v0/agent>', {
  method: 'POST',
  headers: {
    'X-Brian-Api-Key': 'API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    prompt: 'to ETH',
    address: 'limone.eth',
    messages: [
    {
      "sender": "user",
      "content": "I want to swap 100 usdc"
    },
    {
      "sender": "brian",
      "content": "Hey there! I see you're looking to make a swap. Could you let me know which token you'd like to buy? That way, I can help you out better. Thanks!"
    }
    ]
  })
})

The /agent response is a 400 with the following error:

{
  "error": "What is the chain you would like to perform this operation on?",
  "extractedParams": [
    {
      "action": "swap",
      "chain": "",
      "token1": "usdc",
      "token2": "eth",
      "address": "",
      "amount": "100"
    }
  ],
  "conversationHistory": [
    {
      "sender": "user",
      "content": "I want to swap 100 usdc"
    },
    {
      "sender": "brian",
      "content": "Hey there! I see you're looking to make a swap. Could you let me know which token you'd like to buy? That way, I can help you out better. Thanks!"
    },
    {
      "sender": "user",
      "content": "to ETH"
    },
    {
      "sender": "brian",
      "content": "What is the chain you would like to perform this operation on?"
    }
  ]
}

3) The user writes "on Base".

The request should contain the new prompt along with the previous error messages:

fetch('<https://api.brianknows.org/api/v0/agent>', {
  method: 'POST',
  headers: {
    'X-Brian-Api-Key': 'API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    prompt: 'on Base',
    address: 'limone.eth',
    messages: [
    {
      "sender": "user",
      "content": "I want to swap 100 usdc"
    },
    {
      "sender": "brian",
      "content": "Hey there! I see you're looking to make a swap. Could you let me know which token you'd like to buy? That way, I can help you out better. Thanks!"
    },
    {
      "sender": "user",
      "content": "to ETH"
    },
    {
      "sender": "brian",
      "content": "What is the chain you would like to perform this operation on?"
    }
    ]
  })
})

At this point, the /agent response is a 200 providing the requested swap transaction:

{
  "result": [
    {
      "solver": "Enso",
      "action": "swap",
      "type": "write",
      "data": {
        "description": "You are about to swap 100.0 USDC ($100.1) for 0.040 ETH ($99.9) on Base using Enso solver. The address receiver is 0x1358155a15930f89eBc787a34Eb4ccfd9720bC62.",
        "steps": [
          {
            "chainId": 8453,
            "blockNumber": 21625399,
            "from": "0x1358155a15930f89eBc787a34Eb4ccfd9720bC62",
            "to": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
            "gasLimit": "80000",
            "data": "0x095ea7b300000000000000000000000080eba3855878739f4710233a8a19d89bdd2ffb8e0000000000000000000000000000000000000000000000000000000005f5e100",
            "value": "0"
          },
          {
            "chainId": 8453,
            "blockNumber": 21625399,
            "from": "0x1358155a15930f89eBc787a34Eb4ccfd9720bC62",
            "to": "0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E",
            "gasLimit": "345347",
            "data": "0xb35d7e73000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029130000000000000000000000000000000000000000000000000000000005f5e100000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000008a9059cbb010001ffffffffff833589fcd6edb6e08f4c7c32d4f71b54bda02913095ea7b3010203ffffffffff833589fcd6edb6e08f4c7c32d4f71b54bda0291319198595a30485ffffffff85111111125421ca6dc452d289314280a0f8842a659bd3b227018504ffffffff056675a323dedb77822fcf39eaa9d682f6abe72555ddcd52200105ffffffffff057e7d64d987cab6eed08a191c4c2459daf2f8ed0b19198595a30586ffffffffff1358155a15930f89ebc787a34eb4ccfd9720bc626e7a43a3010507ffffffff057e7d64d987cab6eed08a191c4c2459daf2f8ed0b241c59120105ffffffffffff7e7d64d987cab6eed08a191c4c2459daf2f8ed0b000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000008600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000129b480ad625bcd1a5c3a1c10d708114726fa467000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000111111125421ca6dc452d289314280a0f8842a6500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000005f45a600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005c807ed2379000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd09000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd090000000000000000000000007d585b0e27bbb3d981b7757115ec11f47c4769940000000000000000000000000000000000000000000000000000000005f45a60000000000000000000000000000000000000000000000000008a43f6539a353e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000046e00000000000000000000000000000000000000000000045000043a0003f0512003c01acae3d0173a93d819efdc832c7c4f153b06833589fcd6edb6e08f4c7c32d4f71b54bda02913016452bbbe2900000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000671e517cdef66c6c178087fd931514e99b04479e4d3d956c0002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f45a6000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000625745d692b2400000000000000000000000000000000000000000000000000000000671e517c00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000007d585b0e27bbb3d981b7757115ec11f47c47699400000000000000000000000000000000000000000000000000005af3107a40000000000000000086fb9011e2ff8b85700000000000000005784141ea082380000000000000001fa72a814595da483000000000000000000281967d8eade9f05f00000000000000000000000000000000000000000004a963b280a64b330bc48200000000000000004563918244f400000000000000000000006a94d74f430000000000000000000000000000671e51540000000000000000000044364c5bb000000000000000000000000000000000000000000000000000000000000000004128a9125558dbd81d9a74af9f04d915a7505757a7263f5f0f0ad350c2c24b117b612244009379d2ab449a8dd5bb815320719455db5b19a04408aae5bc0599534a1b0000000000000000000000000000000000000000000000000000000000000000a0f2fa6b66eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000723184cdcc4fbc061111111125421ca6dc452d289314280a0f8842a6500000000000000000000000000000000000097864b9100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000008a3f4713a61b82",
            "value": "0"
          }
        ],
        "gasCostUSD": "",
        "fromChainId": 8453,
        "fromAmountUSD": "100.1201441730076",
        "fromAmount": "100000000",
        "fromToken": {
          "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
          "chainId": 8453,
          "symbol": "USDC",
          "decimals": 6,
          "name": "USD Coin",
          "coinKey": "USDC",
          "logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
          "priceUSD": "1.001201441730076"
        },
        "fromAddress": "0x1358155a15930f89eBc787a34Eb4ccfd9720bC62",
        "toChainId": 8453,
        "toAmountUSD": "99.85106923258168",
        "toAmount": "40116619887578922",
        "toAmountMin": "40116619887578922",
        "toToken": {
          "address": "0x0000000000000000000000000000000000000000",
          "chainId": 8453,
          "symbol": "ETH",
          "decimals": 18,
          "name": "ETH",
          "coinKey": "ETH",
          "logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png",
          "priceUSD": "2489.02"
        },
        "toAddress": "0x80EbA3855878739F4710233A8a19d89Bdd2ffB8E",
        "receiver": "0x1358155a15930f89eBc787a34Eb4ccfd9720bC62",
        "protocol": {
          "key": "enso",
          "name": "enso",
          "logoURI": ""
        }
      },
      "extractedParams": {
        "action": "swap",
        "chain": "Base",
        "token1": "usdc",
        "token2": "eth",
        "address": "",
        "amount": "100"
      },
      "conversationHistory": [
        {
          "sender": "user",
          "content": "I want to swap 100 usdc"
        },
        {
          "sender": "brian",
          "content": "Hey there! I see you're looking to make a swap. Could you let me know which token you'd like to buy? That way, I can help you out better. Thanks!"
        },
        {
          "sender": "user",
          "content": "to ETH"
        },
        {
          "sender": "brian",
          "content": "What is the chain you would like to perform this operation on?"
        },
        {
          "sender": "user",
          "content": "on Base"
        },
        {
          "sender": "brian",
          "content": "You are about to swap 100.0 USDC ($100.1) for 0.040 ETH ($99.9) on Base using Enso solver. The address receiver is 0x1358155a15930f89eBc787a34Eb4ccfd9720bC62."
        }
      ]
    }
  ]
}

Last updated