OpenAF AI GPT Types Reference Guide
This document provides a comprehensive reference guide for implementing LLM service API wrappers in OpenAF’s ow.ai library. The OpenWrap.ai.prototype.__gpttypes object contains standardized wrappers for various LLM services, providing a unified interface for chat, tooling, image processing, model listing, and image generation capabilities.
See also: openaf-advanced.md (AI Helpers section) for higher-level usage patterns and integration tips.
Overview
The GPT types system provides a consistent API across different LLM providers through standardized wrapper implementations. Each wrapper normalizes provider-specific APIs into a common interface, handling authentication, conversation management, tool calling, and various prompt types.
Capability Matrix
| Provider | Chat | Tooling | Image | Model List | Image Gen |
|---|---|---|---|---|---|
| openai | ✔ | ✔ | ✔ | ✔ | ✔ |
| gemini | ✔ | ✔ | ✔ | ✔ | ✖ |
| ollama | ✔ | ✔ | ✔ | ✔ | ✖ |
| anthropic | ✔ | ✔ | ✖ | ✔ | ✖ |
OpenAI-Compatible Transport Modes
The openai provider can target OpenAI, Azure OpenAI, and Azure AI Foundry model inference endpoints through aOptions.mode.
| Mode | Auth Default | Chat URL Shape |
|---|---|---|
openai | Authorization: Bearer <key> | {url}/{apiVersion}/chat/completions |
azure-openai-v1 | api-key: <key> | {url}/openai/{apiVersion}/chat/completions |
azure-openai-legacy | api-key: <key> | {url}/openai/deployments/{deployment}/chat/completions?api-version={apiVersion} |
foundry with apiVersion: "v1" | api-key: <key> | {url}/openai/v1/chat/completions |
foundry with a dated apiVersion | api-key: <key> | {url}/chat/completions?api-version={apiVersion} when url ends with /models; otherwise {url}/models/chat/completions?api-version={apiVersion} |
Native decision calls additionally accept decisionApi: "openai" (default), "openrouter", or "microsoft", and an optional absolute HTTP(S) decisionUrl. Microsoft requires Foundry mode, API version v1, and an explicit deployment name in model. It calls {resource-root}/providers/microsoft/v1/systemone using the existing authentication and timeout settings; bearer tokens are supported through authType: "bearer". See Microsoft native decisions for examples, URL rules, and supported inputs.
Aliases are also accepted: azure-v1, azure-legacy, and azure-foundry.
Common options:
url: Base service URL. OpenAI examples commonly usehttps://api.openai.comorhttps://api.openai.com/v1.apiVersion: Defaults tov1. Azure legacy mode emits this as theapi-versionquery parameter. Foundry mode uses/openai/v1whenapiVersionisv1; dated versions are emitted as theapi-versionquery parameter on the/modelsroute.deployment: Azure OpenAI legacy deployment name. If omitted, the selectedmodelis used.authType: Overrides generated auth header style. Supported values arebearer,api-key, andnone.headers: Extra headers. Values here override generated headers with the same names.
Examples:
// OpenAI
var openai = new ow.ai.gpt("openai", {
key : "sk-...",
url : "https://api.openai.com/v1",
model: "gpt-4o-mini"
});
// Azure OpenAI v1 compatible endpoint
var azureV1 = new ow.ai.gpt("openai", {
key : "your-azure-api-key",
url : "https://RESOURCE.openai.azure.com",
mode : "azure-openai-v1",
model: "your-deployment-name"
});
// Azure OpenAI legacy deployment endpoint
var azureLegacy = new ow.ai.gpt("openai", {
key : "your-azure-api-key",
url : "https://RESOURCE.openai.azure.com",
mode : "azure-openai-legacy",
deployment: "your-deployment-name",
apiVersion: "2024-10-21"
});
// Azure AI Foundry v1 endpoint
var foundry = new ow.ai.gpt("openai", {
key : "your-foundry-api-key",
url : "https://RESOURCE.services.ai.azure.com",
mode : "foundry",
model : "your-deployment-name"
});
// Azure AI Foundry dated model inference endpoint
var foundryPreview = new ow.ai.gpt("openai", {
key : "your-foundry-api-key",
url : "https://RESOURCE.services.ai.azure.com/models",
mode : "foundry",
apiVersion: "2024-05-01-preview",
model : "your-deployment-name"
});
Architecture
Each GPT type implementation follows this structure:
OpenWrap.ai.prototype.__gpttypes = {
[providerName]: {
create: (aOptions) => {
// Return wrapper object with standardized interface
}
}
}
Wrapper Interface Specification
Every wrapper must implement the following standardized interface:
Core Properties
conversation: Array - Stores the conversation historytools: Object/Array - Stores available tools/functions
Required Methods
Configuration Methods
getConversation() : Array
Returns the current conversation history in a standardized format.
setConversation(aConversation) : Object
Sets the conversation history. Must handle format normalization between provider formats and the standard format.
setTool(aName, aDesc, aParams, aFn) : Object
Registers a tool/function for use in conversations.
aName: String - Tool nameaDesc: String - Tool descriptionaParams: Object - JSON schema for parametersaFn: Function - Function to execute when tool is called
Core Prompt Methods
prompt(aPrompt, aModel, aTemperature, aJsonFlag, tools) : String
Main prompting method that returns processed response text.
aPrompt: String/Array - The prompt(s) to sendaModel: String - Model to use (optional, defaults to configured model)aTemperature: Number - Temperature setting (optional)aJsonFlag: Boolean - Whether to request JSON responsetools: Array - Tools to make available for this prompt
rawPrompt(aPrompt, aModel, aTemperature, aJsonFlag, aTools) : Object
Returns the raw API response without processing.
promptImage(aPrompt, aImage, aDetailLevel, aRole, aModel, aTemperature, aJsonFlag) : String
Prompts with image input (if supported by provider).
aImage: String - File path or base64 encoded imageaDetailLevel: String - Image analysis detail level
Conversation Management
addPrompt(aRole, aPrompt) : Object
Adds a message to the conversation.
addUserPrompt(aPrompt) : Object
Adds a user message to the conversation.
addSystemPrompt(aPrompt) : Object
Adds a system message to the conversation.
addDeveloperPrompt(aPrompt) : Object
Adds a developer message to the conversation (provider-specific).
cleanPrompt() : Object
Clears the conversation history.
Image Generation (Optional)
rawImgGen(aPrompt, aModel) : Object
Generates images, returns raw API response.
promptImgGen(aPrompt, aModel) : Array
Generates images, returns array of image data.
Model Information
getModels() : Array
Returns list of available models from the provider.
HTTP Communication
_request(aURI, aData, aVerb) : Object
Internal method for making HTTP requests to the provider API.
Implementation Guidelines
1. Options Validation
Always validate and set defaults for configuration options:
create: (aOptions) => {
ow.loadObj()
aOptions = _$(aOptions, "aOptions").isMap().$_()
aOptions.params = _$(aOptions.params, "aOptions.params").isMap().default({})
aOptions.key = _$(aOptions.key, "aOptions.key").isString().$_()
aOptions.timeout = _$(aOptions.timeout, "aOptions.timeout").isNumber().default(15 * 60000)
aOptions.model = _$(aOptions.model, "aOptions.model").isString().default("default-model")
aOptions.temperature = _$(aOptions.temperature, "aOptions.temperature").isNumber().default(0.7)
aOptions.url = _$(aOptions.url, "aOptions.url").isString().default("https://api.provider.com")
aOptions.headers = _$(aOptions.headers, "aOptions.headers").isMap().default({})
aOptions.mode = _$(aOptions.mode, "aOptions.mode").isString().default("openai")
aOptions.authType = _$(aOptions.authType, "aOptions.authType").isString().default("bearer")
// Provider-specific options...
}
2. Conversation Format Normalization
Handle conversion between the standard conversation format and provider-specific formats:
Standard Format:
[
{ role: "system", content: "System message" },
{ role: "user", content: "User message" },
{ role: "assistant", content: "Assistant response" }
]
Provider-specific Format Handling:
- Convert role names (e.g., “assistant” ↔ “model”)
- Handle content structure differences
- Manage system message placement variations
3. Tool/Function Calling
Implement tool calling support where available:
setTool: (aName, aDesc, aParams, aFn) => {
_r.tools[aName] = {
type: "function",
function: {
name: aName,
description: aDesc,
parameters: aParams
},
fn: aFn
}
return _r
}
Handle tool execution in rawPrompt:
- Detect tool calls in responses
- Execute registered functions
- Continue conversation with tool results
Gemini 2.5/3 notes
- Tool calls arrive as
functionCallparts; send tool results back asfunctionResponseparts on a follow-upusermessage. functionCall.argsmay be an object or a JSON string depending on the model/version.- When requesting JSON output, prefer
generationConfig.responseMimeType = "application/json"and only setresponseSchemawhen it has non-emptyproperties.
4. Authentication Patterns
Bearer/API-Key Headers (OpenAI-Compatible, Anthropic)
// Bearer token style
requestHeaders: merge({
Authorization: "Bearer " + Packages.openaf.AFCmdBase.afc.dIP(_key),
Accept: "*/*"
}, aOptions.headers)
// Azure OpenAI and Azure AI Foundry API-key style
requestHeaders: merge({
"api-key": Packages.openaf.AFCmdBase.afc.dIP(_key),
Accept: "*/*"
}, aOptions.headers)
API Key in URL Parameter (Gemini)
case "GET" : return _fnh($rest(__m).get2Stream(aOptions.url + "/" + aURI + "?key=" + Packages.openaf.AFCmdBase.afc.dIP(_key)))
case "POST": return _fnh($rest(__m).post2Stream(aOptions.url + "/" + aURI + "?key=" + Packages.openaf.AFCmdBase.afc.dIP(_key), aData))
No Authentication (Ollama)
requestHeaders: {
Accept: "*/*"
}
5. Error Handling
Implement robust error handling in _request method:
var _fnh = r => {
var _r
if ("function" !== typeof r.getClass) {
_r = (isDef(r.error) ? jsonParse(r.error, __, __, true) : r)
} else {
_r = jsonParse(af.fromBytes2String(r.readAllBytes()))
}
if (typeof _r.response !== "undefined") {
return jsonParse(_r.response)
} else {
return _r
}
}
6. Image Handling
For providers supporting image input:
promptImage: (aPrompt, aImage, aDetailLevel, aRole, aModel, aTemperature, aJsonFlag) => {
aRole = _$(aRole, "aRole").isString().default("user")
aDetailLevel = _$(aDetailLevel, "aDetailLevel").isString().default("low")
var base64 = ""
if (io.fileExists(aImage)) {
base64 = af.fromBytes2String(af.toBase64Bytes(io.readFileBytes(aImage)))
} else {
if (isString(aImage)) {
base64 = aImage
}
}
// Provider-specific image format handling
}
7. JSON Response Handling
Implement JSON-specific prompting:
if (aJsonFlag) {
// Provider-specific JSON response configuration
// Examples:
// OpenAI: response_format: { type: "json_object" }
// Ollama: format: "json"
// Anthropic: Add "output json" to messages
}
Provider-Specific Implementation Notes
OpenAI
- Uses
Bearertoken authentication - Supports comprehensive tool calling
- Has dedicated image generation endpoints
- Supports structured JSON responses via
response_format
Gemini
- Uses API key in URL parameters
- Has unique conversation format with
partsarrays - System instructions handled separately
- Tool calling uses
functionDeclarationsformat
Ollama
- No authentication required (local/self-hosted)
- OpenAI-compatible message format
- Uses
/api/chatand/api/tagsendpoints - JSON format specified in request body
Anthropic
- Uses
x-api-keyheader withanthropic-version - System messages handled via dedicated
systemfield - Limited tool calling support
- No native image generation
Testing Your Implementation
- Basic Chat: Test simple prompt/response
- Conversation: Verify conversation history maintenance
- System Messages: Test system prompt handling
- JSON Mode: Verify JSON response parsing
- Image Input: Test image processing (if supported)
- Tool Calling: Test function execution (if supported)
- Model Listing: Verify model enumeration
- Error Handling: Test with invalid inputs
Error Patterns to Avoid
- Authentication Leakage: Always use
Packages.openaf.AFCmdBase.afc.dIP()for sensitive data - Format Inconsistency: Ensure conversation format normalization
- Missing Defaults: Always provide sensible defaults for optional parameters
- Resource Leaks: Properly close HTTP connections with
_h.close() - Tool Security: Validate tool parameters before execution
Example Minimal Implementation
newprovider: {
create: (aOptions) => {
ow.loadObj()
aOptions = _$(aOptions, "aOptions").isMap().$_()
aOptions.key = _$(aOptions.key, "aOptions.key").isString().$_()
aOptions.url = _$(aOptions.url, "aOptions.url").isString().$_()
aOptions.model = _$(aOptions.model, "aOptions.model").isString().default("default-model")
aOptions.timeout = _$(aOptions.timeout, "aOptions.timeout").isNumber().default(15 * 60000)
var _r = {
conversation: [],
tools: {},
getConversation: () => _r.conversation,
setConversation: (aConversation) => {
if (isArray(aConversation)) _r.conversation = aConversation
return _r
},
prompt: (aPrompt, aModel, aTemperature, aJsonFlag, tools) => {
var result = _r.rawPrompt(aPrompt, aModel, aTemperature, aJsonFlag, tools)
// Extract text from provider-specific response format
return result.message.content
},
rawPrompt: (aPrompt, aModel, aTemperature, aJsonFlag, aTools) => {
// Implementation specific to provider API
var body = {
model: aModel || aOptions.model,
messages: _r.conversation.concat([{role: "user", content: aPrompt}])
}
return _r._request("chat/completions", body)
},
_request: (aURI, aData, aVerb) => {
// HTTP request implementation
},
// ... other required methods
}
return _r
}
}
This guide should provide sufficient information for implementing new LLM service wrappers that integrate seamlessly with the OpenAF AI ecosystem.
Optional decision and structured-output hooks
The additive version 1 decision API is described in Stateless LLM decisions, with verified contract records. Existing third-party adapters do not need these hooks for chat or other established operations.
| Hook on the created provider adapter | Contract |
|---|---|
getCapabilities(model) | Returns a fresh capability map for that model; no HTTP by default |
resetDecisionStats() | Clears built-in legacy last-call statistics before preflight validation |
rawDecide(request) | Native isolated execution; returns { raw, stats } from one request |
normalizeDecisionResponse(raw, request) | Parses native semantics into the canonical named answer map |
rawStructuredPrompt(request) | Isolated schema-constrained execution; returns { raw, stats } |
normalizeStructuredResponse(raw, request) | Parses finalized provider text, rejects blocked/truncated/refused output, validates it, and returns canonical answers |
structuredSchemaPrompt(prompt, descriptor, model, temperature, tools) | Optional conversational schema helper; returns { response, stats } and allows provider-specific parsing without an OpenAI envelope |
The validated decision request contains copied state, copied questions, model, selected strategy, requireProbabilities, allowlisted providerOptions, compiled schema, and trusted instructions. Provider adapters retain HTTP/authentication/timeout and response-envelope responsibilities. The shared layer owns input validation, strategy eligibility, schema compilation, normalized result validation, and facade forwarding. Decisions never call chat’s conversation/tool loop or mutable cleanPrompt path.
Capabilities contain contractVersion: 1, inputTypes: ["text", "json"], streaming: false, and native/structured objects. Each strategy object contains implemented, contract, questionTypes, probabilities, and availability. Verified documentation and implementation support do not establish model, endpoint, tenant, or account availability. Use unknown availability when no authoritative evidence is present. Do not infer native support from the generic openai provider type or from a compatible chat gateway.
| Adapter | Native | Structured | Probability information |
|---|---|---|---|
| Ollama | System One; implemented, contract verified | Unsupported | Provider distributions/P(true), separate expectation/confidence |
| Gemini | Unsupported | GenerateContent; implemented | Null probability/expectation fields |
| OpenAI | Contract unverified; no outbound native request | Responses or explicit Chat; implemented | Null probability/expectation fields |
| Legacy third-party adapters | Unsupported absent hooks | Unsupported absent hooks | Existing methods remain available |
rawDecide() returns { contractVersion, provider, model, strategy, raw }; it does not require a second inference. decideWithStats() receives statistics from the execution result rather than rereading mutable shared state. Last-call statistics remain compatible but are not a concurrency-safe result channel. A failed native request never triggers structured generation, and an OpenAI structured request never uses the legacy chat fallback cache.
Gemini’s explicit schema helper defaults to structuredOutputProfile: "response-format", using generationConfig.responseFormat.text.{mimeType,schema} with APPLICATION_JSON. Explicit legacy-schema uses the older responseMimeType/responseSchema representation. The new helper rejects inherited schema/MIME conflicts; legacy chat pass-through behavior remains intact. Only the declared supported schema subset is translated, and output validation does not depend on global Ajv coercion/default settings.