docs(built-in-agent): document aimlapi.com as an OpenAI-compatible provider - #1
Open
Lookoff-AIMLAPI wants to merge 5 commits into
Open
docs(built-in-agent): document aimlapi.com as an OpenAI-compatible provider#1Lookoff-AIMLAPI wants to merge 5 commits into
Lookoff-AIMLAPI wants to merge 5 commits into
Conversation
…ers list aimlapi.com exposes an OpenAI-compatible route at https://api.aimlapi.com/v1, so it already works through the createOpenAI({ baseURL }) pattern this page documents for OpenRouter, Ollama, Together, Groq and Novita. Nothing in the runtime has to change for it; readers just have no way to discover that today. The callout exists because the failure it prevents is silent-looking and model-dependent, which is worse than Novita's uniform one: the gateway does serve Responses, but only for the openai/ ids it routes. The bare provider("model") call form in the adjacent OpenRouter example therefore works for openai/gpt-4o-mini and openai/gpt-4.1 and returns 404 Model not found for google/, deepseek/ and the Anthropic ids — so a reader who copies the example and swaps in a non-OpenAI model gets an error that looks like a bad model id rather than a wrong call form. Verified by driving BuiltInAgent against the endpoint on both call forms: chat form succeeded on openai/gpt-4o-mini, openai/gpt-4.1, google/gemini-2.5-flash and deepseek/deepseek-v4-flash; the bare form succeeded on the two openai/ ids and returned 404 on the other two.
CopilotKit does open the connection to api.aimlapi.com itself, so unlike a catalog or a pure docs entry there is a real request path that could carry partner attribution. No partner id has been registered for CopilotKit yet, so the constant is empty on purpose rather than filled with a plausible-looking value: the gateway accepts a request carrying a malformed id and drops the attribution silently, so a bad value would never fail visibly at runtime and the traffic would simply earn nothing. The test is what makes that failure mode visible, so it asserts empty-or-well-formed instead of non-empty and pins the shapes a hand-written id gets wrong. Nothing imports the constant and nothing should until an id exists. Actually sending the headers means scoping them to our origin, which in this codebase means a hardcoded aimlapi base URL inside resolveModel — the change upstream declined in CopilotKit#6584. Drop this commit before any upstream PR; it is scaffolding for a colleague, not a contribution.
The OpenAI-compatible provider list on this page is hand-ordered prose, not a generated or alphabetical list, so position is a choice someone makes rather than something the tooling decides. This moves aimlapi.com from the end of that list, where the preceding commit appended it the way Novita was added, to the front. That is a partnership-placement decision, not a documentation improvement, and the page reads exactly as well either way — so it is isolated here for a colleague to drop before any upstream PR. The docs page has no "Recommended"/featured badge mechanism, so none was invented; ordering is the only lever the page offers.
The placeholder part_copilotkit was a readable stand-in chosen before the partner was registered. Registration mints the id server-side, so the real value is part_B5Xmawp87YODJfuBUtiCbR2m. A wrong or unknown partner id is accepted with a 200 and silently not attributed, so this would not have surfaced at runtime.
The placeholder export const AIMLAPI_PARTNER_ID = ""; was a readable stand-in chosen before the partner was registered. Registration mints the id server-side, so the real value is export const AIMLAPI_PARTNER_ID = "part_B5Xmawp87YODJfuBUtiCbR2m";. A wrong or unknown partner id is accepted with a 200 and silently not attributed, so this would not have surfaced at runtime.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds aimlapi.com to the OpenAI-compatible providers list on the Built-in Agent
Model Selection
page, plus a
<Callout>describing the one call-form caveat that applies to it.This is a documentation change on purpose — a
resolveModelprovider case is not on the table.Upstream PR CopilotKit#6584 ("add OrcaRouter as a built-in model provider") was closed unmerged on 2026-08-31
with the reason stated plainly:
aimlapi.com is the same shape of thing, so this follows the route the maintainer named, and copies
the shape of the two Novita commits (
55be3506a,9907d2d72) exactly: one line in the prose list,one warn Callout.
The caveat, and why it is not a copy of Novita's
Novita's caveat is uniform — it has no Responses endpoint at all. aimlapi.com's is
per model, which is a nastier failure for a reader:
openai/gpt-4o-miniopenai/gpt-4.1google/gemini-2.5-flashdeepseek/deepseek-v4-flashprovider.chat(model)(Chat Completions)provider(model)(Responses, as in the OpenRouter example above it)The gateway's catalog has 353 models on
openai/chat-completionsand 60 onopenai/responses/submit, and the Responses 60 are theopenai/family plus one x-ai id. So a readerwho copies the adjacent OpenRouter example verbatim and swaps in a non-OpenAI model gets
404 Model not found, which reads like a bad model id rather than a wrong call form. Hence theCallout.
Commits
docs(built-in-agent): mention aimlapi.com in OpenAI-compatible providers listchore(aimlapi): fork-only partner-id placeholder — do not send upstreamAIMLAPI_PARTNER_IDconstant + a test asserting empty-or-^part_[A-Za-z0-9]{1,64}$chore(aimlapi): fork-only placement — do not send upstreamThe last two commits are separated so they can be dropped before any upstream PR.
On attribution headers
CopilotKit does call
api.aimlapi.comdirectly — the AI SDK OpenAI provider insideBuiltInAgentopens the connection itself; only the base URL and key come from user configuration. So unlike a
catalog or a purely docs-level integration, a request path that could carry the four attribution
headers exists here.
The headers are not shipped, for two reasons. No partner id has been registered for CopilotKit,
and an invented one is worse than none — the gateway accepts a request carrying a malformed id and
drops the attribution silently, so a wrong value never fails visibly and the traffic simply earns
nothing. And scoping headers to our origin (the rule that stops them riding a request to another
provider) requires knowing the aimlapi base URL inside
resolveModel, which is exactly the changeupstream declined. The placeholder commit therefore leaves the constant empty with a test that pins
the id shape, so a bogus value cannot be pasted in unnoticed later.
Verification
Baseline was recorded on a pristine checkout of
mainbefore any change.nx run @copilotkit/runtime:testshowcase/shell-docsnpm run testtsx scripts/validate-doc-model-names.tsshowcase/shell-docsnpm run typecheckshowcase/shell-docsnpm run buildnx run @copilotkit/runtime:check-typesoxlint/oxfmt --checkon the new filesThe 6 pre-existing shell-docs failures are unrelated to this change and identical before and after
(
public-assets.test.ts×3 — PNG fixtures;angular-docs-content.test.ts×2;llm-text.test.ts×1).Live inference — through the documented configuration path, not curl
Every claim in the Callout was produced by driving CopilotKit's own
BuiltInAgentagainsthttps://api.aimlapi.com/v1with a real key, using only documented configuration. No mocks.createOpenAI({ baseURL }).chat("openai/gpt-4o-mini")→BuiltInAgent:The bare form (
createOpenAI({ baseURL })("openai/gpt-4o-mini"), i.e. Responses) returned the sametext with
provider "openai.responses", 169/10/179 tokens. The string model form withOPENAI_BASE_URL=https://api.aimlapi.com/v1andmodel: "openai/openai/gpt-4o-mini"— which goesthrough the existing
openaicase inresolveModelunmodified — returned the same again. So allthree configuration paths this repo already offers reach the gateway with no code change.
Tool calling was exercised once over the same path (
maxSteps: 3, onedefineTool):Each of the four model ids named in the Callout was called live through
BuiltInAgenton both callforms; the table above is that result, not a catalog reading.
What was not verified
gateway's catalog reports it (60 vs 353) plus those four live checks — no exhaustive sweep.
suite, not visually in a browser.
Related PRs and Issues
CopilotKit/CopilotKit#6584(closed unmerged) — the policy this PR is shaped around.CopilotKit/CopilotKit#6502— how Novita was added; this change copies its shape.Checklist