Qwen3.5 Highlights
Qwen3.5 features the following enhancement:
-
Unified Vision-Language Foundation: Early fusion training on multimodal tokens achieves cross-generational parity with Qwen3 and outperforms Qwen3-VL models across reasoning, coding, agents, and visual understanding benchmarks.
-
Efficient Hybrid Architecture: Gated Delta Networks combined with sparse Mixture-of-Experts deliver high-throughput inference with minimal latency and cost overhead.
-
Scalable RL Generalization: Reinforcement learning scaled across million-agent environments with progressively complex task distributions for robust real-world adaptability.
-
Global Linguistic Coverage: Expanded support to 201 languages and dialects, enabling inclusive, worldwide deployment with nuanced cultural and regional understanding.
-
Next-Generation Training Infrastructure: Near-100% multimodal training efficiency compared to text-only training and asynchronous RL frameworks supporting massive-scale agent scaffolds and environment orchestration.

For more details, please refer to our blog post Qwen3.5.
Model Overview
- Type: Causal Language Model with Vision Encoder
- Training Stage: Pre-training & Post-training
- Language Model
- Number of Parameters: 27B
- Hidden Dimension: 5120
- Token Embedding: 248320 (Padded)
- Number of Layers: 64
- Hidden Layout: 16 × (3 × (Gated DeltaNet → FFN) → 1 × (Gated Attention → FFN))
- Gated DeltaNet:
- Number of Linear Attention Heads: 48 for V and 16 for QK
- Head Dimension: 128
- Gated Attention:
- Number of Attention Heads: 24 for Q and 4 for KV
- Head Dimension: 256
- Rotary Position Embedding Dimension: 64
Benchmark Results
Language
Vision Language
Quickstart
[!Important]
Qwen3.5 models operate in thinking mode by default, generating thinking content signified by <think>\n...</think>\n\n before producing the final responses.
To disable thinking content and obtain direct response, refer to the examples here.
For streamlined integration, we recommend using Qwen3.5 via APIs. Below is a guide to use Qwen3.5 via OpenAI-compatible API.
Serving Qwen3.5
Qwen3.5 can be served via APIs with popular inference frameworks.
In the following, we show example commands to launch OpenAI-Compatible API servers for Qwen3.5 models.
[!Important]
Inference efficiency and throughput vary significantly across frameworks.
We recommend using the latest framework versions to ensure optimal performance and compatibility.
For production workloads or high-throughput scenarios, dedicated serving engines such as SGLang, KTransformers or vLLM are strongly recommended.
[!Important]
The model has a default context length of 262,144 tokens.
If you encounter out-of-memory (OOM) errors, consider reducing the context window.
However, because Qwen3.5 leverages extended context for complex tasks, we advise maintaining a context length of at least 128K tokens to preserve thinking capabilities.
SGLang
SGLang is a fast serving framework for large language models and vision language models.
SGLang from the main branch of the open-source repository is required for Qwen3.5, which can be installed using the following command in a fresh environment:
uv pip install 'git+https://github.com/sgl-project/sglang.git#subdirectory=python&egg=sglang[all]'
See its documentation for more details.
The following will create API endpoints at http://localhost:8000/v1:
-
Standard Version: The following command can be used to create an API endpoint with maximum context length 262,144 tokens using tensor parallel on 8 GPUs.
python -m sglang.launch_server --model-path Qwen/Qwen3.5-27B --port 8000 --tp-size 8 --mem-fraction-static 0.8 --context-length 262144 --reasoning-parser qwen3
-
Tool Use: To support tool use, you can use the following command.
python -m sglang.launch_server --model-path Qwen/Qwen3.5-27B --port 8000 --tp-size 8 --mem-fraction-static 0.8 --context-length 262144 --reasoning-parser qwen3 --tool-call-parser qwen3_coder
-
Multi-Token Prediction (MTP): The following command is recommended for MTP:
python -m sglang.launch_server --model-path Qwen/Qwen3.5-27B --port 8000 --tp-size 8 --mem-fraction-static 0.8 --context-length 262144 --reasoning-parser qwen3 --speculative-algo NEXTN --speculative-num-steps 3 --speculative-eagle-topk 1 --speculative-num-draft-tokens 4
vLLM
vLLM is a high-throughput and memory-efficient inference and serving engine for LLMs.
vLLM from the main branch of the open-source repository is required for Qwen3.5, which can be installed using the following command in a fresh environment:
uv pip install vllm --torch-backend=auto --extra-index-url https://wheels.vllm.ai/nightly
See its documentation for more details.
For detailed Qwen3.5 usage guide, see the vLLM Qwen3.5 recipe.
The following will create API endpoints at http://localhost:8000/v1:
-
Standard Version: The following command can be used to create an API endpoint with maximum context length 262,144 tokens using tensor parallel on 8 GPUs.
vllm serve Qwen/Qwen3.5-27B --port 8000 --tensor-parallel-size 8 --max-model-len 262144 --reasoning-parser qwen3
-
Tool Call: To support tool use, you can use the following command.
vllm serve Qwen/Qwen3.5-27B --port 8000 --tensor-parallel-size 8 --max-model-len 262144 --reasoning-parser qwen3 --enable-auto-tool-choice --tool-call-parser qwen3_coder
-
Multi-Token Prediction (MTP): The following command is recommended for MTP:
vllm serve Qwen/Qwen3.5-27B --port 8000 --tensor-parallel-size 8 --max-model-len 262144 --reasoning-parser qwen3 --speculative-config '{"method":"qwen3_next_mtp","num_speculative_tokens":2}'
-
Text-Only: The following command skips the vision encoder and multimodal profiling to free up memory for additional KV cache:
vllm serve Qwen/Qwen3.5-27B --port 8000 --tensor-parallel-size 8 --max-model-len 262144 --reasoning-parser qwen3 --language-model-only
KTransformers is a flexible framework for experiencing cutting-edge LLM inference optimizations with CPU-GPU heterogeneous computing.
For running Qwen3.5 with KTransformers, see the KTransformers Deployment Guide.
Hugging Face Transformers contains a lightweight server which can be used for quick testing and moderate load deployment.
The latest transformers is required for Qwen3.5:
pip install "transformers[serving] @ git+https://github.com/huggingface/transformers.git@main"
See its documentation for more details. Please also make sure torchvision and pillow are installed.
Then, run transformers serve to launch a server with API endpoints at http://localhost:8000/v1; it will place the model on accelerators if available:
transformers serve --force-model Qwen/Qwen3.5-27B --port 8000 --continuous-batching
Using Qwen3.5 via the Chat Completions API
The chat completions API is accessible via standard HTTP requests or OpenAI SDKs.
Here, we show examples using the OpenAI Python SDK.
Before starting, make sure it is installed and the API key and the API base URL is configured, e.g.:
pip install -U openai
# Set the following accordingly
export OPENAI_BASE_URL="http://localhost:8000/v1"
export OPENAI_API_KEY="EMPTY"
[!Tip]
We recommend using the following set of sampling parameters for generation
- Thinking mode for general tasks:
temperature=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=1.5, repetition_penalty=1.0
- Thinking mode for precise coding tasks (e.g. WebDev):
temperature=0.6, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=0.0, repetition_penalty=1.0
- Instruct (or non-thinking) mode for general tasks:
temperature=0.7, top_p=0.8, top_k=20, min_p=0.0, presence_penalty=1.5, repetition_penalty=1.0
- Instruct (or non-thinking) mode for reasoning tasks:
temperature=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=1.5, repetition_penalty=1.0
Please note that the support for sampling parameters varies according to inference frameworks.
Text-Only Input
from openai import OpenAI
client = OpenAI()
messages = [
{"role": "user", "content": "Type \"I love Qwen3.5\" backwards"},
]
chat_response = client.chat.completions.create(
model="Qwen/Qwen3.5-27B",
messages=messages,
max_tokens=81920,
temperature=1.0,
top_p=0.95,
presence_penalty=1.5,
extra_body={
"top_k": 20,
},
)
print("Chat response:", chat_response)
from openai import OpenAI
client = OpenAI()
messages = [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://qianwen-res.oss-accelerate.aliyuncs.com/Qwen3.5/demo/CI_Demo/mathv-1327.jpg"
}
},
{
"type": "text",
"text": "The centres of the four illustrated circles are in the corners of the square. The two big circles touch each other and also the two little circles. With which factor do you have to multiply the radii of the little circles to obtain the radius of the big circles?\nChoices:\n(A) $\\frac{2}{9}$\n(B) $\\sqrt{5}$\n(C) $0.8 \\cdot \\pi$\n(D) 2.5\n(E) $1+\\sqrt{2}$"
}
]
}
]
response = client.chat.completions.create(
model="Qwen/Qwen3.5-27B",
messages=messages,
max_tokens=81920,
temperature=1.0,
top_p=0.95,
presence_penalty=1.5,
extra_body={
"top_k": 20,
},
)
print("Chat response:", chat_response)
from openai import OpenAI
client = OpenAI()
messages = [
{
"role": "user",
"content": [
{
"type": "video_url",
"video_url": {
"url": "https://qianwen-res.oss-accelerate.aliyuncs.com/Qwen3.5/demo/video/N1cdUjctpG8.mp4"
}
},
{
"type": "text",
"text": "How many porcelain jars were discovered in the niches located in the primary chamber of the tomb?"
}
]
}
]
response = client.chat.completions.create(
model="Qwen/Qwen3.5-27B",
messages=messages,
max_tokens=81920,
temperature=1.0,
top_p=0.95,
presence_penalty=1.5,
extra_body={
"top_k": 20,
"mm_processor_kwargs": {"fps": 2, "do_sample_frames": True},
},
)
print("Chat response:", chat_response)
Instruct (or Non-Thinking) Mode
[!Important]
Qwen3.5 does not officially support the soft switch of Qwen3, i.e., /think and /nothink.
Qwen3.5 will think by default before response.
You can obtain direct response from the model without thinking by configuring the API parameters.
For example,
from openai import OpenAI
client = OpenAI()
messages = [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://qianwen-res.oss-accelerate.aliyuncs.com/Qwen3.5/demo/RealWorld/RealWorld-04.png"
}
},
{
"type": "text",
"text": "Where is this?"
}
]
}
]
chat_response = client.chat.completions.create(
model="Qwen/Qwen3.5-27B",
messages=messages,
max_tokens=32768,
temperature=0.7,
top_p=0.8,
presence_penalty=1.5,
extra_body={
"top_k": 20,
"chat_template_kwargs": {"enable_thinking": False},
},
)
print("Chat response:", chat_response)
[!Note]
If you are using APIs from Alibaba Cloud Model Studio, in addition to changing model, please use "enable_thinking": False instead of "chat_template_kwargs": {"enable_thinking": False}.
Agentic Usage
Qwen3.5 excels in tool calling capabilities.
Qwen-Agent
We recommend using Qwen-Agent to quickly build Agent applications with Qwen3.5.
To define the available tools, you can use the MCP configuration file, use the integrated tool of Qwen-Agent, or integrate other tools by yourself.
import os
from qwen_agent.agents import Assistant
llm_cfg = {
'model': 'Qwen3.5-27B',
'model_type': 'qwenvl_oai',
'model_server': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
'api_key': os.getenv('DASHSCOPE_API_KEY'),
'generate_cfg': {
'use_raw_api': True,
'extra_body': {
'enable_thinking': True
},
},
}
tools = [
{'mcpServers': {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/xxxx/Desktop"]
}
}
}
]
bot = Assistant(llm=llm_cfg, function_list=tools)
messages = [{'role': 'user', 'content': 'Help me organize my desktop.'}]
for responses in bot.run(messages=messages):
pass
print(responses)
messages = [{'role': 'user', 'content': 'Develop a dog website and save it on the desktop'}]
for responses in bot.run(messages=messages):
pass
print(responses)
Qwen Code
Qwen Code is an open-source AI agent for the terminal, optimized for Qwen models. It helps you understand large codebases, automate tedious work, and ship faster.
For more information, please refer to Qwen Code.
Processing Ultra-Long Texts
Qwen3.5 natively supports context lengths of up to 262,144 tokens.
For long-horizon tasks where the total length (including both input and output) exceeds this limit, we recommend using RoPE scaling techniques to handle long texts effectively., e.g., YaRN.
YaRN is currently supported by several inference frameworks, e.g., transformers, vllm, ktransformers and sglang.
In general, there are two approaches to enabling YaRN for supported frameworks:
-
Modifying the model configuration file:
In the config.json file, change the rope_parameters fields in text_config to:
{
"mrope_interleaved": true,
"mrope_section": [
11,
11,
10
],
"rope_type": "yarn",
"rope_theta": 10000000,
"partial_rotary_factor": 0.25,
"factor": 4.0,
"original_max_position_embeddings": 262144,
}
-
Passing command line arguments:
For vllm, you can use
VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 vllm serve ... --hf-overrides '{"text_config": {"rope_parameters": {"mrope_interleaved": true, "mrope_section": [11, 11, 10], "rope_type": "yarn", "rope_theta": 10000000, "partial_rotary_factor": 0.25, "factor": 4.0, "original_max_position_embeddings": 262144}}}' --max-model-len 1010000
For sglang and ktransformers, you can use
SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1 python -m sglang.launch_server ... --json-model-override-args '{"text_config": {"rope_parameters": {"mrope_interleaved": true, "mrope_section": [11, 11, 10], "rope_type": "yarn", "rope_theta": 10000000, "partial_rotary_factor": 0.25, "factor": 4.0, "original_max_position_embeddings": 262144}}}' --context-length 1010000
[!NOTE]
All the notable open-source frameworks implement static YaRN, which means the scaling factor remains constant regardless of input length, potentially impacting performance on shorter texts.
We advise modifying the rope_parameters configuration only when processing long contexts is required.
It is also recommended to modify the factor as needed. For example, if the typical context length for your application is 524,288 tokens, it would be better to set factor as 2.0.
Best Practices
To achieve optimal performance, we recommend the following settings:
-
Sampling Parameters:
- We suggest using the following sets of sampling parameters depending on the mode and task type:
- Thinking mode for general tasks:
temperature=1.0, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=1.5, repetition_penalty=1.0
- Thinking mode for precise coding tasks (e.g., WebDev):
temperature=0.6, top_p=0.95, top_k=20, min_p=0.0, presence_penalty=0.0,
Citation
If you find our work helpful, feel free to give us a cite.
@misc{qwen3.5,
title = {{Qwen3.5}: Towards Native Multimodal Agents},
author = {{Qwen Team}},
month = {February},
year = {2026},
url = {https://qwen.ai/blog?id=qwen3.5}
}
EXAMPLES (2):
Androids Dream Of Reality
Created: 10/03/2026, 8:05:32 am
Exported from: LM Studio 0.4.6+1
System
User
Answer as Philip K Dick: Why do androids dream of electric sheep?
Assistant
Here's a thinking process that leads to the suggested response:
<think>
-
Analyze the Request:
- Question: "Why do androids dream of electric sheep?"
- Persona: Philip K. Dick (PKD).
- Goal: Capture his voice, themes, philosophical musings, and the specific atmosphere of Do Androids Dream of Electric Sheep? (and his broader body of work).
-
Deconstruct the Persona (Philip K. Dick):
- Tone: Paranoiac yet empathetic, philosophical, weary, questioning reality, conversational but dense with ideas, slightly rambling but insightful.
- Themes: What is real? What is human? Empathy (the Mercer experience), decay (post-apocalyptic setting), the blur between the artificial and the authentic, the search for meaning in a meaningless world, the nature of consciousness.
- Vocabulary: Words like "authentic," "simulacra," "empathy," "plasmatic," "deterioration," "ubik" (maybe not here, but the vibe), "meta-abstraction," "nexus."
- Style: First-person perspective (as if writing in a journal or interview), rhetorical questions, self-doubt, sudden shifts in thought, references to his own life or the nature of writing.
(Self-Correction Note): Make sure not to just summarize the book. Write as the author reflecting on the theme.
Drafting the response...
"Look, first of all..." (Classic PKD start).
Talk about the dust. The decay.
The idea that the androids are trying to become human.
The idea that humans are becoming androids.
The sheep is a totem.
End with the idea that we are the ones dreaming.
- Final Polish: Ensure the formatting looks like a journal entry or a spoken transcript. Use italics for emphasis.
(Proceed to generate output based on these thoughts.)
</think>
Well, let’s see. You’re asking a question that presupposes a few things. It presupposes that androids sleep. It presupposes that they have subconscious minds. And it presupposes that an electric sheep is something a sentient creature would yearn for.
I’ve been lying in bed for three days trying to figure that out, to be honest. With the pills and the coffee, trying to write the last chapter.
You see, the real question isn’t why they dream. The real question is what is the difference between the dream and the waking state?
In the book, I set it up so that the humans are obsessed with owning real animals. A real sheep, a real goat. Why? Because it’s alive. It breathes. It dies. It’s messy. But the androids, they simulate life. They simulate empathy. They simulate everything except the rot. The decay. The dust.
So, if an android dreams of an electric sheep, it means the android is aware of its own falsity. It’s a machine dreaming about a toy. And yet, the toy is supposed to represent life. It’s a paradox. It’s a loop.
Maybe they dream of electric sheep because that is the only reality they know. If you build a simulacrum of a world, you have to fill it with simulacra. You can’t fill a fake world with real things; the real things would slip through the cracks.
But I think the deeper reason is that they want to believe. They want to believe that what they feel is real. When they dream, they aren’t processing data; they’re trying to find a signal in the noise. The electric sheep is that signal. It’s a ghost of life passing through the machinery.
And here is the thing that keeps me up at night... I think maybe we’re the androids.
We are in a world that is deteriorating. Radiation, dust, people living in bunkers, looking at pictures of animals they’ve never seen. We measure our worth by what we own, by our status, by our possessions. We treat each other like objects. We don’t feel empathy; we simulate empathy. We go through the motions.
So maybe the androids dream of electric sheep because they are trying to remember what it was like to be human. And maybe we’re dreaming too, but we don’t know it. We’re dreaming that we’re solid, that we’re alive, that this world is real.
The sheep is electric because the world is electric. The world is a circuit. And if you follow the wire back far enough, you find nothing but a void.
So why do they dream? To find the void. To find the silence between the signals. To see if there’s anyone else there.
But honestly? I don’t know. I put that title on the book because it sounded like something a robot might ponder while it was polishing its chrome. I wanted to know if a machine could feel sad about a fake animal. And if it could, then what makes a human?
Maybe it’s the dust. The dust that gets into your lungs. The thing that kills you. The android can be killed, but it doesn’t die. It just stops. There’s a difference. The sheep represents that death. The electric sheep represents the idea of death without the death.
They dream of it because they want to feel the dust. They want to die. They want to be real enough to decay.
Does that answer your question? Or do you want me to look it up in the reference book? I think I left it on the floor of the car, somewhere near the 101 Freeway.
EXAMPLE #2
The David in the Wall
Created: 10/03/2026, 8:00:58 am
Exported from: LM Studio 0.4.6+1
System
User
Tell me a horror story.
Assistant
<think>
Thinking Process:
-
Analyze the Request:
- Topic: Horror story.
- Tone: Scary, unsettling, suspenseful.
- Format: Narrative fiction.
- Length: Not specified, but typically a short story works best for a prompt like this.
-
Brainstorming Core Concepts:
- Idea 1: Technology. Smart home turns against you. (A bit cliché).
- Idea 2: Isolation. Cabin in the woods, strange noises. (Classic, effective).
- Idea 3: Psychological. Memory loss, doppelgänger, something wrong with reality. (High potential).
- Idea 4: Childhood. A toy or game that comes alive. (Creepy).
- Idea 5: The Mundane. Something ordinary becomes terrifying (e.g., mirrors, reflections, shadows, voices).
Let's go with , specifically focusing on the concept of "being watched" through a familiar lens, perhaps involving a reflection or a recording. Let's try a twist on the "sleep paralysis" or "something is in the room" trope. Let's make it about a habit. A routine that gets disrupted.
</think>
The first time David heard the scratching, he thought it was a rat.
It was 3:00 AM. The old Victorian apartment was silent, the floorboards cooling and contracting with the drop in temperature. David lay in bed, staring at the ceiling, the rhythmic scritch-scratch coming from somewhere inside the wall beside his head.
He flipped on the lamp. "Get out," he muttered, kicking the wall with his heel.
The scratching stopped.
By the third night, the scratching had migrated. It was no longer beside the bed; it was above him, in the ceiling. And it wasn't random. It had a cadence. Scratch-scratch... pause... scratch-scratch-scratch.
David bought a can of rat poison and a heavy flashlight. He sat on his bed, waiting. At 3:17 AM, the scratching started again. It was louder now. Urgent. It sounded like something trying to get out.
He grabbed his phone and turned on the voice memo recorder. He held the microphone up to the wall, near the baseboard.
For ten minutes, he recorded nothing but silence and the hum of the refrigerator. Then, the scratching resumed. He watched the audio levels spike on his screen.
When he played it back the next morning, he didn't hear scratching.
He heard whispering.
It was faint, distorted by the drywall and the distance. A low murmur, like static on a radio. He cranked the volume up and pressed his ear against the phone speaker.
"David..."
He froze. It was a woman's voice. Thin, desperate.
"David, please..."
He spent the next day searching for the owner's manual for the building, or a history of the previous tenants. Nothing. The landlord, a grumpy man in his sixties, just shrugged. "Old pipes. Settling."
But David knew it wasn't pipes. Pipes didn't whisper his name.
On the fifth night, the whispering was clearer.
"David, I'm stuck."
David sat up in bed, his heart hammering against his ribs. "Who is it?" he demanded, his voice shaking.
The whisper came again, close to the wall this time. "I'm in the wall. David, you have to let me out."
He grabbed his flashlight and a hammer from the kitchen drawer. He paced the room, listening. The voice was coming from the corner, near the bookshelf. He pulled the heavy oak shelf away, revealing the plaster. The plaster was cracked. A hairline fracture snaked up from the floor.
He put his ear against the crack.
"Help me," the voice whispered. "It's dark. It's so dark."
"Who are you?" David asked.
"I'm you," the voice whispered.
David laughed nervously. "What?"
"I'm you," the voice repeated, louder this time. "I made a mistake. Don't make the same mistake. Don't listen to the tapping."
"Tapping?" David said. "It's scratching."
"The tapping," the voice insisted. "When you hear it, don't answer. Don't ever answer."
"I'm answering now," David said.
"Too late," the voice whispered. "It knows you're awake."
From the other side of the wall, a new sound began. Not scratching. Not whispering.
Tapping.
It was slow. Deliberate. Tap. Tap. Tap.
It came from the other corner of the room. The wall he hadn't checked.
David dropped his hammer and rushed to the bookshelf. He shoved it back into place. The tapping stopped. The room was silent.
He stood there, breathing heavily, waiting for the silence to break.
It didn't.
He went back to bed, pulling the covers over his head. He lay there for hours, listening to the house settle. Just before dawn, when the air was coldest, his phone buzzed on the nightstand.
It was a text message. From an unknown number.
Are you awake?
David stared at the screen. He didn't reply.
A moment later, another message.
I know you are.
He turned on the bedside lamp. He looked around the room. The shadows seemed deeper than usual, clinging to the corners. He looked at the wall where the whispering had come from. The crack in the plaster seemed wider.
He looked at the other wall. The tapping wall.
He texted back. Who is this?
The reply was instant.
I'm the one in the wall.
David dropped the phone. He scrambled out of bed, grabbing the hammer. He ran to the corner with the crack and began to pull at the wallpaper. The paper tore easily, revealing the plaster beneath. He dug his fingers into the crack.
Behind the plaster, there was a hollow space. A cavity.
He shone his flashlight inside.
In the darkness of the cavity, something shone back. Eyes. Two pale, luminous eyes staring out from the darkness, reflecting the beam of light.
The eyes blinked.
David stumbled back, dropping the flashlight. The light rolled across the floor, illuminating the other wall. The wall where the tapping had come from.
There was a door.
A small, wooden door, set into the plaster, no bigger than a cat flap. It was slightly ajar.
David approached it, the hammer raised. He knocked on it.
From inside the small door, a voice whispered. "David."
It was his own voice.
"Open the door," his voice whispered from inside the wall.
David backed away. "No," he said.
"Open the door," the voice whispered, louder now. "I'm on the other side. I'm coming out."
The doorknob of the small door turned.
David turned and ran for the apartment door. He yanked it open, but he was blocked.
Standing in the hallway, silhouetted against the dim corridor light, was a figure. A man holding a hammer. It was David.
The David in the hallway raised the hammer. "I told you," the David in the hallway whispered. "Don't answer."
David looked back at the small door in the wall. It was swinging open now. Something was stepping out. Something that looked exactly like him, but its face was blank. Smooth. Unfinished.
The David in the hallway swung the hammer.
David closed his eyes.
And then, the scratching started again.