GLM-5.2 with LlamaIndex: Tested Setup, RAG and Tools
Independent research — not an official Z.ai publication.Identity and provider disclosure
Original editorial illustration of the tested data path. It is not a LlamaIndex or Z.ai product screen. The later terminal image is generated from the sanitized Docker results.
GLM-5.2 speaks an OpenAI-compatible chat protocol, but that does not make
every class named OpenAI interchangeable. LlamaIndex’s regular wrapper
expects a model in its own OpenAI metadata table. When our test asked it for
metadata about glm-5.2, it raised ValueError: Unknown model 'glm-5.2'
before making a network request.
OpenAILike is the deliberate escape hatch for a third-party compatible API.
It also makes three decisions your application must not leave implicit. The
tested package defaults to a 3,900-token context, treats the model as a
completion model rather than a chat model, and disables function-calling
metadata. GLM-5.2 supports a one-million-token context and chat tools, so each
value needs to be stated.
This guide provides the exact object, four live acceptance checks, observed latency and usage, an embedding-free document query, and the commercial boundary between Z.ai’s metered API and Coding Plan. The goal is a runnable receipt, not a configuration that merely imports.
Follow the LlamaIndex acceptance path
Section titled “Follow the LlamaIndex acceptance path”- Choose the adapter
- Separate the Z.ai products
- Install pinned packages
- Copy the tested object
- Verify chat
- Verify streaming
- Execute a tool
- Query one document
- Read the receipts
- Reconstruct cost
- Repair failures
- Promote safely
- Audit sources
Choose OpenAILike before copying code
Section titled “Choose OpenAILike before copying code”The two wrappers share many constructor fields, but their metadata contracts are different:
| LlamaIndex class | Intended model family | glm-5.2 result in our test |
|---|---|---|
llama_index.llms.openai.OpenAI |
Known OpenAI model IDs | Metadata lookup raised ValueError |
llama_index.llms.openai_like.OpenAILike |
Third-party OpenAI-compatible APIs | Accepted explicit GLM metadata and completed four checks |
The current
OpenAILike source
describes it as a thin wrapper for compatible third-party APIs. The same
source exposes these defaults:
context_window = 3900is_chat_model = falseis_function_calling_model = falseThose values are safe generic assumptions, not GLM-5.2 discovery. LlamaIndex does not fetch Z.ai’s model card and repair them for you.
The regular wrapper failure is useful. It prevents an unknown name from
silently inheriting incorrect OpenAI metadata. Do not “fix” it by renaming
the model to gpt-5.2; that is a different provider’s model. Change the
adapter while preserving the real Z.ai model ID.
Separate the metered endpoint from Coding Plan
Section titled “Separate the metered endpoint from Coding Plan”Z.ai publishes two OpenAI-compatible commercial routes with different usage rules:
| Route | Base URL | LlamaIndex status on July 29 |
|---|---|---|
| General pay-as-you-go API | https://api.z.ai/api/paas/v4 |
Live tested and passed |
| GLM Coding Plan | https://api.z.ai/api/coding/paas/v4 |
Not called; LlamaIndex was not listed as a supported tool |
The Z.ai quick start says the Coding endpoint is for supported tools and recommends the general API for other use cases. The current Coding Plan tool list includes coding agents such as Claude Code, OpenCode, Cline, Kilo Code and others, but not LlamaIndex.
An endpoint accepting the same JSON shape does not erase that product rule. For a LlamaIndex application, use a general API key and general endpoint unless Z.ai adds the framework to its supported list. If you need a supported coding shell instead, the Coding Plan versus API guide separates subscription, metered and self-hosted decisions.
Install the four pinned packages
Section titled “Install the four pinned packages”The successful container used Python 3.13.13 and this package set:
llama-index-core 0.14.23llama-index-llms-openai 0.7.10llama-index-llms-openai-like 0.7.2openai 2.50.0pydantic 2.13.4Create a clean environment and install only the integrations used here:
python -m venv .venv. .venv/bin/activatepython -m pip install \ "llama-index-core==0.14.23" \ "llama-index-llms-openai==0.7.10" \ "llama-index-llms-openai-like==0.7.2"python -m pip checkPyPI lists
llama-index-llms-openai-like 0.7.2
for Python 3.10 and newer. It was uploaded April 23, 2026. Pinning the
integration separately from core matters because LlamaIndex ships provider
adapters as independent packages.
Our digest-pinned container mounted the repository read-only and opened no listener or published port. Its default Docker bridge reproduced this host’s known DNS failure, so the trusted outbound-only test used the documented host network exception. That accommodation is part of our reproducibility record, not a recommendation to grant host networking to arbitrary containers.
Copy the explicit GLM-5.2 object
Section titled “Copy the explicit GLM-5.2 object”Keep the key out of the Python file:
export ZAI_API_KEY="your-general-api-key"test -n "$ZAI_API_KEY" && echo "ZAI_API_KEY is set"Then set every model-specific metadata field:
import osfrom llama_index.llms.openai_like import OpenAILike
llm = OpenAILike( model="glm-5.2", api_base="https://api.z.ai/api/paas/v4", api_key=os.environ["ZAI_API_KEY"], context_window=1_048_576, is_chat_model=True, is_function_calling_model=True, reasoning_effort="none", temperature=0, max_tokens=128, max_retries=0, timeout=90,)The official GLM-5.2 guide supplies
the model ID, the OpenAI-compatible base URL, text modality, one-million-token
context and 128K maximum output. The max_tokens=128 line above is a small
test budget, not the model maximum.
max_retries=0 makes a one-shot acceptance test easier to interpret. A
production application can add bounded retries for selected transient
errors, but it should record the attempt count. Otherwise one apparent
five-second call may hide several upstream requests and charges.
Prove one exact chat response
Section titled “Prove one exact chat response”Do not stop after printing llm.metadata. Send a request and assert the
application-visible value:
from llama_index.core.llms import ChatMessagefrom glm_llamaindex import llm
response = llm.chat([ ChatMessage( role="user", content="Return exactly LLAMAINDEX_CHAT_OK and no other text.", )])
text = (response.message.content or "").strip()assert text == "LLAMAINDEX_CHAT_OK", textprint(text)The July 29 request returned the exact marker in 3,432 ms. Its usage object reported 25 prompt tokens, 65 completion tokens and 90 total tokens. This is one observed request, not a latency percentile.
The completion count is more important than it first appears. The visible marker is short, yet the provider accounted for 65 completion tokens. Hidden reasoning or provider-side accounting can make visible characters a poor cost proxy. Save sanitized usage fields even when the final text is tiny.
Stream the marker and count events
Section titled “Stream the marker and count events”Streaming success requires more than receiving HTTP 200. Accumulate deltas and check the final string:
from llama_index.core.llms import ChatMessagefrom glm_llamaindex import llm
pieces = []event_count = 0for event in llm.stream_chat([ ChatMessage( role="user", content="Return exactly LLAMAINDEX_STREAM_OK and no other text.", )]): event_count += 1 if event.delta: pieces.append(event.delta)
text = "".join(pieces).strip()assert text == "LLAMAINDEX_STREAM_OK", textprint(event_count, text)Our stream delivered 117 LlamaIndex events and the exact marker in 2,691 ms. The final usage object reported 25 prompt and 120 completion tokens. Event count is adapter behavior, not token count: one token can be surrounded by metadata-only events, and a delta can contain more than one text unit.
For an SSE-level parser and disconnect tests, use the separate GLM-5.2 streaming API guide. LlamaIndex abstracts that wire format; it does not remove the need to handle empty deltas, cancellation, timeouts and partial output.
Execute a typed LlamaIndex function tool
Section titled “Execute a typed LlamaIndex function tool”Marking is_function_calling_model=True advertises a capability to
LlamaIndex. A real tool test must still prove the model selected the right
function, supplied valid arguments and allowed the application to execute it:
from llama_index.core.tools import FunctionToolfrom glm_llamaindex import llm
calls = []
def lookup_service_port(service: str) -> str: """Return the configured TCP port for one fixture service.""" calls.append(service) return "7442" if service == "Orchid Relay" else "unknown"
tool = FunctionTool.from_defaults(fn=lookup_service_port)answer = llm.predict_and_call( [tool], user_msg=( "Call lookup_service_port for Orchid Relay. " "Return only the tool result." ), error_on_no_tool_call=True, error_on_tool_error=True,)
assert calls == ["Orchid Relay"], callsassert str(answer.response).strip() == "7442", answer.responseprint(answer.response)The function ran once with Orchid Relay and returned 7442 in 5,518
ms. This receipt covers one string parameter and one local function. It does
not prove parallel tools, nested schemas, MCP resources, retries after a tool
error, or a multi-turn tool loop.
Use the GLM-5.2 tool-calling acceptance loop when an application needs the full request → tool execution → tool result → final answer cycle.
Query one document without an embedding dependency
Section titled “Query one document without an embedding dependency”A beginner RAG example often fails for an unrelated reason: VectorStoreIndex
needs an embedding model, and LlamaIndex may fall back to an OpenAI embedding
default if none is configured. GLM-5.2 is the generator in this guide; it is
not being presented as an embedding model.
SummaryIndex provides a smaller acceptance path. It stores the document
nodes and sends the relevant list through the configured LLM without requiring
an embedding service:
from llama_index.core import Document, SummaryIndexfrom glm_llamaindex import llm
document = Document(text=( "Orchid Relay is the internal event bridge. " "Its production TCP port is 7442. " "Cedar mode is disabled during maintenance."))
index = SummaryIndex.from_documents([document])query_engine = index.as_query_engine( llm=llm, response_mode="compact",)answer = query_engine.query( "What production TCP port does Orchid Relay use? " "Return only the number.")
assert str(answer).strip() == "7442", answerassert len(answer.source_nodes) == 1print(answer)The query returned 7442 from one document and one source node in 1,224
ms. That proves LlamaIndex orchestration beyond a direct chat call. It is
not a vector-retrieval benchmark: SummaryIndex can become expensive as the
document set grows because it is designed to synthesize across its nodes.
For production vector RAG, choose and test an explicit embedding model, chunking rule, vector store, metadata filters, top-k value and citation policy. The ColBERT retrieval guide provides a pinned multi-vector example with MaxSim, a tail-truncation negative control, raw index arithmetic and source-preserving context packing. Keep the generator and embedder credentials separate.
Read the four July 29 receipts
Section titled “Read the four July 29 receipts”
Actual test capture generated from the sanitized result JSON. It contains no API key, Authorization header, cookie, response ID, account detail or model reasoning. It is not a Z.ai billing or LlamaIndex product screen.
| Acceptance check | Measured time | Result | Evidence boundary |
|---|---|---|---|
| Exact chat | 3.432 s | LLAMAINDEX_CHAT_OK |
One request; 25 in / 65 completion tokens |
| Stream | 2.691 s | 117 events; LLAMAINDEX_STREAM_OK |
One stream; 25 in / 120 completion tokens |
| Function tool | 5.518 s | One call; 7442 |
One typed string argument and local function |
SummaryIndex |
1.224 s | 7442; one source node |
One tiny document; no embedding model |
These timings are not a speed ranking. The prompts and response paths differ, the account and region are one sample, and no warm-up or percentile run was performed. The value is compatibility evidence: four different LlamaIndex surfaces produced the expected application result.
The full sanitized machine-readable record is available as GLM-5.2 LlamaIndex test data. Use it to compare package versions and usage fields before repeating the test.
Budget from provider usage, not visible characters
Section titled “Budget from provider usage, not visible characters”Z.ai’s pricing page listed GLM-5.2 at $1.40 per million fresh input tokens, $0.26 per million cached input tokens and $4.40 per million output tokens on the test date.
Using fresh-input rates, the two requests with captured usage reconstruct to:
chat = 25 × $1.40 / 1M + 65 × $4.40 / 1M = $0.000321
stream = 25 × $1.40 / 1M + 120 × $4.40 / 1M = $0.000563Those values are arithmetic estimates, not an invoice. The tool and
SummaryIndex wrappers did not expose equivalent usage in our sanitized
receipt, so we do not invent their cost. Caching eligibility, rounding,
account discounts and future prices can also change the bill.
For reusable documents, prompt caching can matter more than the framework choice. The GLM-5.2 prompt-caching guide shows how to distinguish cache eligibility from a confirmed cache hit.
Repair seven LlamaIndex failure modes
Section titled “Repair seven LlamaIndex failure modes”Unknown model appears before the first request
Section titled “Unknown model appears before the first request”Symptom: ValueError: Unknown model 'glm-5.2'.
Cause: the regular OpenAI wrapper tries to resolve the name against its
built-in OpenAI model metadata.
Fix: import OpenAILike from llama_index.llms.openai_like. Keep the real
glm-5.2 model ID and set its metadata explicitly.
The client posts to a completion route
Section titled “The client posts to a completion route”Symptom: a request targets a legacy completion path, returns a route error, or formats chat messages into one prompt.
Cause: OpenAILike defaults is_chat_model to false.
Fix: set is_chat_model=True and run an exact ChatMessage acceptance call.
Do not infer the wire route from the successful constructor.
Long documents hit a 3900-token ceiling
Section titled “Long documents hit a 3900-token ceiling”Symptom: LlamaIndex truncates, repacks or rejects a context far below the model’s documented limit.
Cause: the integration default is 3,900, while GLM-5.2’s official context is 1,048,576.
Fix: set context_window=1_048_576. Then choose a smaller application limit
based on latency, cost and retrieval quality; a model maximum is not a target
for every query.
FunctionTool returns no call
Section titled “FunctionTool returns no call”Symptom: predict_and_call raises for no tool call or the model answers in
plain text.
Cause: function-calling metadata remained false, the tool description was ambiguous, or the requested schema exceeded the tested capability.
Fix: set is_function_calling_model=True, use a typed function with a
specific docstring, require a tool in the acceptance prompt, and validate the
arguments before execution. Test complex schemas separately.
A 401 follows an endpoint swap
Section titled “A 401 follows an endpoint swap”Symptom: a key that works in one Z.ai product returns unauthorized on the other URL.
Cause: general API and Coding Plan credentials, quota and eligibility are separate. A correct protocol shape does not make the products interchangeable.
Fix: pair the general key with https://api.z.ai/api/paas/v4. Do not route
LlamaIndex through Coding Plan unless Z.ai’s current supported-tool policy
allows it.
VectorStoreIndex asks for another provider key
Section titled “VectorStoreIndex asks for another provider key”Symptom: a document example unexpectedly requests OPENAI_API_KEY or fails
while constructing embeddings.
Cause: the vector index needs an embedder, and no explicit embedding model was configured.
Fix: configure a deliberate embedding integration or start with the
embedding-free SummaryIndex acceptance check above. Do not claim GLM-5.2
performed vector embedding when a different service did.
Streaming finishes with no accepted answer
Section titled “Streaming finishes with no accepted answer”Symptom: the generator produced events but the joined text is empty, partial or stopped at the output cap.
Cause: metadata-only deltas, a disconnect, a too-small output budget, or reasoning usage consumed the allowance.
Fix: accumulate only non-empty deltas, retain the final usage and finish metadata, enforce a non-empty acceptance condition, and budget output from observed usage. An event count alone is not success.
Promote the adapter with a versioned acceptance test
Section titled “Promote the adapter with a versioned acceptance test”Before production, turn the four examples into a small CI or release gate:
- pin Python and all three LlamaIndex packages;
- record the exact API base and model ID without the key;
- assert explicit metadata before the first network call;
- require an exact chat marker and non-empty streamed marker;
- execute one real application tool and validate its arguments;
- query a fixture document and require the expected source node;
- archive sanitized latency, usage and package versions;
- fail closed on a changed endpoint, model error, empty stream or missing tool;
- rerun after any LlamaIndex, OpenAI SDK or provider upgrade.
Keep the adapter object local to the component or pass it explicitly to the
query engine. A global Settings.llm can be convenient, but it also makes
tests depend on import order and can hide which model answered a query.
If multi-provider routing is the real requirement, compare this direct path with the tested GLM-5.2 LangChain route guide or the GLM-5.2 API provider map. Framework choice and commercial route are separate architecture decisions.
Audit the LlamaIndex evidence ledger
Section titled “Audit the LlamaIndex evidence ledger”Primary sources checked July 29, 2026:
- Z.ai GLM-5.2 model guide — model ID, base URL example, modalities, context and output limits.
- Z.ai API quick start — general endpoint and the separate Coding Plan route.
- Z.ai Coding Plan supported tools — current eligibility list and protocol endpoints.
- Z.ai GLM-5.2 pricing — fresh input, cached input and output list rates.
- LlamaIndex OpenAI-like package — package purpose, version and Python requirement.
- LlamaIndex OpenAILike source — metadata fields, default context, chat behavior and function-calling flag.
Our reproducible probe is archived under
docs/evidence/glm-5-2-llamaindex-2026-07-29/. The test proves one general
Z.ai account, one package set and four bounded operations on the stated date.
It does not prove every index, embedding model, agent, tool schema, provider
account, region or future release.
