DocsOperate & extend
Operate & extend
Markdown ↗

Custom providers

On this pageConstruction and registrationAdapter obligationsReal qualification

An application can install its own adapter alongside AgenticDriver without changing the runtime or any language client. The host imports trusted code; remote applications select only a configured instance and an enabled model. Extensions run with the host's privileges. This is a compatibility boundary, not a JavaScript sandbox or a review of third-party code.

@agenticdriver/sdk/provider-kit exports defineProviderExtension, its TypeScript contracts, ProviderExtensionManifestSchema, providerEndpoint and readProviderResponse. The manifest JSON Schema is also included in the installed package. These are Node host modules; browser applications continue to import @agenticdriver/sdk/client.

Construction and registration

The independent NDJSON adapter demonstrates credential resolution, a host-owned endpoint, discovery, visible streaming, tools and private continuation state. The adapter requires an actual endpoint implementing that protocol. For a standard OpenAI-compatible gateway, use openaiCompatible instead.

ts
import {
  configuredDriver,
  readHostConfig,
  configuredServer,
} from "@agenticdriver/sdk/host";
import { serve } from "@agenticdriver/sdk/server";
import { customProvider } from "./custom-provider.mjs";

const path = "/absolute/path/to/host.json";
const config = await readHostConfig(path);
const driver = configuredDriver(config, path, {
  extensions: new Map([[customProvider.manifest.id, customProvider]]),
});
const server = await serve(driver, await configuredServer(config, path));
// On application shutdown: await server.close().

Example operator configuration:

json
{
  "version": 1,
  "usage": { "hostId": "enterprise-host" },
  "providers": [
    {
      "kind": "extension",
      "id": "company-agent",
      "accountId": "company-account",
      "models": ["YOUR_EXPLICIT_MODEL"],
      "extensionId": "example-ndjson",
      "extensionVersion": "1.0.0",
      "settings": { "endpoint": "https://inference.example/enterprise/" },
      "secretRefs": { "apiKey": { "env": "ENTERPRISE_API_KEY" } }
    }
  ],
  "tokens": [
    {
      "id": "review-app",
      "subject": "review-user",
      "providers": ["company-agent"],
      "tokenRef": { "file": "credentials/review-app.token" }
    }
  ]
}

Supply the model, endpoint and credentials for your service. A loopback HTTP endpoint can replace HTTPS for local development. The example endpoint protocol is illustrative; it is not an existing provider's API. For an OpenAI-compatible service, use the existing openaiCompatible({ baseUrl, models, apiKey }) factory instead of translating this example protocol.

The registry key, manifest ID and exact extension version must match. An absent registration, unsupported adapter contract or version mismatch fails with PROVIDER_EXTENSION_UNAVAILABLE. Configuration never imports modules or executes paths. The stock CLI has no extension registry; use a custom host entry point as above. Runtime RunRequest bodies reject extension/URL/settings fields. Metadata is application labeling and must never be interpreted as endpoint configuration.

The extension declares its own version and contractVersion: "1.0". Adapter ABI, HTTP protocol version and SDK package version are separate. Contract 1.0 is the supported construction/operation shape; breaking changes require a new contract version. Pin the extension package in the host's dependency lockfile as well as the version in host configuration. Version matching does not authenticate an installed package's contents.

Adapter obligations

The factory receives an instance ID, optional display name, explicit model allowlist, a validated JSON settings snapshot (at most 128 KB), and an optional getSecret(alias, signal) resolver. Validate your own settings before contacting an endpoint or reading a credential. configuredDriver restricts aliases to that instance's secretRefs and uses the existing host secret resolver; secrets are not included in discovery, run requests or usage records. Keep secret values out of settings. The SDK cannot identify arbitrary secrets hidden in custom JSON.

providerEndpoint requires HTTPS or loopback HTTP without URL credentials, query parameters or fragments. It returns a base URL ending with /. Keep URLs in the factory closure and disable redirects on every fetch. Preserve TLS verification. Do not derive hostnames, credential aliases, binaries or environment variables from prompts, tool arguments or metadata.

OperationContract
inspect({ signal })Optional read-only, non-generation probe returning an inspection code and optional model catalog. Discovery filters the catalog against the host allowlist. Return fixed inspection codes; never raw diagnostics.
complete(request, context)Translate the explicit model, messages, instructions, selected tool definitions and output-token bound. Return the complete visible text, optional tool calls, measured usage and private state.
context.emitText(delta)Visible incremental text only. With emitted text, the final turn must contain exactly that accumulated text. Do not emit reasoning or credentials. Declare textStreaming: true.
context.reportProgress()Real work, such as received function arguments or a completed processing batch. Never a timer, ping or lease heartbeat.
context.signalForward cancellation to network I/O, credential reads and child processes. Release resources in finally. The kit stops awaiting noncooperative implementations and suppresses late callbacks, but cannot stop arbitrary JavaScript or undo a side effect.
turn.toolCallsDeclare tools: true. Return at most 32 calls with stable nonempty IDs, valid names and JSON object arguments. The runtime validates selected tools and arguments and obtains approval before execution.
turn.nativeBounded JSON opaque to applications. It can preserve provider items/signatures inside a run; cross-run retention requires an explicitly selected native session and nativeContinuation: true. Never export it as visible history.
turn.usageReport only known measurements. Missing values remain unknown. Choose accurate usageSource provenance; never turn subscription estimates into invoice costs.

The helper freezes instance models and capabilities, checks the explicit model, rejects undeclared tools/streaming and validates a bounded (2 MB) result. Inspection has the runtime's separate discovery timeout. Runs have no default total or inactivity timeout. An application's explicit inactivity policy resets on real progress.

Unknown exceptions become the runtime's fixed INTERNAL_ERROR. A deliberately thrown DriverError is public: use fixed, actionable messages, never upstream bodies, stderr, stack traces, URLs containing secrets or arbitrary user content. The kit does not introduce provider/model/account fallback or automatic retries. Usage identity and the Usagestat integration remain host-owned. Text/Markdown context and scoped RAG use the ordinary driver request; capabilities must not imply unimplemented image/PDF or native-agent support.

Real qualification

Register the extension against its actual service and run meaningful prompts with an explicitly selected account and inexpensive model. Check discovery, streaming, cancellation, tools and reported usage individually; unsupported features must be reported honestly. The simulated provider-conformance package entry was removed. See real connection verification.

Maintained with the AgenticDriver SDKSource snapshot ↗