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

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 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. 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 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.

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.

// 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. The runtime automatically applies authentication, substitutes placeholders, and handles pagination identical to built-in providers.

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 to introspect the unified catalog for UI discovery.

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.
  • 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, 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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →