Imported from peonist-ai/halogen-flash-server (
AGENTS.md). Install upstream withnpx skills add peonist-ai/halogen-flash-server. Copyright stays with the author.
AGENTS.md
The short form of this repository for an AI agent that is deploying, driving or debugging halogen-flash-server. README.md is the full account and is canonical wherever the two disagree.
What this is
An OpenAI-compatible server for Qwen3.8-Flash-Next on AMD Strix Halo
(gfx1151), shipped as a container image:
ghcr.io/peonist-ai/halogen-flash-server:<version>. The weights are
peonist-ai/halogen-qwen3.8-flash-next on Hugging Face (118 GiB, tokenizer
included). Native Linux on the amdgpu/KFD stack, kernel 7.0 or newer. WSL2
is not a supported host. One GPU, one model family.
The engine is closed source and is not in this repository. This tree holds the deployment surface only:
| file | what it is |
|---|---|
| README.md | how to run it, what it measures, every design choice a user meets |
| docs/FLAGS.md | every HALOGEN_* variable: default, and whether it changes the output |
| docs/QUANT.md | the precision of every tensor family in the shipped checkpoint |
| docker-compose.yml, deploy/entrypoint.sh | the split topology and the container's startup |
| tools/ | the benchmark scripts the README's numbers come from |
| CHANGELOG.md | what each release changed, with the issue that drove it |
| CONTRIBUTING.md | how to report, and why a diff cannot be merged |
Do not open a pull request. There is no inbound licence for code, and a patch to a deployment tree cannot reach the engine. Send the analysis in an issue: the mechanism, what you measured, what you think the fix is. It is credited by handle in the changelog.
Run it
podman run --rm -p 8731:8731 \
--device /dev/kfd --device /dev/dri --group-add keep-groups \
--ipc=host --ulimit memlock=-1:-1 \
-e HALOGEN_DOWNLOAD=peonist-ai/halogen-qwen3.8-flash-next \
-v ~/halogen-models:/models \
ghcr.io/peonist-ai/halogen-flash-server:0.11.4
- On Docker,
--group-add keep-groupsis--group-add video --group-add render. HALOGEN_DOWNLOADfetches on first start and re-fetches nothing after (except a stale 2.4 GiB sidecar). Unset, the container opens no outbound connection.- If you split the engine and the API into two containers, run both from
the same image tag. Each prints its version on its first log line and
/healthreports both. - The engine's own port (
HALOGEN_PORT, 8730) has no authentication. Keep it unpublished; onlyHALOGEN_API_PORT(8731) is for clients.
Before you change a setting
Everything is an environment variable, read once at startup; the full list with defaults is docs/FLAGS.md. The ones that decide whether it starts and how it behaves:
- The memory knob is
HALOGEN_KV_POOL_POSITIONS, notHALOGEN_KV_SLOTS. Slots share one pool; one slot allocates as much as four. An "out of memory" at startup means the pool did not fit:262144is the small layout,524288the default.HALOGEN_MAX_TOK=16384halves the prefill arena if it still will not start. Never raiseHALOGEN_MAX_TOKto the context. - A request reserves
prompt + max_tokenspositions when admitted and waits in arrival order when the pool cannot hold it. A large default budget costs concurrency. AboveHALOGEN_MAX_TOKENS_CAP(65,536) the answer is a 400, not a truncation. - The server's defaults are what your harness runs at. Coding-agent
harnesses send no thinking control to a custom endpoint, so a request
without one runs at the model's
xhigheffort, and the server closes the think block with room for the answer.HALOGEN_REASONING_EFFORT,HALOGEN_ENABLE_THINKING=0andHALOGEN_MAX_THINKING_TOKENSare the server side; a request that names its own wins. The chat route acceptsreasoning_effort,enable_thinking,max_thinking_tokensand the OpenRouter and Anthropic shapes;/healthlists them undersupported. - The token budget covers thinking too.
finish_reason: "length"means the budget ran out; the default is 8,192, andmax_tokens,max_completion_tokensandmax_output_tokensare the same field. - Images are off until
HALOGEN_VISION_TOWERis set (1finds the sidecar beside the checkpoint). Without it an image is a 400 naming the flag. - The prompt cache is on (
HALOGEN_PROMPT_CACHE=2): a follow-up turn prefills only its new tokens. An answer that resumes from the cache is not always byte-identical to a cold one;=1saves only at fixed checkpoints and is, for evaluation and regression suites.HALOGEN_CACHE_DIRkeeps the cache across a restart. - This server holds most of a 128 GB host. Read the startup line
host memory left for everything elseand believe it:freeandMemAvailableoverstate free memory by about 68 GiB, the size of the locked weights. Another large process beside it, or a pool that leaves under about 10 GiB, turns into minutes-long stalls that look like a hang. The pool is the lever.
Every published number in the README states its conditions (image, flags, concurrency, prompt). Quote them with the number.
Reading the server
- The first log line is the version; the lines before
engine listeningare the prologue: what is loaded, the pool, and the memory arithmetic. GET /healthis the authoritative account of the running build: what it accepts (supported,token_budget_aliases,max_tokens_default, whether images are accepted and why not),versionfor both containers,engine.responds,busy,busy_for_s,in_flight,queued.GET /cache: hits and stores, andpool(waiting_for_room,waiting_s,relocated,cold_resorts).GET /metrics: Prometheus, in llama-server's metric names.- Log lines worth a grep during a problem:
flash_serve: req N prefill P/T tokensandreq N generated K tokens(a long turn's progress),kv pool:(room in the pool, evictions, relocations),lookup table: ... took N s(the table paging in from disk),client disconnected, and theserve_api:line at the end of every request with its timings. - A cancelled request is a closed connection; there is no cancel by id and no response store.
Reporting a problem
What resolves most reports on the first exchange (from CONTRIBUTING.md):
- The image tag, and every
HALOGEN_*variable you set. - The prologue, and the container log around the problem. If the server stopped answering: the last lines it printed before it did.
GET /healthwhile the problem is happening, not after a restart.- What sent the request (which harness, or the raw body), and the
max_tokensit sends. - For a speed report: how many requests were in flight, and whether the number is per stream or aggregate.
Check the CHANGELOG and the open issues first: many reports are a fixed version. An unsupported host (WSL2, a kernel before 7.0, another GPU) is documented, not a bug. Security issues go to the maintainers directly, not to a public issue.