> For the complete documentation index, see [llms.txt](https://docs.bitte.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bitte.ai/agents/solana-agent-building.md).

# Solana Agent Building

Quickstart building your agent on Solana.

{% hint style="info" %}
Prerequisite: Complete [Agent Setup](https://docs.bitte.ai/agents/build-agent)
{% endhint %}

#### Adding Solana tools to your agent

You can change your agent's plugin settings by altering the manifest returned by the `GET /api/ai-plugin` route. Here you can find a `tools` array in `(manifest).'x-mb'.assistant.tools` . Add the `'generate-sol-tx'` primitive to the tools array like so:

<pre class="language-json5"><code class="lang-json5">{
  //...
  'x-mb': {
    'account-id': ACCOUNT_ID,
    assistant: {
      name: 'Solana Assistant',
      description:
        "An assistant that generates solana transactions.",
      instructions:
        "You create solana transactions by using the generate-sol-tx tool, which takes a fromPubKey, a toPubKey and an amountInSol and creates a simple SOL transfer.",
<strong>      tools: [
</strong><strong>        // Add 'generate-sol-tx' primitive here:
</strong><strong>        { type: 'generate-sol-tx' },
</strong><strong>        //...
</strong>      ],
    },
  },
  //...
}
</code></pre>

#### Using the generate-sol-tx tool

The `generate-sol-tx` tool takes either a **base64** encoded transaction or, if you wish to generate a simple SOL transfer, it can also take a **fromPubKey**(string), a **toPubKey**(string) and an **amountInSol**(number) as parameters. To use the second option, simply instruct the agent to use the generate-sol-tx tool when given these three parameters (see instructions in example above).&#x20;

If you want more flexibility in the types of possible transactions, the base64 encoded transaction is better suited for the job. You can add the transaction building logic to a route and then add the route to the manifest. Here's an example from our agent-boilerplate:

{% code title="Add a new path for solana transactions." %}

```json5
paths:{
  '/api/tools/create-sol-transaction': {
    get: {
      operationId: 'solTransfer',
      summary: 'Construct a Native Asset Solana Transfer',
      description:
        'Constructs an unsigned Solana transfer of {amount} to {recipient} from {solAddress}',
      parameters: [
        {
          name: 'solAddress',
          in: 'query',
          required: true,
          schema: {
            type: 'string',
          },
          description: "The connected user's solAddress (base58 encoded)",
        },
        {
          name: 'recipient',
          in: 'query',
          required: true,
          schema: {
            type: 'string',
          },
          description:
            'The transfer recipient address (base58 encoded) or token symbol',
        },
        {
          name: 'amount',
          in: 'query',
          required: true,
          schema: {
            type: 'number',
          },
          description:
            'The amount of SOL to transfer in token units (not lamports)',
        },
      ],
      responses: {
        '200': {
          description: 'Serialized Solana Transaction Bytes',
          content: {
            'application/json': {
              schema: {
                type: 'object',
                properties: {
                  transactionBytes: {
                    type: 'string',
                    description:
                      'The unsigned base64 encoded solana transaction',
                  },
                },
                required: ['transactionBytes'],
              },
            },
          },
        },
      },
    },
  },
  //...
}
```

{% endcode %}

{% code title="Create the route for that path with the transaction creation logic." %}

```typescript
// in ./api/tools/create-sol-transaction/route.ts
import { Connection, SystemProgram, Transaction } from '@solana/web3.js';
import { type NextRequest, NextResponse } from 'next/server';
import { TransferQuerySchema } from './schema';

const SOLANA_RPC =
  process.env.SOLANA_RPC ?? 'http://api.mainnet-beta.solana.com/';

export async function GET(request: NextRequest): Promise<NextResponse> {
  try {
    const { searchParams } = new URL(request.url);

    const { success, data, error } = TransferQuerySchema.safeParse(
      Object.fromEntries(searchParams.entries()),
    );
    if (!success) {
      return NextResponse.json(
        { type: 'InvalidInput', ...error },
        { status: 400 },
      );
    }
    const { solAddress, recipient, amount } = data;

    const transferParams = {
      fromPubkey: solAddress,
      toPubkey: recipient,
      lamports: amount,
    };

    const ix = SystemProgram.transfer(transferParams);

    const tx = new Transaction().add(ix);
    tx.feePayer = solAddress;

    const connection = new Connection(SOLANA_RPC, 'confirmed');
    const { blockhash } = await connection.getLatestBlockhash();
    tx.recentBlockhash = blockhash;

    const transactionBytes = tx
      .serialize({ requireAllSignatures: false })
      .toString('base64');

    return NextResponse.json({ transactionBytes }, { status: 200 });
  } catch (error) {
    const message = `${error}`;
    console.error(message);
    return NextResponse.json({ error: message }, { status: 500 });
  }
}

```

{% endcode %}

#### Test and Deploy

Now you can run your agent locally with:

```sh
pnpm dev
```

This should open a chat UI where you can ask the agent to make a solana transaction, providing it with the necessary parameters. **If the agent isn't calling your tool like expected or isn't picking up on the parameters correctly, try editing the agent's instructions.** \
After, if you wish to have your agent go live, deploy it to your preferred cloud platform (e.g. vercel) and update your agent url in .env:

```clike
BITTE_AGENT_URL="https://my-solana-agent.vercel.app"
```

Alternatively you can add it directly in the manifest's servers list:

<pre class="language-json5"><code class="lang-json5">{
  openapi: '3.0.0',
  info: {
    title: 'Boilerplate',
    description: 'API for the boilerplate',
    version: '1.0.0',
  },
<strong>  servers: [
</strong><strong>    {
</strong><strong>      url: "https://my-solana-agent.vercel.app",
</strong><strong>    },
</strong><strong>  ],
</strong>  //...
}
</code></pre>

Finally, deploy to bitte with make-agent:&#x20;

```
make-agent deploy
```

This will validate your key, register your agent URL, and then you'll be live!

#### See also

* Bitte Jupiter Agent (by @bh2smith): <https://github.com/bh2smith/jupiter-agent>
* Embeddable Chat Component: <https://docs.bitte.ai/agents/embeddable-chat-component>
