Define the stable contract
Keep auth, project context, model identifiers, request IDs, timeout and cancellation behavior, common errors, usage fields, and metadata consistent. For text, an OpenAI-compatible surface reduces client work and supports existing SDKs.
Version incompatible changes and document provider-specific escape hatches. Silent semantic drift is worse than an explicit extension.
Make capabilities discoverable
A catalog should expose modality, context limits, tool and structured-output support, job lifecycle, input types, pricing units, and current availability. The application or router can then reject impossible requests before paying provider latency.
Treat capability support as tested behavior, not a marketing label.
Separate synchronous and asynchronous work
Streaming text and long-running video have different durability needs. Use a common job envelope for asynchronous work: create, status, cancel, result, signed webhook, usage, and error. Preserve direct streaming where it improves the experience.
Idempotency and stable job IDs matter because networks fail while expensive work continues.
Keep routing and observation below the contract
Applications should express required capability and preferred model; infrastructure can apply health, cost, and fallback policy. Every decision should be traceable, and usage should be recorded once, in a form that can be compared with each provider's own invoice.
This boundary lets model policy evolve faster than application releases.
