> ## Documentation Index
> Fetch the complete documentation index at: https://docs.morphllm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Open Source Models

> Open-weight models with automatic prefix caching

Running on Morph's custom kernels and inference stack optimized for codegen. OpenAI-compatible at `https://api.morphllm.com/v1`, and Anthropic-compatible at `/v1/messages` (see [Endpoints](/endpoints)).

| Model                                   | Model ID           | Context |
| :-------------------------------------- | :----------------- | :------ |
| **Kimi K3 2.8T**                        | `morph-kimik3`     | 1M      |
| **GLM-5.3 744B**                        | `morph-glm53-744b` | 1M      |
| **GLM-5.3-Flash** <sup>multimodal</sup> | `morph-glm53flash` | 1M      |
| **DeepSeek V4 Flash 0731**              | `morph-dsv4flash`  | 1M      |

All models support `tools`, `response_format` (JSON mode + JSON schema), structured outputs, logprobs, and reasoning. Per-token rates are on the [pricing page](https://www.morphllm.com/pricing) and live at [`/api/models/json`](https://www.morphllm.com/api/models/json).

## Quick Start

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from openai import OpenAI

    client = OpenAI(
        api_key="YOUR_API_KEY",
        base_url="https://api.morphllm.com/v1",
    )

    response = client.chat.completions.create(
        model="morph-glm53-744b",
        messages=[
            {"role": "system", "content": "You are a senior backend engineer."},
            {"role": "user", "content": "Refactor this Express handler to use async/await: ..."},
        ],
        temperature=0.2,
    )

    print(response.choices[0].message.content)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import OpenAI from "openai";

    const client = new OpenAI({
      apiKey: "YOUR_API_KEY",
      baseURL: "https://api.morphllm.com/v1",
    });

    const stream = await client.chat.completions.create({
      model: "morph-glm53-744b",
      messages: [{ role: "user", content: "Write a tiny rate limiter in TS." }],
      stream: true,
    });

    for await (const chunk of stream) {
      process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
    }
    ```
  </Tab>

  <Tab title="Anthropic SDK">
    ```python theme={null}
    import anthropic

    client = anthropic.Anthropic(
        api_key="YOUR_API_KEY",
        base_url="https://api.morphllm.com",  # no /v1 suffix
    )

    message = client.messages.create(
        model="morph-glm53-744b",
        max_tokens=1024,
        messages=[{"role": "user", "content": "Write a tiny rate limiter in TS."}],
    )
    print(message.content[-1].text)
    ```
  </Tab>

  <Tab title="Claude Code">
    ```bash theme={null}
    export ANTHROPIC_BASE_URL="https://api.morphllm.com"   # no /v1 suffix
    export ANTHROPIC_AUTH_TOKEN="YOUR_API_KEY"
    export ANTHROPIC_MODEL="morph-glm53-744b"              # or any model above
    ```

    Claude Code talks the Anthropic Messages API natively, which every model on this page serves at `/v1/messages`. `ANTHROPIC_MODEL` remaps sonnet/opus; `ANTHROPIC_SMALL_FAST_MODEL` remaps haiku (background tasks). Details and caveats in [Endpoints](/endpoints) and the [Coding Agents guide](/guides/coding-agents).
  </Tab>

  <Tab title="Vercel AI SDK">
    ```typescript theme={null}
    import { createOpenAI } from "@ai-sdk/openai";
    import { generateText } from "ai";

    const morph = createOpenAI({
      apiKey: "YOUR_API_KEY",
      baseURL: "https://api.morphllm.com/v1",
    });

    const { text } = await generateText({
      model: morph("morph-glm53-744b"),
      prompt: "Summarize this PR diff in one paragraph: ...",
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST "https://api.morphllm.com/v1/chat/completions" \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "morph-glm53-744b",
        "messages": [
          {"role": "user", "content": "Write a SQL query that finds the top 5 customers by revenue last quarter."}
        ],
        "temperature": 0.2
      }'
    ```

    The Anthropic Messages shape works on the same key, same models:

    ```bash theme={null}
    curl -X POST "https://api.morphllm.com/v1/messages" \
      -H "x-api-key: YOUR_API_KEY" \
      -H "anthropic-version: 2023-06-01" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "morph-glm53-744b",
        "max_tokens": 1024,
        "messages": [
          {"role": "user", "content": "Write a SQL query that finds the top 5 customers by revenue last quarter."}
        ]
      }'
    ```
  </Tab>
</Tabs>

## Tools and Structured Output

Tool format follows the endpoint: OpenAI function definitions on `/v1/chat/completions`, Anthropic `tools` + `tool_use` blocks on `/v1/messages`. Kimi K3 can also [load tools dynamically](/sdk/components/dynamic-tool-loading) from a contentless system message, so an agent can add schemas after searching a large tool registry without resending the full catalog on every turn.

<Tabs>
  <Tab title="OpenAI">
    ```typescript theme={null}
    const response = await client.chat.completions.create({
      model: "morph-glm53-744b",
      messages: [{ role: "user", content: "What's the weather in SF?" }],
      tools: [
        {
          type: "function",
          function: {
            name: "get_weather",
            description: "Get weather for a city",
            parameters: {
              type: "object",
              properties: { city: { type: "string" } },
              required: ["city"],
            },
          },
        },
      ],
      response_format: { type: "json_object" },
    });
    ```
  </Tab>

  <Tab title="Anthropic SDK">
    ```python theme={null}
    message = client.messages.create(
        model="morph-kimik3",
        max_tokens=1024,
        messages=[{"role": "user", "content": "What's the weather in SF?"}],
        tools=[
            {
                "name": "get_weather",
                "description": "Get weather for a city",
                "input_schema": {
                    "type": "object",
                    "properties": {"city": {"type": "string"}},
                    "required": ["city"],
                },
            }
        ],
    )

    tool_use = next(b for b in message.content if b.type == "tool_use")
    print(tool_use.name, tool_use.input)  # get_weather {'city': 'San Francisco'}
    ```

    Send the result back as a `tool_result` block in a `user` message, same as Anthropic documents. `stop_reason` is `tool_use` when the model calls a tool.
  </Tab>
</Tabs>

Reasoning is off by default. Enable with `reasoning: { effort: "medium" }` (`"low"` / `"high"`). Reasoning tokens bill as output.

Automatic [prefix caching](/sdk/components/caching) is on for all models, with per-request TTL control. Use [Model Router](/sdk/components/router) to pick automatically per request.

Multi-turn agents: send `prompt_cache_key` (or the `x-session-id` header) with a per-conversation id so every turn lands on the worker holding its cache. See [Session key](/sdk/components/caching#session-key).

## Service Tiers

GLM-5.3 supports the OpenAI `service_tier` parameter.

| Tier                              | Behavior                                                                                                                            |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `default` (or `auto`, or omitted) | Standard processing. What every request gets today.                                                                                 |
| `standby`                         | Best-effort capacity. Served when the fleet has headroom, rejected with a retryable 429 when it doesn't. No latency target, no SLA. |

```python theme={null}
response = client.chat.completions.create(
    model="morph-glm53-744b",
    messages=[{"role": "user", "content": "Label these 500 rows: ..."}],
    service_tier="standby",
)
```

How standby works:

* A standby request is admitted only while the fleet is under roughly a quarter of its serving capacity. When no region qualifies, you get `429` with `error.code: "resource_unavailable"` and a `Retry-After` header. Nothing is generated and nothing is billed. Expect most standby throughput off-peak.
* On a 429, retry with exponential backoff. If you need the result now, resend with `service_tier: "default"`.
* The response echoes the tier that served it in a `service_tier` field (on the final usage chunk when streaming).
* Streaming, tools, and structured output work the same as `default`.
* Unknown tier values return `400` listing the accepted ones.

Use standby for evals, batch labeling, data generation, and anything a retry loop can absorb. Keep interactive and agent-loop traffic on `default`: under load, default requests are served in full while standby is shed in \~200ms.

Standby bills at 50% of the standard per-token rates ([Standby Requests](/sdk/components/standby)). Available on GLM-5.3 (`morph-glm53-744b`); sending it to other models is a no-op.

## Route 5% of Production Traffic

To trial a model on a slice of real traffic, paste this into Claude Code (or any coding agent) at the root of your repo:

```text theme={null}
Route 5% of our production LLM traffic (or the percentage I specify) to Kimi K3 on Morph. We may be using the OpenAI SDK or the Anthropic SDK — detect which and keep it: OpenAI-compatible base URL is `https://api.morphllm.com/v1`, Anthropic-compatible is `https://api.morphllm.com` (no `/v1` suffix). Model is `morph-kimik3`, auth via `MORPH_API_KEY` env var. Docs: https://docs.morphllm.com/sdk/components/fast-models

Before wiring it into prod, verify locally with a quick script using our SDK: one non-streaming call, one streaming call, and a tool call if we use tools. Then implement the split at our existing client chokepoint: deterministic bucketing on a stable ID (same user always gets the same provider), percentage from an env var so 0 is the kill switch, and fall back to our current provider if the Morph call errors.

Watch out for:
- Anthropic `messages.create` requires `max_tokens`, and responses may lead with a `thinking` block — read the last text block, not `content[0].text`.
- Tool format must match the endpoint: OpenAI shape on `/v1/chat/completions`, Anthropic `tool_use` blocks on `/v1/messages`.

Verify locally before calling it done:
- Smoke script passes for every request shape we use.
- Run ~100 requests through the routing function: Morph share is ≈ the configured percent, same ID always lands in the same bucket.
- Break the Morph key: request still succeeds via fallback. Set percent to 0: nothing routes to Morph.
```

Swap `morph-kimik3` for any model ID in the table above.

## Claude Code

Claude Code speaks the Anthropic Messages API, so it runs on these models with four env vars — tools (Read, Edit, Write, Bash, Grep) go through the standard `tool_use` / `tool_result` loop:

```bash theme={null}
export ANTHROPIC_BASE_URL="https://api.morphllm.com"
export ANTHROPIC_AUTH_TOKEN="YOUR_MORPH_API_KEY"
export ANTHROPIC_MODEL="morph-kimik3"
export ANTHROPIC_SMALL_FAST_MODEL="morph-glm53flash"
claude
```

Full setup, `settings.json`, and MCP tools: [Claude Code](/guides/claude-code).

## Pitfalls

<AccordionGroup>
  <Accordion title="Latency worse than expected">
    TPS numbers are generation throughput, not end-to-end. With 30k tokens of context, prefill dominates first-token wait even with caching. For agent loops, keep a smaller working context with [Compact](/sdk/components/compact) rather than filling the full window.
  </Accordion>

  <Accordion title="Tool calls not working">
    On `/v1/chat/completions` these models use OpenAI tool-call shape; Anthropic `tool_use` blocks work on [`/v1/messages`](/endpoints). Match the tool format to the endpoint. Gemini `functionDeclarations` work on neither.
  </Accordion>

  <Accordion title="JSON mode returns prose">
    Pass `response_format: { type: "json_object" }` *and* say "respond in JSON" in your prompt. For strict shape control: `response_format: { type: "json_schema", json_schema: { ... } }`.
  </Accordion>
</AccordionGroup>

## See Also

* [Dynamic Tool Loading](/sdk/components/dynamic-tool-loading) — add Kimi K3 tools during a conversation
* [Prompt Caching](/sdk/components/caching) — automatic cached-input discounts, per-request TTL
* [Session key](/sdk/components/caching#session-key) — one id per conversation keeps its turns on the worker holding the cache
* [Standby Requests](/sdk/components/standby) — best-effort GLM-5.3 capacity for batch and background work
* [Model Router](/sdk/components/router) — auto-route between these and frontier models per request
* [Compact](/sdk/components/compact) — shrink context before paying for it
* [WarpGrep](/sdk/components/warp-grep/index) — code search for retrieval when context is the bottleneck
* [Claude Code](/guides/claude-code) — run these models in Claude Code over `/v1/messages`
