Connect Agno agents to Router One with OpenAILike
Agno runs agents, tools and teams in your application. OpenAILike connects their Chat Completions requests to Router One, while Agno keeps responsibility for the agent loop, state and tool execution. This guide covers Agno 3.1.1 and its OpenAILike Chat Completions adapter, re-checked on 2026-10-09 against the Agno 3.1.2 source (October 8, 2026), whose OpenAILike defaults and openai:<model-id> shorthand are unchanged.
Install the client and set two explicit variables
Use a Python environment with agno and openai installed. Create a Router One key for this agent and set its maxSpend in the dashboard. ROUTER_ONE_MODEL must be a current chat-model ID copied from /models, including any vendor prefix. Run the script below once without tools before adding your application logic.
python -m pip install "agno==3.1.1" openai export ROUTER_ONE_API_KEY="sk-your-router-one-key" export ROUTER_ONE_MODEL="<exact-model-id-from-/models>" python agent.py
Configure Agno to use the Router One base URL
Import OpenAILike from agno.models.openai.like and pass a model instance to Agent. Set base_url to https://api.router.one/v1, api_key explicitly, and id to the exact catalog ID. OpenAILike sends id unchanged: anthropic/claude-sonnet-5 does not need an extra openai/ or custom/ prefix. The first run below disables SDK, model and guidance retries to make request counting easier. After it works, enable streaming with agent.print_response("Say hello in one sentence.", stream=True); this adapter requests stream_options.include_usage automatically.
from os import environ
from agno.agent import Agent
from agno.models.openai.like import OpenAILike
agent = Agent(
model=OpenAILike(
id=environ["ROUTER_ONE_MODEL"],
api_key=environ["ROUTER_ONE_API_KEY"],
base_url="https://api.router.one/v1",
max_retries=0,
retries=0,
retry_with_guidance=False,
),
)
agent.print_response("Say hello in one sentence.")The model class chooses the protocol
Agno 3.1.1 resolves the string shorthand openai:<model-id> to OpenAIResponses, not OpenAILike. The prefix selects an adapter; it is separate from a Router One model ID such as openai/gpt-5.5. Use the explicit OpenAILike instance for this Chat Completions guide. If you deliberately switch to OpenAIResponses or OpenResponses, confirm that the selected model and required features support /v1/responses first. Changing the class can change the endpoint without changing the model ID.
Count model calls separately from an agent run
One agent run can call the model again after each tool result. tool_call_limit limits tool execution, not token spend or every model request. Retries also have separate scopes: max_retries belongs to the OpenAI client, model.retries repeats model requests, and Agent.retries can repeat the whole run. Configure them deliberately before adding side-effecting tools. Use a dedicated capped key and reconcile model, time, tokens and request_id with Dashboard → Logs; Agno metrics are usage reports, not Router One settlement amounts. A missing log alone does not prove that no request reached the gateway: records awaiting pricing can be temporarily absent.
Configure knowledge embeddings independently
Changing Agent.model does not reconfigure a knowledge database or its embedder. For example, Agno’s official PgVector recipe uses OpenAIEmbedder separately from the agent model. Keep embeddings on a local model or a provider that serves that endpoint; Router One does not expose /v1/embeddings. Documents, retrieval, session storage and tool execution stay in your Agno application. Configure any separate reasoning, parser or output model explicitly too; they are additional model clients.
Which model ID should Agno send?
Copy the exact model ID from /models, preserving case, hyphens, and version suffixes; do not substitute a display name. Open its detail page and match the supported API endpoints, context window, and capabilities such as tool calling to the provider and features selected in Agno. A catalog listing does not mean the client can use every feature of that model. Give each client or application a dedicated API key with a maxSpend cap.
Which API protocol is Agno using?
OpenAI-compatible describes an interface format; it does not make Chat Completions (/v1/chat/completions), Responses (/v1/responses), and Anthropic Messages (/v1/messages) interchangeable. Check the installed client version, provider configuration, and actual request path against the model detail page and API compatibility fact sheet. A successful plain-text chat does not establish support for hosted tools, conversation state, or file-editing features.
Verify the Agno call in your request trace
Send a simple text request from Agno, then match its trace in Dashboard → Logs by time, model, and request_id: tokens, cost, latency, and status. Next, test streaming, tool calls, and multi-turn history separately. For failures, retain the actual request path, full error message, and request_id. If there is no matching log, either the request never reached the gateway (client configuration or connectivity) or the gateway refused it before calling a model — a 401 for the key, a 402 for funds, a 429 from your key's or account's limits, or a 400 or 404 for the model ID or endpoint; a streamed request that failed before any output may have no log either. The status and error message the client received tell which, so check them before attributing the error to the gateway or upstream.
FAQ
Why does OpenAILike return 401 even though OPENAI_API_KEY is set?
In Agno 3.1.1, OpenAILike defaults api_key to the literal string not-provided. That nonempty value prevents OpenAIChat’s fallback to OPENAI_API_KEY, so omitting api_key sends Authorization: Bearer not-provided (per the Agno source, 3.1.1 and 3.1.2, checked 2026-10-09). Pass api_key=environ["ROUTER_ONE_API_KEY"] explicitly. If you already pass the correct key, retain the response body and request ID and check whether the key was revoked or copied incorrectly.
Does OpenAILike automatically remove a vendor prefix from my model ID?
No. Its Chat Completions implementation sends model=self.id. Use the complete catalog ID, including anthropic/ or openai/ when present; IDs such as grok-4.6 have no vendor prefix. Do not copy the extra routing prefixes used by the LiteLLM or Mastra guides. A missing /v1 in base_url is a separate path error, not a model-name problem.
Does OpenAILike guarantee structured output for every model?
No. Its configuration supports structured-output requests, but the endpoint and selected model must support the schema and parameters. Start with a plain text request, then verify output_schema and tool calls separately. An unsupported parameter or schema error calls for checking the actual error and model capability, rather than changing a working base URL.
Which models can Agno use through the gateway?
Choose a current catalog model that supports both the endpoint and the features Agno uses. Check /models and the model detail page for the exact ID, current rates, and capabilities; a family name such as GPT or Claude is not a compatibility guarantee. A client that lists a model has only read the ID, from its own configuration or from GET /v1/models; verify an actual request too.
Models are listed, but requests fail with 400 or 404. What should I check?
Record the actual request path and error message, then check the exact model ID. A 400 can indicate invalid parameters, unsupported tools, or a model/endpoint mismatch; a 404 can indicate an incorrect path or missing resource, so it does not by itself establish that a model was retired. If the error says must be called via, use the named endpoint or select a model supported on the current endpoint. Do not add or remove /v1 or /chat/completions across all clients indiscriminately.
Does this work from Mainland China?
Yes. The gateway is reachable from Mainland China without a VPN, and the configuration is identical to the global setup.
How do I debug a 401/402/403/429?
Start from what your client received: the status, the error body and the X-Request-ID header. A 401 (missing, unknown, revoked or expired key), a 402 (wallet balance, or the key's maxSpend cap) and a 429 from your key's or account's rate limits are refused before any model is called, so they never appear in Dashboard → Logs — nor does a 400 or 404 for a wrong model ID or endpoint. For 401, check that the full key is sent and still active in Dashboard → API Keys; for 402, top up or raise the key's maxSpend; for a 403, keep the full error body. For 429, back off and retry later; a 429 that does show up in Logs came back from upstream after the gateway's retries. Keep the request_id and follow the error-codes reference.