Quincy Labs LogoQuincy Labs
Join ourFollow on

Setting Up OpenClaw, Part 3: Model Routing With OpenRouter and Codex

Once Telegram and Slack were working, the next question was no longer "can the bot answer?"It was: which model is answering, and why?A lot of personal-agent setups quietly collapse that into one...

Substack
8 min read

Setting Up OpenClaw, Part 3: Model Routing With OpenRouter and Codex

Henry
via Substack
View original

Once Telegram and Slack were working, the next question was no longer "can the bot answer?"

It was: which model is answering, and why?

A lot of personal-agent setups quietly collapse that into one permanent choice. You add an API key, pick a model, and from then on the whole system becomes that model. That is fine for a simple chatbot. It is not how I want a long-running local agent gateway to work.

Different jobs want different model behavior.

A short Telegram reply does not need the same model as a multi-file codebase edit. A Slack summary does not need the same economics as a difficult debugging session. A broad research pass does not need the same latency profile as a one-sentence administrative answer.

That is why model routing is a real layer of the system.

In my OpenClaw setup, OpenRouter became the practical default route. OpenAI/Codex became an additional provider path for coding-heavy and higher-stakes turns. The point was not to declare one permanent winner. The point was to keep one agent surface while letting the intelligence underneath change based on the work.

Authentication should not silently change routing

The most important distinction is between provider authentication and default routing.

Authentication means the gateway has credentials for a provider. It can call that provider if the route asks for it.

Default routing means the gateway knows what to use when a message does not explicitly request another model.

Those are not the same decision.

This matters because adding a provider should expand the system. It should not quietly rewrite every Slack and Telegram turn.

In my setup, OpenRouter was already configured. Then I added the OpenAI/Codex auth path with a login flow shaped like this:

# ==================== BASH CODE ====================
openclaw models auth login --provider openai-codex

After login, OpenClaw reported that a Codex-capable model was available as a possible default. But it did not automatically replace the OpenRouter route I was already using.

That was the right behavior.

It meant OpenClaw had a second lane, not a surprise new identity.

The public rule is simple:

# ==================== TEXT CODE ====================
Authentication adds capability.
Default routing chooses behavior.

If those stay separate, the system remains understandable. If they get blurred together, every provider change becomes a mystery: did I add a new option, or did I just change what every channel uses by default?

Why OpenRouter was the everyday route

OpenRouter is useful as a default path because it gives one provider interface over a broad model catalog.

For a chat-reachable agent, that matters. The default route is not just a benchmark decision. It is an operating decision.

A Slack or Telegram bot gets used casually. It gets asked to summarize threads, draft replies, explain a config state, turn a debugging session into notes, and answer small questions that do not justify a heavyweight model every time.

The default should be strong enough that the agent feels useful and cheap enough that you do not hesitate to use it.

That was the role OpenRouter played in my setup. I could point ordinary bot turns at a capable, cost-aware route while keeping other models available for more specialized work.

I would not make the public claim "always use this exact model." Model catalogs change. Pricing changes. Context limits change. What matters is the routing pattern:

# ==================== TEXT CODE ====================
Use a capable default for ordinary agent turns.
Reserve premium or specialized routes for the work that needs them.

That is the durable part.

Why Codex belonged in the same gateway

Codex mattered for a different reason.

Some tasks really are coding tasks, even if they begin as a chat message.

Examples:

• Inspect this repo and explain what changed.

• Fix the failing test without touching unrelated files.

• Compare this branch to main and summarize the risk.

• Debug a CI failure from logs and local state.

• Update a multi-file feature while preserving existing behavior.

Those are not just normal chatbot turns. They involve codebase context, tool use, file edits, tests, and judgment about what not to change.

For that kind of work, I want a stronger coding-oriented route available. But I do not want to rebuild the bot or manually swap the whole provider setup whenever the task changes.

That is why the OpenAI/Codex auth profile belongs beside OpenRouter rather than replacing it.

The gateway should know both lanes exist. Routing should decide which one handles the turn.

A model provider is a lane, not the whole road.

What a normal Slack message should do

Defaults matter most when the prompt does not mention a model.

If I mention the bot in Slack with something ordinary like this:

# ==================== TEXT CODE ====================
@YourBot summarize the last twenty messages in this channel.

I want that to use the configured default route for the agent, channel, or session unless I have created a more specific policy.

That is why the default should be deliberate.

If every casual Slack mention hits a premium model, the system becomes expensive and awkward to use. If the default is too weak, the bot feels unreliable and I stop trusting it for normal work.

The target is the middle: a default route that can summarize, reason, call tools, and handle messy context, without making every small prompt feel like a special occasion.

For my setup, that meant OpenRouter as the everyday model path, with Codex available separately for harder coding and agentic work.

The important part is not the exact provider names. It is the separation of concerns:

# ==================== TEXT CODE ====================
Normal channel turn -> default route
Harder coding turn -> stronger coding route
Explicit request -> requested route, if supported

That is the shape I want from a personal agent gateway.

The goal is a model portfolio, not a model identity

The ideal version of this setup is not one static default forever.

It is a routing policy.

The rough policy I want looks like this:

• Use the cost-aware default for normal Slack and Telegram turns.

• Use a stronger coding model for repo edits, CI debugging, and multi-file changes.

• Use a research-capable route when the task needs documentation, search, or synthesis.

• Use a fast route for short administrative replies.

• Allow explicit overrides when I ask for a specific model.

That is a model portfolio.

It also changes how I think about the bot. The bot is not "the Kimi bot" or "the GPT bot." It is an agent gateway with multiple possible routes behind it.

That distinction matters because model catalogs move quickly. A route that is the best default today may be the wrong default later. The architecture should make it easy to change the route without changing the channel setup, the Slack policy, or the MCP toolbelt.

When the model layer is modular, provider changes become maintenance. They do not become rewrites.

Avoiding accidental model drift

Once multiple providers exist, confusion becomes easy.

A bot can feel like it is using the wrong model for several reasons:

• The default route changed.

• A channel has its own route.

• An older session is still active.

• The gateway has not reloaded the latest config.

• A command worked in the terminal but the running service still has old state.

The fix is to inspect instead of guessing.

The command shapes I use are:

# ==================== BASH CODE ====================
openclaw models list
openclaw status
openclaw config validate

The useful thing in status output is not just whether OpenClaw is alive. It is which sessions are active and what model state they appear to be using.

Long-running systems accumulate state. A Slack thread, Telegram conversation, or local gateway process can outlive the config change that made you expect new behavior.

So when a reply feels wrong, I do not start by blaming the provider. I start by asking: which route did this turn actually use?

Restart, then test with a fresh turn

After changing model defaults or provider config, I treat OpenClaw like a service.

The safe rhythm is:

# ==================== BASH CODE ====================
openclaw config validate
openclaw gateway restart
openclaw health

Then I send a fresh message from the actual channel I care about.

Fresh matters.

Testing an old Slack thread can make a new config look broken if the previous session is still carrying older state. Testing only from a CLI command can make the channel path look healthier than it really is.

The clean test is a new prompt through the real channel after the gateway restarts.

That gives you a better answer to the question you actually care about:

# ==================== TEXT CODE ====================
When I mention the bot from Slack or Telegram now, what model route handles the turn?

How to explain the setup publicly

The public version should be high-level and redacted.

I would describe the model layer like this:

# ==================== TEXT CODE ====================
I configured OpenRouter as the default provider route for ordinary bot turns. Then I added OpenAI/Codex as a second auth profile so the same OpenClaw agent could access stronger coding-oriented models when needed. The OpenAI login did not overwrite the OpenRouter setup. It added another provider lane. From there, model choice became a routing question rather than a reinstall question.

That says the important part without exposing keys, account emails, profile IDs, private local paths, provider account metadata, or exact runtime state.

The article should show command shapes, not secrets.

Good public examples look like this:

# ==================== TEXT CODE ====================
OPENROUTER_API_KEY=REDACTED
OPENAI_CODEX_AUTH=REDACTED

The exact value is never the lesson.

The lesson is that provider auth, model defaults, channel behavior, and tool access are separate layers.

Practical model-routing checklist

Before relying on a multi-model OpenClaw setup, I would use this checklist.

1. Get one provider working first.

Do not debug routing before you know one model path works end to end.

1. Confirm the default route.

Do not assume the last provider you added became the default.

1. Add the second provider.

Use the provider's supported auth flow, whether that is OAuth, an API key, or another local credential path.

1. Re-check defaults after adding auth.

Auth and routing are separate. Confirm both.

1. Restart the gateway after config changes.

The config on disk is not always the config in the running service.

1. Test from the actual channel.

A route that works from a CLI still needs to work from Slack or Telegram.

1. Start a fresh session when behavior looks stale.

Old sessions can make new config look broken.

1. Keep public examples redacted.

Never publish provider keys, OAuth artifacts, local account IDs, channel IDs, or private dashboard URLs.

The key lesson from part three

The model layer should be flexible without becoming mysterious.

OpenRouter gave me a practical everyday route. Codex gave me a stronger coding-oriented lane. OpenClaw sat above both as the local gateway that channels could reach and tools could attach to.

That is the separation of concerns I want:

• Channels decide how the agent is reached.

• Model routing decides what intelligence handles the turn.

• MCP servers decide what tools the agent can use.

When those layers stay separate, the system becomes easier to reason about. I can change the default model without rebuilding Slack. I can add Codex without deleting OpenRouter. I can add MCP tools without changing who is allowed to trigger the bot.

That is what turns a messaging bot into infrastructure.

In the next part, I will cover the MCP layer: how Slack, Ref, Exa, Firecrawl, filesystem, Websets, Paper, and Morph turned the bot from a chat surface into a workstation agent.

Enjoyed this post?

Get our latest research insights and technical deep dives delivered to your inbox.

Subscribe on Substack