# Extending Claude Code: Routing Third-Party Models & Using Codex as a Second Agent

**Teaching material** · Module "AI Conception" / Agentic AI
**Format:** Handoff for Claude AI Design · freely shareable with course participants
**Scope:** two units that build on each other (approx. 90 min. each)

---

## About This Document

This material consists of two parts that can be taught independently or in combination:

- **Part 1 – Model Routing:** How to redirect Claude Code to a different provider (here
  GLM-5.2 via Z.ai) so that the familiar tiers such as *Opus* access a third-party
  model.
- **Part 2 – Codex Plugin:** How to embed a second, independent coding agent (Codex) in
  Claude Code using `openai/codex-plugin-cc`.

The common thread of both parts: **Claude Code is open.** You can swap out the *model
behind it* (Part 1) and place *additional agents* alongside it (Part 2). Both techniques
are independent of each other and can even be used simultaneously.

> **Important connection for participants:** If you route Claude Code to GLM, *only
> Claude Code* runs over GLM. The Codex plugin still uses the separate Codex login and
> OpenAI models. The two paths don't interfere with each other — but they are billed
> separately.

---

## Shared Learning Objectives

After both units, participants will be able to:

1. explain how Claude Code is configured via environment variables;
2. redirect Claude Code to an Anthropic-compatible third-party endpoint;
3. map the tier aliases (opus/sonnet/haiku) to arbitrary models;
4. install and set up a plugin via the marketplace;
5. deploy a second agent for reviews and delegated tasks;
6. name the risks of both approaches (cost, data paths, agent loops, trust boundaries).

---
---

# PART 1 — Routing Third-Party Models in Claude Code (Example: GLM-5.2)

## 1.1 The Basic Principle

By default, Claude Code talks to `api.anthropic.com`. Using the `env` block in a settings
file, this target endpoint can be redirected entirely. By now, several providers offer an
**Anthropic-compatible endpoint** — besides Z.ai (Zhipu AI, GLM family), also Moonshot
with Kimi and MiniMax, for example. With these, routing works without an additional proxy
as a genuine drop-in replacement. GLM-5.2 serves as the example here; you integrate Kimi
or MiniMax through the same `env` variables — you only swap the base URL and the model IDs
(e.g. `https://api.z.ai/api/anthropic` for Z.ai).

**The central trick:** Internally, Claude Code knows only the *tier aliases* `opus`,
`sonnet`, and `haiku`. Using the `ANTHROPIC_DEFAULT_*_MODEL` variables, you map each tier
to a concrete GLM model. When you then pick `/model opus` in the CLI, the request actually
goes to `glm-5.2`.

```
   You (in the terminal)
        │
        ▼
   Claude Code ──ANTHROPIC_BASE_URL──►  api.z.ai/api/anthropic
        │                                     │
   /model opus                          translates request
        │                                     ▼
   maps via                               GLM-5.2 responds
   ANTHROPIC_DEFAULT_OPUS_MODEL          in Anthropic format
```

## 1.2 Prerequisites

| Prerequisite | Details |
|---|---|
| Z.ai account | Registration on the Z.ai Open Platform |
| API key | create it in the "API Keys" section |
| Coding plan | subscription for GLM coding access (quota-based; GLM-5.2 included) |
| Claude Code | currently installed |

## 1.3 Step by Step

**Step 1 — Obtain an API key.** Register on the Z.ai Open Platform, create a key under
"API Keys", and copy it.

**Step 2 — Open the settings file.**
- *Project-scoped* (recommended for keys): `.claude/settings.local.json` in the repo root.
  This file is ignored by Git by default.
- *Machine-wide:* `~/.claude/settings.json`.

**Step 3 — Add the `env` block** (official Z.ai configuration):

```json
{
  "env": {
    "ANTHROPIC_AUTH_TOKEN": "DEIN_ZAI_API_KEY",
    "ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic",
    "ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.7",
    "ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-5.2[1m]",
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-5.2[1m]",
    "CLAUDE_CODE_AUTO_COMPACT_WINDOW": "1000000",
    "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
    "API_TIMEOUT_MS": "3000000"
  }
}
```

**Step 4 — Restart Claude Code completely.** Environment variables are read only *once, at
process start*. Reopening a tab is not enough — fully quit the process and start `claude`
fresh.

**Step 5 — Verify.**
- `echo $ANTHROPIC_BASE_URL` → must print `https://api.z.ai/api/anthropic`.
- In the CLI, check `/model` → should show `glm-5.2` / `GLM-5.2`, with no Claude fallback.
- Identity probe: "What model are you?" → GLM-5.2 identifies itself correctly. If it says
  "Claude", the routing is wrong.

## 1.4 What the Fields Mean

| Field | Function |
|---|---|
| `ANTHROPIC_AUTH_TOKEN` | Bearer token for the gateway. **With Z.ai it must go here**, not in `ANTHROPIC_API_KEY`. |
| `ANTHROPIC_BASE_URL` | Redirects all traffic to the third-party endpoint. |
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | Tier *haiku* → the low-cost `glm-4.7`. |
| `ANTHROPIC_DEFAULT_SONNET_MODEL` | Tier *sonnet* → `glm-5.2[1m]` (1M context). |
| `ANTHROPIC_DEFAULT_OPUS_MODEL` | Tier *opus* → `glm-5.2[1m]`. |
| `API_TIMEOUT_MS` | Raised because GLM responds more slowly and agent loops would otherwise time out. |

## 1.5 Common Mistakes (for the Classroom)

- **Wrong key variable:** Z.ai expects `ANTHROPIC_AUTH_TOKEN`, not `ANTHROPIC_API_KEY`.
  The most common beginner mistake.
- **Wrong path in the URL:** The Anthropic-compatible path is `/api/anthropic` — not the
  generic OpenAI path.
- **Process not restarted:** the change takes effect only after a full restart.
- **Competing login:** An active Claude Max login or an `ANTHROPIC_API_KEY` in the shell
  can take precedence. Use `/status` to check which route is active.
- **Key in Git:** be sure to keep `.claude/settings.local.json` in `.gitignore`.

## 1.6 Tip: Switching Cleanly

If you want to switch between GLM and regular Claude, it's better to set up a separate
shell function than to redirect globally — that way it's always clear which provider is
active (and being paid for) in which terminal:

```bash
# in ~/.zshrc or ~/.bashrc
claude-zai() {
  ANTHROPIC_BASE_URL="https://api.z.ai/api/anthropic" \
  ANTHROPIC_AUTH_TOKEN="$Z_AI_API_KEY" \
  claude "$@"
}
```
Then use `claude-zai` for GLM and plain `claude` for Anthropic.

## 1.7 Discussion Questions (Part 1)

1. Why does routing to Z.ai work *without* a proxy, while for many other providers it
   works only through a gateway such as OpenRouter?
2. What is the difference between `ANTHROPIC_AUTH_TOKEN` and `ANTHROPIC_API_KEY`?
3. What privacy question arises when code is sent to an endpoint in a different legal
   jurisdiction?
4. Why do you deliberately map *haiku* to a cheaper model than *opus*?

---
---

# PART 2 — Embedding Codex as a Second Agent (`openai/codex-plugin-cc`)

**Repository:** `openai/codex-plugin-cc` · License Apache-2.0 · Language JavaScript

## 2.1 What Is This About?

Claude Code is Anthropic's agentic coding tool. Codex is OpenAI's counterpart. Both are
standalone agents with their own CLI, their own login, and their own models.

The `codex-plugin-cc` plugin connects the two: it lets you invoke **Codex from within
Claude Code** — to have your own code reviewed by a second, independent instance, or to
hand off entire tasks to Codex.

**Core teaching idea — a "second opinion" among agents:** Just as you have code reviewed
by a human colleague, here you obtain the judgment of a *different* model. A second agent
that doesn't share the first one's assumptions often finds errors that the original author
(human or AI) overlooks.

> **Key point:** The plugin does *not* start a second AI runtime. It calls the locally
> installed Codex CLI on the same machine — same installation, same login, same repo
> checkout. Claude Code is merely the remote control.

## 2.2 Architecture

```
   You (in the terminal)
        │
        ▼
   Claude Code ──calls──►  codex-plugin-cc  ──wraps──►   Codex App Server
                             (slash commands)                │
                                                             ▼
                                                    local Codex CLI
                                                    (same login,
                                                     same config.toml)
```

Consequences:
- **One login is enough:** Anyone already logged in to Codex can get started right away.
- **Shared configuration:** The plugin reads the same `config.toml` as Codex does directly.
- **Usage counts against the Codex quota**, not against Claude's.

## 2.3 Prerequisites

| Prerequisite | Details |
|---|---|
| Codex access | ChatGPT subscription (Free tier too) **or** OpenAI API key |
| Node.js | Version 18.18 or newer |
| Claude Code | with plugin/marketplace support |

## 2.4 Installation — Step by Step

**Step 1 — Add the marketplace**
```
/plugin marketplace add openai/codex-plugin-cc
```

**Step 2 — Install the plugin**
```
/plugin install codex@openai-codex
```

**Step 3 — Reload plugins**
```
/reload-plugins
```

**Step 4 — Setup check**
```
/codex:setup
```
Checks whether Codex is installed and logged in. If Codex is missing and npm is available,
the setup offers to install Codex.

**Manual Codex installation (optional):**
```
npm install -g @openai/codex
```

**Login (if needed):**
```
!codex login
```
> The leading `!` runs a shell command directly from within Claude Code.

**Success check:** Afterward the slash commands are visible and the `codex:codex-rescue`
subagent appears under `/agents`.

## 2.5 Command Reference — The Seven Commands (Handout)

| Command | Purpose | Changes code? | Steerable? |
|---|---|---|---|
| `/codex:review` | Standard read-only review of the current work | No | No |
| `/codex:adversarial-review` | Critical scrutiny of design & assumptions | No | Yes (focus text) |
| `/codex:rescue` | Delegate a task to Codex (bug, fix, continuation) | Yes | Yes |
| `/codex:transfer` | Continue a Claude session as a Codex thread | — | — |
| `/codex:status` | Show running & recent Codex jobs | No | — |
| `/codex:result` | Retrieve the final result of a finished job | No | — |
| `/codex:cancel` | Abort an active background job | No | — |

### `/codex:review` — the second opinion
Review of the current, uncommitted changes. Branch comparison with `--base <ref>`.
```
/codex:review
/codex:review --base main
/codex:review --background
```
*Teaching point:* Multi-file reviews take time → let them run in the background and
collect them with `/codex:status` / `/codex:result`.

### `/codex:adversarial-review` — the devil's advocate
A **steerable** review that questions the chosen implementation: assumptions, trade-offs,
failure modes, alternatives. Free-form focus text follows the flags.
```
/codex:adversarial-review --base main challenge whether this was the right caching and retry design
/codex:adversarial-review --background look for race conditions and question the chosen approach
```
*Didactic contrast:* `review` = "Is the code correct?" · `adversarial-review` = "Was this
even the right approach?"

### `/codex:rescue` — hand off work
Hands a task off via the `codex:codex-rescue` subagent. Flags: `--background`, `--wait`,
`--resume`, `--fresh`, `--model`, `--effort`.
```
/codex:rescue investigate why the tests started failing
/codex:rescue --model gpt-5.4-mini --effort medium investigate the flaky integration test
/codex:rescue --resume apply the top fix from the last run
```
Can also be delegated in natural language:
```
Ask Codex to redesign the database connection to be more resilient.
```
*Notes:* Without `--model`/`--effort`, Codex picks defaults. `spark` maps to
`gpt-5.3-codex-spark`. Follow-up requests continue the last task in the repo.

### `/codex:transfer` — take the context with you
Creates a persistent Codex thread from the current Claude session and outputs
`codex resume <session-id>`. Useful for continuing a debugging conversation you've started
in Codex with the same context. The source must reside under `~/.claude/projects`.

### Job management: `status`, `result`, `cancel`
```
/codex:status              # is the job still running?
/codex:result              # retrieve the final result (incl. Codex session ID)
/codex:cancel task-abc123  # cancel a specific job
```

## 2.6 Typical Workflows

**Review before shipping**
```
/codex:review
```
**Hand a problem off to Codex**
```
/codex:rescue investigate why the build is failing in CI
```
**Start something long-running and pick it up later**
```
/codex:adversarial-review --background
/codex:rescue --background investigate the flaky test
/codex:status
/codex:result
```

## 2.7 The Review Gate — Advanced & to Be Used with Caution

```
/codex:setup --enable-review-gate
/codex:setup --disable-review-gate
```
When the gate is active, the plugin hooks into Claude's response via a `Stop` hook and
lets Codex run a targeted review. If Codex finds problems, the stop is **blocked** until
Claude has fixed them.

> **Warning:** The gate can create a long-running Claude-↔-Codex loop and burn through the
> usage limit quickly. Enable it only when you are actively watching the session.

A good occasion to discuss **agent loops and cost control**.

## 2.8 Configuration

Reasoning effort and the default model are controlled through Codex's `config.toml`:
```toml
model = "gpt-5.4-mini"
model_reasoning_effort = "high"
```
Load order: user level `~/.codex/config.toml` → project level `.codex/config.toml` (only
if the project is *trusted*). An alternative endpoint can be set via `openai_base_url`.

## 2.9 Discussion Questions (Part 2)

1. Why does a *different* model often deliver better review results than the model that
   wrote the code?
2. When is `adversarial-review` more useful than `review`? Name two cases.
3. What does it mean for privacy and cost that the plugin uses the *local* Codex CLI and
   its login?
4. Explain the difference between `--wait` and `--background`.
5. What danger does the review gate pose, and how do you contain it?

---
---

# Final Hands-On Exercise (Combines Parts 1 & 2)

**Goal:** Experience both techniques in a realistic workflow.

1. Clone a small repo and introduce a subtle bug on a branch (e.g. an off-by-one or a race
   condition).
2. **Part 1:** Route Claude Code to GLM-5.2 via `.claude/settings.local.json` and verify
   with `/model` as well as an identity probe.
3. Have the GLM-routed Claude Code investigate the bug.
4. **Part 2:** Install the Codex plugin (`/codex:setup`) and start
   `/codex:adversarial-review --background` with a focus on the race condition.
5. Collect the results (`/codex:status`, `/codex:result`) and compare them with the GLM
   findings.
6. **Reflection:** Where did the GLM analysis and the Codex review diverge in substance?
   What does that say about the value of independent second opinions?

---

## Notes for Reuse in Claude AI Design

- This document is deliberately modular: heading levels (`#`, `##`, `###`) and tables can
  be transferred directly into slides, a dashboard, or a handout.
- The command tables in 2.5 and the field table in 1.4 work well as standalone cheat-sheet
  cards.
- The discussion questions and the hands-on exercises can be split off as separate
  worksheets.

*Sources: official Z.ai documentation on Claude Code integration as well as the README of
the repository `openai/codex-plugin-cc`. Commands, flags, and model names may change with
new releases — for the current reference, check the respective original sources.*
