# /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`).

{% hint style="success" %}
Have a look at [/transation](/brian-api/apis/transaction/transactions-flow.md) to understand the transaction flow from prompt request to execution.
{% endhint %}

## Understanding `/agent`&#x20;

The existing [`/transaction`](https://docs.brianknows.org/brian-api/apis/transaction) and [`/knowledge`](https://docs.brianknows.org/brian-api/apis/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

<mark style="color:green;">`POST`</mark> `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`](/brian-api/apis/transaction.md) and [`/knowledge`](/brian-api/apis/knowledge.md).

**Headers**

| Name              | Type             | Description        |
| ----------------- | ---------------- | ------------------ |
| x-brian-api-key\* | String           | Brian API key.     |
| Content-Type\*    | application/json | Body content type. |

**Request Body**

| Name      | Type            | Description                                                                                           |
| --------- | --------------- | ----------------------------------------------------------------------------------------------------- |
| 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*

{% hint style="success" %}
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.
{% endhint %}

**Request Example**

```jsx
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**

```json
{
  "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:

```json
{
  "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:

```json
{
  "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.

{% hint style="success" %}
For the moment, we suggest to often clean the message history sent to the API for better performance or at least after a couple of sucesfull response from the API.&#x20;
{% endhint %}

### 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.&#x20;

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".&#x20;

The request should be:

```typescript
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:

{% tabs %}
{% tab title="400: Missing parameters" %}

```json
{
  "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"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

2\) The user writes "to ETH".

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

```typescript
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:

{% tabs %}
{% tab title="400" %}

```json
{
  "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?"
    }
  ]
}
```

{% endtab %}
{% endtabs %}

3\) The user writes "on Base".

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

```typescript
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:

{% tabs %}
{% tab title="200" %}

```json
{
  "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."
        }
      ]
    }
  ]
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.brianknows.org/brian-api/apis/agent.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
