Appearance
Model Provider Adapters
Initiative 1 adds a permanent, model-agnostic provider adapter layer to the platform. This page explains the architecture; see OpenAI Adapter for the first concrete implementation, Provider Connections (Initiative 2) for how a tenant's own credentials — never CARC's — get injected into a managed execution, and Execution Profiles (Initiative 3) for the canonical execution contract that ties an adapter, a connection, and a model configuration together.
The proof this initiative makes
The same Runtime Control Engine — unchanged policy, evidence, risk, approval, recording, replay, and metrics logic — governs three kinds of Agent Run:
- synthetic — the engine's own in-process reference agent
- externally submitted: a company ran its own model and handed the engine a finished output (External Agent Runs)
- managed — the platform executed a real external model itself, through a provider adapter (this page)
The Runtime Control Engine never imports a provider SDK type and never knows which provider produced an output. It only ever evaluates a standardized result.
Agent Registry vs. Adapter Registry — two separate concepts
| Agent Registry | Adapter Registry | |
|---|---|---|
| Answers | Which agent is this, who owns it, what may it do, is it trusted to run? | How does the platform talk to an external model/agent provider? |
| Entity | RegisteredAgent | RegisteredAdapter (secret-free wire summary) |
| Governs | whether an agent may run | how an execution request reaches a real provider |
| Connected by | RegisteredAgent.adapter_id (nullable — an agent may have no adapter at all) | — |
An agent with no adapter_id can still be used via bring-your-own execution or the synthetic path — it simply cannot be executed through the managed endpoint below.
Initiative 2 adds a third, equally separate concept: the Provider Connection, which supplies WHOSE credentials a managed execution uses.
Initiative 3 adds a fourth: the Execution Profile, the canonical execution contract — model, inference parameters, timeouts/retries. As of Initiative 3, a RegisteredAgent no longer references adapter_id/provider_connection_id directly for managed execution; it references exactly one ExecutionProfile via execution_profile_id, and the profile itself carries adapter_id + provider_connection_id. RegisteredAgent.adapter_id is kept only as a deprecated, display-only field for backward compatibility — see Execution Profiles for the full resolution order and the migration story for agents registered before Initiative 3.
Target architecture
text
Business Application
|
Agent Registry <- governs whether the agent may run
|
Execution Profile <- resolves HOW execution happens (model, params, timeouts) (Initiative 3)
|
Provider Connection <- resolves WHOSE tenant-owned credentials are used (Initiative 2)
|
Adapter Registry <- resolves WHICH protocol/implementation handles it
|
Agent Provider Adapter <- generic contract, TRANSIENT credentialed instance
|
External Model Provider (the tenant's own account)
|
Standardized execution result (text + citations + safe metadata)
|
AgentExecutionMapper <- bridges into AgentOutput, still no provider SDK types
|
Runtime Control Engine <- UNCHANGED evidence/policy/risk/Decision Controller
|
Runtime Session -> Agent Run -> Decision Context Record -> Decision ReplaySee Execution Profiles for the full resolution order (19 ordered checks) and Provider Connections for the credential-resolution architecture (CredentialStore) — including why the Adapter Registry's own boot-time instance is never used to execute a customer's request.
Managed execution vs. bring-your-own execution
| Bring Your Own Execution | Managed Adapter Execution | |
|---|---|---|
| Endpoint | POST /runtime/agent-runs | POST /runtime/agents/:agentId/execute |
| Who runs the model | The caller, on its own infrastructure | The platform, via a registered adapter |
| Caller supplies | A finished, structured AgentOutput | Raw subject context/instructions; the platform produces the output |
execution_origin on the resulting AgentRun | "external" | "managed" |
| Whose provider credentials are used | N/A — CARC never sees them | Yours — a tenant-owned Provider Connection, never CARC's |
| When to use | You already run your own agent/model/framework | You want the platform to call a supported provider on your behalf, using your own account |
Both land in the exact same evidence/policy/risk/Decision Controller pipeline and both are visible through the same Runtime Session, Agent Run, Decision Context Record, and Decision Replay APIs.
The generic adapter contract
Every provider adapter (OpenAI, Azure OpenAI, Google Gemini, Anthropic, a self-hosted model, a local model, a custom AI endpoint) implements the same AgentProviderAdapter interface (@giggle-ai/agent-adapter-core):
ts
interface AgentProviderAdapter {
readonly adapterId: string;
readonly provider: string;
readonly version: string;
getCapabilities(): AgentAdapterCapabilities;
validateConfiguration(): Promise<AdapterValidationResult>;
execute(request: AgentExecutionRequest): Promise<AgentExecutionResult>;
}execute() never runs runtime policy, evidence, risk, or approval logic — it only calls the provider and returns a generic { output, citations, modelProvider, modelVersion, adapterId, executionMetadata } envelope. The engine's AgentExecutionMapper bridges that into a full AgentOutput before the unchanged evidence/policy/risk pipeline runs.
Adapter lifecycle
text
registered ("unavailable")
|
validateAdapter()
|
+-- available <- configuration valid, ready for managed execution
+-- misconfigured <- required configuration (e.g. an API key) missing/invalid
+-- unavailable <- configuration valid but not currently usable
+-- deprecated <- historical only, never selected for new executionsAdapters are registered only by the engine's own composition root at boot — there is no HTTP endpoint to create or edit adapter configuration.
Configuration and security considerations
- Provider secrets (API keys, base URLs) live only in the adapter package's own config module and the process environment — never in a
RegisteredAgent, never in aRegisteredAdapter's wire representation, never logged. GET /runtime/adapters*responses only ever return the secret-freeRegisteredAdapterSummaryshape.- An unconfigured or unreachable provider never affects engine health/readiness — see
GET /ready'sdegradedfield. - No provider prompt or response text is ever logged — only safe metadata (token counts, latency, provider request id, finish reason).
APIs
text
GET /runtime/adapters
GET /runtime/adapters/:id
POST /runtime/adapters/:id/validate
GET /runtime/adapters/:id/health
POST /runtime/agents/:agentId/executeSee SDK Guide and REST API Guide for usage, and OpenAI Adapter for the first concrete provider implementation.