AI Contracts¶
Namespace¶
ASTX.AI.run(request)
ASTX.AI.text(request)
ASTX.AI.structured(request)
ASTX.AI.tools(request)
ASTX.AI.image(request)
ASTX.AI.stream(request)
ASTX.AI.providers()
ASTX.AI.capabilities(provider)
ASTX.AI.configure(config, options)
ASTX.AI.getConfig()
ASTX.AI.clearConfig()
ASTX.AI.OutputRepair.continueIfTruncated(request)
configure is useful in consumer projects when you want to load script properties once and avoid passing auth on every call.
Auth/model resolution order:
- per-call
request.auth.*/request.model - runtime config loaded via
ASTX.AI.configure(...) - script properties
- throw
AstAiAuthErrorif still missing
Common request contract¶
{
provider: 'openai' | 'gemini' | 'vertex_gemini' | 'openrouter' | 'perplexity',
operation: 'text' | 'structured' | 'tools' | 'image',
model: 'optional-model-override',
input: 'prompt' | [{ role, content }],
system: 'optional system instruction',
options: {
temperature: 0.2,
maxOutputTokens: 1024,
timeoutMs: 45000,
retries: 2,
includeRaw: false,
maxToolRounds: 3,
reliability: {
maxSchemaRetries: 2,
repairMode: 'none' | 'json_repair' | 'llm_repair',
strictValidation: true
}
},
auth: { ...provider overrides... },
providerOptions: { ...provider-native extras... },
routing: {
strategy: 'priority' | 'fastest' | 'cost_first',
maxProviderAttempts: 2,
perAttemptTimeoutMs: 20000,
retryOn: {
transientHttp: true,
providerErrors: false,
authErrors: true,
capabilityErrors: true,
responseParseErrors: true
},
candidates: [{
provider: 'openai',
model: 'gpt-4.1-mini',
auth: { apiKey: '...' },
providerOptions: { ... },
options: { retries: 1 },
priority: 0,
latencyMs: 2500,
unitCost: 3
}]
}
}
options.timeoutMs is accepted for cross-runtime parity, but Apps Script UrlFetchApp.fetch does not provide hard request-timeout control. Use options.retries plus provider-side timeout settings where supported.
Routing notes:
- top-level
provideris optional whenrouting.candidatesis provided. - default
routing.strategyispriority(candidate order/priority). - deterministic
4xxprovider errors do not fail over unlessrouting.retryOn.providerErrors=true. - transient
429/5xxprovider errors fail over by default. - stream mode supports a single routing candidate only.
Structured request additions¶
ASTX.AI.structured(...) returns parsed JSON at response.output.json.
Structured reliability notes:
- default reliability policy:
maxSchemaRetries=2,repairMode='json_repair',strictValidation=true. - retries are bounded and deterministic (
1 + maxSchemaRetriestotal attempts). json_repairperforms local JSON cleanup (code fences, trailing commas, substring extraction).llm_repairmay issue one additional provider call per attempt to repair malformed output.- final failures throw
AstAiResponseParseErrorwith diagnostics inerror.details: retryCountattempts[](failure kind, schema diagnostics, truncated payload)originalPayload(truncated)
Tool request additions¶
{
provider,
input,
tools: [{
name,
description,
inputSchema,
handler, // function(args) or global function name string
guardrails: {
timeoutMs: 5000,
maxArgsBytes: 50000,
maxResultBytes: 200000,
retries: 0,
idempotencyKeyFromArgs: false,
idempotencyKey: 'optional-fixed-key' // scoped per tool name
}
}],
toolChoice: 'auto' | 'none' | { name: 'tool_name' },
options: {
maxToolRounds: 3
}
}
Normalized response contract¶
{
provider,
operation,
model,
id,
createdAt,
finishReason,
output: {
text,
json,
images,
toolCalls,
toolResults // includes idempotentReplay=true when replayed from idempotency guardrail
},
usage: {
inputTokens,
outputTokens,
totalTokens
},
route: {
strategy,
maxProviderAttempts,
selectedProvider,
selectedModel,
attempts: [{
attempt,
candidateId,
provider,
model,
status: 'ok' | 'error',
durationMs,
error: { name, message, statusCode, retryable } // error attempts only
}]
},
raw // present when options.includeRaw=true
}
Error contracts¶
Typed errors thrown by AI surface:
AstAiErrorAstAiValidationErrorAstAiAuthErrorAstAiCapabilityErrorAstAiProviderErrorAstAiToolExecutionErrorAstAiToolTimeoutErrorAstAiToolPayloadLimitErrorAstAiToolIdempotencyErrorAstAiToolLoopErrorAstAiResponseParseError
Recommended usage:
try {
const out = ASTX.AI.text({ provider: 'openai', input: 'hello' });
Logger.log(out.output.text);
} catch (error) {
Logger.log(`${error.name}: ${error.message}`);
}
Output continuation repair¶
ASTX.AI.OutputRepair.continueIfTruncated(...) is a bounded helper for incomplete model output:
const repaired = ASTX.AI.OutputRepair.continueIfTruncated({
provider: 'vertex_gemini',
model: 'gemini-2.5-flash',
partial: partialAnswerText,
finishReason: aiResponse.finishReason,
question: 'Summarize risks and actions',
citations: response.citations,
auth: {},
passes: 2,
maxOutputTokens: 512
});
Logger.log(repaired.text);
Behavior notes:
- no-op when output does not appear truncated (unless
force=true) - bounded continuation passes (
1..5) - overlap-aware merge to avoid duplicate text prefixes