> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stigg.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Bring your own vendor

> Meter and gate any OpenAI-compatible API with no extra code, and any other LLM or AI client, including your own models, by writing a recipe.

The SDK is not limited to the vendors it ships with. Every built-in vendor is supported through a **recipe**: a small, plain-data description of which client methods make model calls, and where the response says how much they used. The same interface is open to you, so you can meter and gate any client:

* A vendor the SDK does not support yet.
* Your own models, or an internal AI service with its own client.
* A client you got from somewhere else, such as an open-source library.

Write a recipe and pass it to `wrap()`. Everything else, checking before each call and reporting after it, works exactly as it does for the built-in vendors.

## Any OpenAI-compatible API

Many vendors expose an API in **OpenAI's format**, and support calling it with OpenAI's `openai` client. Any of them that returns an OpenAI-shaped `usage` block is metered with no recipe at all: point the `OpenAI` client's `baseURL` at the vendor and wrap it.

```typescript theme={null}
import OpenAI from 'openai';

const client = stigg.wrap(
  new OpenAI({ baseURL: 'https://api.example-llm.com/v1', apiKey: process.env.EXAMPLE_API_KEY }),
);

await client.chat.completions.create({
  model,
  messages,
  stiggContext: { customerId: 'customer-acme', entitlement: { currencyId: 'credits' } },
});
```

Calls are reported with the OpenAI recipe: the `openai.chat.completions.create` and `openai.responses.create` event names, and the same metrics as [OpenAI](/documentation/ai-agents/providers/openai#what-is-reported). Which of those metrics are filled in depends on what the vendor returns in its `usage` block, so check the vendor's own API docs. To tell vendors apart in Stigg, add a dimension such as `provider` to the `stiggContext`.

Vendors with their own page, such as [Together AI](/documentation/ai-agents/providers/together), [Fireworks AI](/documentation/ai-agents/providers/fireworks), [DeepSeek](/documentation/ai-agents/providers/deepseek), [xAI](/documentation/ai-agents/providers/xai), [Perplexity](/documentation/ai-agents/providers/perplexity) and [vLLM](/documentation/ai-agents/providers/vllm), work exactly this way. Some vendors have a recipe of their own, which the SDK selects instead of the OpenAI recipe, so their calls are reported under their own event names: [OpenRouter](/documentation/ai-agents/providers/openrouter), [LiteLLM Proxy](/documentation/ai-agents/providers/litellm), [Groq](/documentation/ai-agents/providers/groq), [Cloudflare](/documentation/ai-agents/providers/cloudflare) and [Databricks](/documentation/ai-agents/providers/databricks).

> [!TIP]
>
> Many compatible vendors only include usage in a stream when `stream_options: { include_usage: true }` is set. Check one streamed call in Stigg before relying on it.

For a vendor whose API is not in OpenAI's format, write a recipe, as described below.

## Write a recipe

```typescript theme={null}
import type { ClientRecipe } from '@stigg/agent-sdk-js';

const myRecipe: ClientRecipe<'input_tokens' | 'output_tokens'> = {
  vendor: 'my-vendor',
  metrics: ['input_tokens', 'output_tokens'],
  methods: [
    {
      path: ['generate'],
      extractUsage: (result) => ({
        metrics: { input_tokens: result.usage.in, output_tokens: result.usage.out },
      }),
    },
  ],
};
```

| Field | What it is |
| - | - |
| `vendor` | A name for the vendor. Events are named after it, for example `my-vendor.generate`. |
| `metrics` | The names of the metrics this recipe reports. These are the names you meter on in Stigg. |
| `methods` | Every client method that makes a model call. Methods not listed here are passed through without checks or reporting. |
| `methods[].path` | Where the method lives on the client. `['generate']` is `client.generate()`, and `['chat', 'completions', 'create']` is `client.chat.completions.create()`. |
| `methods[].extractUsage` | A function that receives the method's result and returns what to report: `{ metrics }`, and optionally `dimensions` to add to the event, `raw` usage fields, and an `idempotencyKey`, such as the vendor's own request ID. Check the vendor's API docs for where its response reports usage. |
| `methods[].attachStream` | Optional. For a method that streams, reads usage from the stream and reports it once the stream finishes. |
| `methods[].estimate` | Optional. An estimate of the call's usage, used as the [requested usage](/documentation/ai-agents/access-enforcement#requested-usage) of the check. |
| `methods[].event` | Optional. The event name for this method, instead of one built from `vendor` and `path`. |
| `matches` | Optional. A function that recognizes the vendor's client, so `wrap()` can pick this recipe automatically. |
| `totalTokensMetric` | Optional. The name of a metric that is the vendor's total, if it reports one. |

You can also start from a built-in recipe and change part of it, for example to add an estimate to every method of `anthropicRecipe`. See [Requested usage](/documentation/ai-agents/access-enforcement#requested-usage) for an example.

## Use it

Pass the recipe to `wrap()`, then call the client as usual:

```typescript theme={null}
const client = stigg.wrap(myVendorClient, { recipe: myRecipe });

await client.generate({
  prompt,
  stiggContext: { customerId: 'customer-acme', entitlement: { currencyId: 'credits' } },
});
```

As with any wrapped client, the `stiggContext` says which customer the call's usage is reported for (`customerId`, required) and, optionally, which credits or metered feature to check before the call (`entitlement`). The SDK removes it before the call reaches your vendor. See [AI agents](/documentation/ai-agents/overview#what-it-is) for every field.

Make one call, then open the customer in the Stigg app and check that a usage event arrived with the metrics you expect.

## Contribute your recipe

The Agent SDK is [open source](https://github.com/stiggio/stigg-agent-sdk-ts) under the MIT license, and the built-in recipes are written exactly the way yours is. If you wrote a recipe for a vendor other developers use too, contribute it to the [Agent SDK on GitHub](https://github.com/stiggio/stigg-agent-sdk-ts/blob/main/CONTRIBUTING.md). Once it is merged, the SDK recognizes that vendor automatically and no one needs to pass a recipe for it.

## Usage without a client

Wrapping works when you call a model through a client object. Sometimes there is nothing to wrap: for example, you call a model over plain HTTP, or the usage is not a model call at all, such as a paid web-search API your agent uses. In that case, count the usage yourself and send it to Stigg with [`stigg.report()`](/api-and-sdks/references/sdk/backend/rest/agent-sdk#report):

```typescript theme={null}
await stigg.report({ customerId: 'customer-acme' }, { 'feature-web-searches': 1 });
```

The keys are the IDs of the Stigg features or credit types to report against. To check before the call, use [`stigg.check()`](/api-and-sdks/references/sdk/backend/rest/agent-sdk#check). For a full example, see [Actions that are not model calls](/documentation/ai-agents/access-enforcement#actions-that-are-not-model-calls).

Need a vendor we do not support yet? [Let us know](mailto:support@stigg.io).


## Related topics

- [Usage metering](/documentation/ai-agents/usage-metering.md)
- [Bring Your Own Solution](/api-and-sdks/integration/additional-deployment-methods/bring-your-own-solution.md)
- [Bring Your Own Cloud (BYOC)](/documentation/high-availability-and-scale/byoc/overview.md)
- [Welcome to Stigg](/documentation/getting-started/welcome-to-stigg.md)
- [Meter usage from your own gateway](/guides/ai-agents/meter-usage-from-your-own-gateway.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.