Agent workflows ยท 2026-08-29
Strix LLMTR setup: model prefix, dedupe and the reporting chain
Run the Python-based Strix agent through LLMTR by setting the right environment variables, understanding how the llmtr prefix resolves onto a LiteLLM route, and why finding dedupe pins its own endpoint per call.
What Strix does and what this guide covers
Strix is an autonomous security testing agent written in Python. It dispatches model calls through LiteLLM, so adding a provider is mostly a routing question: which prefix lands on which client, and where the base URL comes from. This guide covers exactly that layer.
Every step below assumes the run is authorised. You need a signed testing agreement, a target list with drawn boundaries and a non-production environment. Without those three, a technically correct model configuration means nothing. The text does not cover detection evasion, mass scanning or unauthorised targeting; it addresses provider routing and model selection only.
- Which branch carries which configuration surface.
- Which value each environment variable actually carries.
- How prefix resolution turns into a LiteLLM route.
- Why finding dedupe pins its own endpoint.
Two branches, two configuration surfaces
The integration has not landed upstream, so none of the behaviour below exists in the tool's published release. The code lives on two separate branches in the knowhycodata/strix repository, and the two do different things.
The documentation branch, docs/add-llmtr-provider, changes no runtime behaviour; it only writes down how to use existing LiteLLM capability. The model value is written with an openai prefix and the base URL is supplied by hand. The native branch, feat/llmtr-native-provider, makes the llmtr prefix first class: the moment the prefix is recognised, the gateway address and attribution headers fall into place, and the user sets only the model name and the key.
In practice the choice comes down to this: three variables on the documentation branch, two on the native branch. A manually supplied base URL wins on either branch, so putting a proxy in front of the gateway does not change the behaviour.
| Branch | How the model value is written | Where the base URL comes from |
|---|---|---|
| docs/add-llmtr-provider | With an openai prefix, e.g. openai/anthropic/claude-sonnet-5 | Set by hand |
| feat/llmtr-native-provider | With an llmtr prefix, e.g. llmtr/anthropic/claude-sonnet-5 | Assigned automatically once the prefix is recognised |
| Both branches | Everything after the prefix is the canonical id | A manually set address always wins |
Setup with environment variables
The documentation branch needs three variables: the model string, the key and the base URL. The key is issued in the dashboard and begins with the llmtr prefix; any other prefix means you copied a different provider's key.
The leading openai segment in the model string is not a duplicated provider. It is the LiteLLM route name that selects the OpenAI-compatible client; everything after it is the canonical id sent to the gateway. Any model in the catalog works the same way, and all you do is put that route name in front of its id.
Attribution headers are optional and supplied as a JSON object applied to every request. Set that variable if you want scans identifiable as Strix in the dashboard; on the native branch the same headers are attached automatically.
Three-variable setup from the documentation branch
export STRIX_LLM="openai/anthropic/claude-sonnet-5"
export LLM_API_KEY="llmtr-your_key"
export LLM_API_BASE="https://llmtr.com/v1"
# Optional: attribution headers so scans are identifiable in the dashboard
export LLM_EXTRA_HEADERS='{"HTTP-Referer":"https://strix.ai","X-Title":"Strix"}'
Prefix resolution: how llmtr becomes a LiteLLM route
On the native branch the model resolver lives in strix/config/models.py. When the prefix is recognised as llmtr, the remaining string is placed behind LiteLLM's OpenAI-compatible route. The nested namespace is preserved, which is why a Turkey-hosted row shows the prefix twice: the first is the route selector, the second is the id's own namespace. That is not a typo.
Recognition is tolerant. An uppercase prefix is accepted, and so is leading or trailing whitespace. By contrast, when another provider's prefix arrives the router does nothing at all: it sets no base URL and adds no header.
The routing configurator does two jobs. If no base URL was set by hand it assigns the gateway root as the LiteLLM default; if one was set it leaves it alone. Attribution headers are merged with existing headers in either case, so scans stay identifiable even behind a proxy.
How the model string turns into a resolved route
STRIX_LLM=llmtr/anthropic/claude-sonnet-5 -> openai/anthropic/claude-sonnet-5
STRIX_LLM=llmtr/openai/gpt-5.5 -> openai/openai/gpt-5.5
STRIX_LLM=llmtr/llmtr/gemma-4 -> openai/llmtr/gemma-4
STRIX_LLM=LLMTR/openai/gpt-5.5 -> openai/openai/gpt-5.5
STRIX_LLM=openrouter/anthropic/claude-sonnet-5 -> untouched, LLMTR routing does not engage
Finding dedupe pins its own endpoint
Strix deduplicates findings before they reach the report, and a separate model can be assigned to that job. It has its own variables for the model, the key and the base URL, and the dedupe request carries those values as per-call extra arguments.
The subtlety is this: LiteLLM's global base URL default is derived from the main model. If the main model runs on a different provider, that default is wrong for the dedupe model and the request never reaches the gateway. So when the dedupe model carries the llmtr prefix and no address was set by hand, the gateway address is pinned onto the request itself.
The rule is clean in both directions: an explicitly set dedupe address always wins, and no address is injected for a dedupe model without the llmtr prefix. That makes running the main model and the dedupe model on different providers a supported setup rather than an accident.
- The main model and the dedupe model may live on different providers, each with its own key.
- Set a dedupe base URL by hand and the gateway default never engages.
- No address injection happens at all when the dedupe model lacks the llmtr prefix.
- Recording which model deduplicated which finding makes later review far easier.
Turkey-hosted rows in the docs and tool-call fitness
The documentation branch lists two sets: frontier models and Turkey-hosted rows. The benefits section on the same page states that Strix relies on native tool calls. Read together, those two statements produce a filter, because not every listed row suits an agent loop.
The tool-call flag is measured per model in the catalog rather than copied across a family. The table below shows where the Turkey-hosted rows named in the docs stand today. A row without tool calling is still usable for summarisation or text generation, but it is the wrong pick for a loop that calls tools.
| Model id | Tool calling | Use in an agent loop |
|---|---|---|
| llmtr/gemma-4 | Yes | Suitable, also supports image input |
| llmtr/qwen3-6-35b | Yes | Suitable for a text-only loop |
| llmtr/muse-glimmer-30b-tr | Yes | Suitable, tool calling and image input together |
| llmtr/trendyol-asure-12b | No | Listed in the docs, should not drive a tool-calling loop |
Reporting chain, verification and what the branches do not cover
Request headers are built from the model name: attribution headers are added when the id carries the llmtr prefix, and headers you define yourself merge afterwards, so your value is preserved. The frontier-model check also accepts llmtr-prefixed ids, so a model is not discarded as unknown merely because of the prefix.
Three things fall outside these branches, and stating that is better than inventing it. The install command, the isolated environment the agent runs in, and the report file format are not touched here; the diffs change model routing, request headers and the dedupe endpoint only. The tool's own installation documentation remains the authority on those.
- First check: confirm which route the model string resolves onto.
- Second check: send one short request, and inspect the key prefix if authentication fails.
- Third check: if a dedupe model is configured, exercise it with its own request.
- An id that is not in canonical form cannot be matched; copy the spelling from the catalog exactly.
Frequently asked questions
Why does the openai prefix appear twice in the model string?
The leading segment is the LiteLLM route name that selects the OpenAI-compatible client, and the second part is the namespace of the canonical id sent to the gateway. For frontier models the two differ, while Turkey-hosted rows repeat the same word twice. That is expected behaviour.
Can the main model and the dedupe model use different providers?
Yes. Dedupe accepts its own model, key and base URL. When the dedupe model carries the llmtr prefix and no address is set by hand, the gateway address is pinned onto that request, so it works independently of whichever provider serves the main model.
I cannot find an LLMTR option in the published Strix release. Why?
The integration has not landed upstream. The documentation surface sits on the docs/add-llmtr-provider branch of the knowhycodata/strix repository, and prefix resolution on feat/llmtr-native-provider. The three-variable setup from the documentation branch still works on a release without prefix support, because it uses existing LiteLLM behaviour.
In which environment should this setup be used?
Only in an authorised test. A signed testing agreement, a target list with drawn boundaries and a non-production environment are preconditions. This guide covers provider routing; target selection, detection evasion and mass scanning are out of scope.