# Enable agents to accept payments based on usage

# Agent quickstart (Developer preview)

Learn how to build a basic chatbot and bill for usage with the Stripe Agent Toolkit.

> Explore this SDK to integrate Stripe into agentic workflows. Because agent behaviour is non-deterministic, use the SDK in a *sandbox* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes) and run evaluations to assess your application’s performance.
> 
> For security, we strongly recommend using [restricted API keys](https://docs.stripe.com/keys.md#create-restricted-api-secret-key) (`rk_*`) to limit your agent’s access to only the functionality it requires, especially in live mode. Tool availability is determined by the permissions you configure on the restricted key.

### Install the Stripe Agent Toolkit

Install the package and import it into your code.

#### npm

Install the library:

```bash
npm install --save @stripe/agent-toolkit
```

#### GitHub

Or download the `@stripe/agent-toolkit` library source code directly [from GitHub](https://github.com/stripe/agent-toolkit).

### Create an endpoint to handle the request

Add an endpoint on your server that handles the new chat input.

### Initialise the toolkit

Using your Stripe API key, create a new instance of the `StripeAgentToolkit`. The toolkit allows you to insert billing middleware and also access Stripe functionality.

### Provide the middleware to the model

Using middleware, you can report the prompt and completion token usage to Stripe through the Meter API. The `billing` configuration requires you to provide a [Customer](https://docs.stripe.com/api/customers/object.md) ID and input and output [Meter Events](https://docs.stripe.com/api/billing/meter-event/object.md).

Learn how to [setup usage-based billing](https://docs.stripe.com/billing/subscriptions/usage-based/implementation-guide.md).

### Call the model

Use Vercel’s AI SDK to call the model and stream back results to the client. Your request includes the existing message log and a system prompt to provide initial instructions to the model.

### Create a chat interface

Use Next.js and Vercel’s AI SDK to build a basic chat interface to call into the back end you built.

### Set your environment variables

Add your publishable and secret keys to a `.env` file. Next.js automatically loads them into your application as [environment variables](https://nextjs.org/docs/basic-features/environment-variables).

### Run the application

Start your app with `npm run dev` and go to <http://localhost:3000>.

### Testing

To test this functionality, send a message to the chat.

### View usage in the Dashboard

View your Meters in the [Stripe Dashboard](https://dashboard.stripe.com/meters) to confirm that events are sent successfully.

import { createStripeAgentToolkit } from '@stripe/agent-toolkit/ai-sdk';
// Initialize toolkit - use restricted key (rk_*) for better security.
const toolkit = await createStripeAgentToolkit({
  secretKey: process.env.STRIPE_SECRET_KEY!,
  configuration: {},
});
export async function POST(req: Request) {
    middleware: toolkit.middleware({
      billing: {
        customer: process.env.STRIPE_CUSTOMER_ID!,
        meters: {
          input: process.env.STRIPE_METER_INPUT!,
          output: process.env.STRIPE_METER_OUTPUT!,
        },
      },
    }),
  });
  // Call the model and stream back the results.
  const result = await streamText({
    model: model,
    system: SYSTEM_PROMPT,
    messages: convertToCoreMessages(messages),
  });
import { createStripeAgentToolkit } from '@stripe/agent-toolkit/ai-sdk';
// Initialize toolkit - use restricted key (rk_*) for better security.
const toolkit = await createStripeAgentToolkit({
  secretKey: process.env.STRIPE_SECRET_KEY!,
  configuration: {},
});
export async function POST(req: Request) {
    middleware: toolkit.middleware({
      billing: {
        customer: process.env.STRIPE_CUSTOMER_ID!,
        meters: {
          input: process.env.STRIPE_METER_INPUT!,
          output: process.env.STRIPE_METER_OUTPUT!,
        },
      },
    }),
  });
  // Call the model and stream back the results.
  const result = await streamText({
    model: model,
    system: SYSTEM_PROMPT,
    messages: convertToCoreMessages(messages),
  });
import { createStripeAgentToolkit } from '@stripe/agent-toolkit/ai-sdk';
// Initialize toolkit - use restricted key (rk_*) for better security.
const toolkit = await createStripeAgentToolkit({
  secretKey: process.env.STRIPE_SECRET_KEY!,
  configuration: {},
});
export async function POST(req: Request) {
    middleware: toolkit.middleware({
      billing: {
        customer: process.env.STRIPE_CUSTOMER_ID!,
        meters: {
          input: process.env.STRIPE_METER_INPUT!,
          output: process.env.STRIPE_METER_OUTPUT!,
        },
      },
    }),
  });
  // Call the model and stream back the results.
  const result = await streamText({
    model: model,
    system: SYSTEM_PROMPT,
    messages: convertToCoreMessages(messages),
  });
import { createStripeAgentToolkit } from '@stripe/agent-toolkit/ai-sdk';
// Initialize toolkit - use restricted key (rk_*) for better security.
const toolkit = await createStripeAgentToolkit({
  secretKey: process.env.STRIPE_SECRET_KEY!,
  configuration: {},
});
export async function POST(req: Request) {
    middleware: toolkit.middleware({
      billing: {
        customer: process.env.STRIPE_CUSTOMER_ID!,
        meters: {
          input: process.env.STRIPE_METER_INPUT!,
          output: process.env.STRIPE_METER_OUTPUT!,
        },
      },
    }),
  });
  // Call the model and stream back the results.
  const result = await streamText({
    model: model,
    system: SYSTEM_PROMPT,
    messages: convertToCoreMessages(messages),
  });
'use client';

import { useChat } from 'ai/react';

export default function Chat() {
  const {
    input,
    isLoading,
    handleInputChange,
    handleSubmit,
    messages,
  } = useChat();

  return (
    <div>
      {messages.map(m => (
        <div key={m.id}>
          {m.role === 'user' ? 'User: ' : 'Agent: '}
          {m.content}
        </div>
      ))}

      {isLoading && (
        <div>Loading...</div>
      )}

      <form onSubmit={handleSubmit}>
        <input
          value={input}
          placeholder="Write a message"
          onChange={handleInputChange}
          disabled={isLoading}
        />
      </form>
    </div>
  );
}
\# https://dashboard.stripe.com/apikeys
STRIPE_SECRET_KEY=<<YOUR_SECRET_KEY>>