# How to Add Custom Provider API Integrations Beyond the Built-In Catalog in Agent-Native

> Easily extend Agent-Native by registering custom API providers at runtime. Integrate any external service beyond the built-in catalog with simple configuration.

- Repository: [Builder.io/agent-native](https://github.com/BuilderIO/agent-native)
- Tags: how-to-guide
- Published: 2026-06-29

---

**Agent-Native allows you to register custom API providers at runtime using the `provider-api-register` action, which stores configurations in the `custom_api_providers` SQL table and merges them with the static built-in catalog for immediate use via standard request actions.**

BuilderIO/agent-native ships with a static catalog of popular SaaS APIs, but production workflows often require connections to internal services or niche third-party platforms. When you need to add custom provider API integrations beyond the built-in catalog, the framework exposes a runtime registration system that validates, persists, and secures these custom configurations alongside native providers like Slack or GitHub.

## Registering a Custom Provider

The `provider-api-register` action defined in [`packages/dispatch/src/actions/provider-api-register.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/dispatch/src/actions/provider-api-register.ts) exposes a Zod-validated API for upserting custom providers. This action handles credential-key validation, scope management (`user` vs `org`), and persists only key names—never secret values—to the `custom_api_providers` SQL table.

The registration flow enforces strict security constraints through [`packages/core/src/provider-api/custom-registry.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/provider-api/custom-registry.ts). The `validateCustomBaseUrl` and `validateAllowedHostSuffixes` functions block private or internal hosts using `isBlockedExtensionUrlWithDns` and reject overly broad public suffixes like `com` to prevent credential leakage.

## Runtime Architecture

### Merging with Built-In Catalog

When executing requests, the runtime created by `createProviderApiRuntime` in [`packages/dispatch/src/server/lib/provider-api.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/dispatch/src/server/lib/provider-api.ts) loads custom providers via the `getCustomProviders` callback. It merges these entries with the static `PROVIDER_API_IDS` catalog, ensuring custom providers cannot shadow built-in IDs. This unified runtime enables the same actions—`provider-api-catalog`, `provider-api-request`, and `provider-api-docs`—to work identically for both built-in and custom providers.

### Security Validations

The custom registry guarantees **SSRF protection** by validating that base URLs resolve to public endpoints, not internal network addresses. The **host-suffix whitelist** requires explicit declaration of allowed domains (e.g., `api.example.com`), preventing attackers from exfiltrating credentials to arbitrary hosts. During request execution, `executeProviderApiRequest` resolves credential values from the vault at runtime and redacts them from responses.

## Practical Implementation

### Step 1: Register a New Provider

Call the `provider-api-register` action with the `upsert` operation to add a custom provider. The `id` must be unique, lowercase, and use hyphens for spaces. The `credentialKey` references a secret stored in your vault, not the actual value.

```typescript
await providerApiRegister.run({
  operation: "upsert",
  id: "my-api",
  label: "My Awesome API",
  baseUrl: "https://api.myservice.com/v1",
  auth: {
    type: "api-key-header",
    credentialKey: "MY_API_KEY",
    headerName: "X-Api-Key",
  },
  docsUrls: ["https://docs.myservice.com"],
  allowedHostSuffixes: ["api.myservice.com"],
  defaultHeaders: { Accept: "application/json" },
  scope: "org",
});

```

### Step 2: List and Manage Providers

List existing custom providers to verify registration or retrieve metadata for UI rendering. Use the `delete` operation to remove obsolete entries.

```typescript
// List all custom providers
const result = await providerApiRegister.run({ operation: "list" });
console.log(result.providers);

// Delete a provider
await providerApiRegister.run({
  operation: "delete",
  id: "my-api",
});

```

### Step 3: Execute Requests

Once registered, invoke your custom provider using `provider-api-request` in [`packages/dispatch/src/actions/provider-api-request.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/dispatch/src/actions/provider-api-request.ts). The runtime automatically applies authentication, substitutes placeholders, and handles pagination identical to built-in providers.

```typescript
const resp = await providerApiRequest.run({
  provider: "my-api",
  method: "GET",
  path: "/items",
  query: { limit: 10 },
});

console.log(resp.response.json);

```

Use `provider-api-catalog` from [`packages/dispatch/src/actions/provider-api-catalog.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/dispatch/src/actions/provider-api-catalog.ts) to introspect the unified catalog for UI discovery.

```typescript
const catalog = await providerApiCatalog.run({});
console.table(catalog.providers.map(p => ({
  id: p.id,
  label: p.label,
  auth: p.auth.type,
})));

```

## Summary

- **Registration**: Use `provider-api-register` to persist custom providers to the `custom_api_providers` table with scoped access (`user` or `org`).
- **Security**: The system enforces SSRF protection via `validateCustomBaseUrl` and restricts credential scope through `allowedHostSuffixes` validation in [`custom-registry.ts`](https://github.com/BuilderIO/agent-native/blob/main/custom-registry.ts).
- **Runtime**: `createProviderApiRuntime` merges custom providers with the built-in catalog, making them available to `provider-api-request` and `provider-api-catalog`.
- **Credentials**: Only key names are stored; secret values are fetched from the vault at runtime and redacted from responses.

## Frequently Asked Questions

### Can custom providers override built-in providers?

No. According to the runtime implementation in [`packages/dispatch/src/server/lib/provider-api.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/dispatch/src/server/lib/provider-api.ts), custom providers are merged with the static `PROVIDER_API_IDS` catalog but cannot shadow built-in IDs. The system explicitly prevents custom providers from using IDs that conflict with native integrations like Slack or GitHub.

### How are credentials stored securely?

The `provider-api-register` action stores only **credential key names** (e.g., `MY_API_KEY`) in the SQL table, never the actual secret values. At request time, `executeProviderApiRequest` fetches the secret from the vault and injects it into the HTTP headers. Response processing automatically redacts these values to prevent accidental exposure in logs or UI.

### What authentication types are supported?

The custom registry supports various authentication schemes configured via the `auth` object. The example demonstrates `api-key-header` mode, which sends the resolved credential in a specified HTTP header. The validation logic in [`packages/core/src/provider-api/custom-registry.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/provider-api/custom-registry.ts) ensures the credential key references a valid vault entry before persisting the provider configuration.

### How does Agent-Native prevent SSRF attacks?

The `validateCustomBaseUrl` function in [`packages/core/src/provider-api/custom-registry.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/provider-api/custom-registry.ts) blocks requests to private IP ranges and internal hostnames using `isBlockedExtensionUrlWithDns`. Additionally, `validateAllowedHostSuffixes` rejects overly broad public suffixes (like `com` or `net`), ensuring credentials can only be sent to specific, whitelisted domains such as `api.myservice.com`.