cd /news/developer-tools/wiring-a-model-into-soloncode-dialec… · home topics developer-tools article
[ARTICLE · art-85299] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Wiring a Model into SolonCode: Dialects, the apiUrl Rules, and the Timeouts Nobody Warns You About

SolonCode, a coding assistant built on Solon AI, ships without a bundled model, requiring users to wire one up manually. The project supports seven chat dialects—including OpenAI, Ollama, Gemini, and Anthropic—detected via the 'standard' field or the shape of the apiUrl, with OpenAI-compatible endpoints recommended for fastest setup. Key configuration fields include apiUrl, apiKey, model, timeout, and contextLength, with a 60-second default timeout that often needs adjustment for long tool-calling sessions.

read11 min views1 publishedAug 3, 2026

SolonCode ships with no model. That is a deliberate product choice, not an omission: no bundled provider, no default key, no telemetry-backed endpoint you did not ask for. The upside is you can point it at DeepSeek, a local Ollama box, or an air-gapped corporate gateway with equal ease. The downside is that installing the binary does not give you a working assistant. You have to wire a model up first, and that is where most first-time users stall.

This is the follow-up to getting SolonCode installed. Here we get one model connected and stable — meaning it survives long tool-calling sessions, weak networks, and multi-file refactors without mysterious mid-task failures.

You can hand-edit settings.json

. You should not, at least not on day one. The settings page validates your input and gives you a Test connection button, which is the single most useful debugging affordance in the whole product.

soloncode web        # default port 4808
soloncode web 0      # pick any free port
soloncode web 1212   # explicit port

Then go to Settings → LLM, add a model, and hit test. Do not skip the test. A green test is the boundary between "config problem" and "everything else."

If the port is taken, soloncode web 0

sidesteps it. That is the official answer too.

This is the part that saves the most time. SolonCode sits on Solon AI, and Solon AI does not have a list of supported vendors. It has a list of supported chat dialects — request/response shapes. Any service that speaks one of those shapes works.

The built-in dialects and how they are detected:

Dialect Detected by
openai
default, or apiUrl ending in .../chat/completions
openai-responses
standard=openai-responses , or apiUrl ending in .../v1/responses
ollama
standard=ollama
gemini
standard=gemini , or apiUrl matching .../v1beta/models/* (usable since v3.8.1)
gemini-interactions
standard=gemini-interactions , or .../v1beta/interactions/* (usable since v4.0.3)
anthropic
standard=anthropic , or apiUrl ending in .../v1/messages (usable since v3.9.1)
dashscope
standard=dashscope , or apiUrl matching .../v1/services/*

ChatConfig

picks the dialect from either standard

or the shape of apiUrl

. So the question is never "does SolonCode support vendor X" — it is "which of these seven shapes does vendor X's endpoint speak."

Two useful notes straight from the docs: Claude also offers an OpenAI-compatible mode, so you can run it through the openai

dialect instead of anthropic

. Alibaba's Bailian exposes both its native DashScope protocol and an OpenAI-compatible one. When a provider gives you both, the OpenAI-compatible endpoint is almost always the faster path to a green test.

apiUrl

Underneath, a model entry maps to Solon AI's ChatConfig

:

Field Required Notes
apiUrl
yes the endpoint address
apiKey
depends token; may be empty for unauthenticated local services
model
yes the API model id, not the console display name
standard
no interface spec; defaults to openai
timeout
no
Duration , defaults to 60s
headers
no extra headers — other options are all passed as headers
proxy
no network proxy
contextLength
no model context length; the docs flag this one as important
defaultAutoToolCall
no defaults to true , since v3.8.4

There is also provider

, which served the role of standard

before v4.0. If you are reading an old config, that is what it is.

Now the apiUrl

rules, which are where the real failures live:

/chat/completions

or /api/chat

) and the dialect is inferred from the tail.standard

#

#

onward is stripped.One honest wrinkle: the ChatConfig

reference describes apiUrl

as "the full address, not a baseUrl," while the dialect page explicitly supports baseUrl + standard

. Both statements are in the official docs. My practical read: paste the full address. It removes a whole class of ambiguity, and the #

rule exists precisely for the cases where appending would break you.

Field shapes are stable. Hostnames and model ids are not — providers rename models and retire old ones. Always confirm the current id in the vendor console, and never put a real key in a doc, a screenshot, or a commit.

A cloud provider over an OpenAI-compatible endpoint — the common case, and the one to start with:

apiUrl: "https://api.example.com/v1/chat/completions"
apiKey: "sk-xxxxxx"
model: "<copy the exact id from the console>"
timeout: "180s"

Find the "OpenAI compatible" base URL in your provider's console, leave standard

at its default, and copy the model id rather than typing it from memory. The console's display name is frequently not the API id.

A local Ollama instance, from the official example:

ChatModel chatModel = ChatModel.of("http://127.0.0.1:11434/api/chat")
        .standard("ollama")
        .model("llama3.2")
        .build();

The model

value is whatever you pulled — if you ran ollama run deepseek-r1:7b

, you write deepseek-r1:7b

. Note that the dialect table lists only standard=ollama

as the detection rule; the /api/chat

tail-matching behavior appears in the dialect's source, not the table. Declaring standard

explicitly is the safe move.

Also worth setting expectations: a small local model that connects fine may still be unreliable at multi-file refactors and long tool chains. That is a capability ceiling, not a config bug.

A corporate gateway. Fill apiUrl

per the gateway's own docs, put tenant or custom auth headers in headers

, use the model names from the gateway's allow-list rather than the public cloud names, and if the gateway path is unusual, apply the #

suffix. Keep this one in the workspace scope so a client-specific gateway does not leak into every other project on your machine.

Settings persist to settings.json

in one of two places:

Scope Path Good for
user ~/.soloncode/settings.json
models, skill pool, and MCP servers shared across projects
workspace .soloncode/settings.json
models, APIs, LSP, and mounts for this project only

The merge order is documented plainly: the user-level file is read first, then the workspace file, and workspace config overrides or supplements user config. Saving from the settings page tries to write into the running engine, so a restart is often unnecessary — the docs say "not necessarily," so if your model list does not refresh, restarting the web process is the cheap fix.

Practical split: your personal default model goes global; anything client- or gateway-specific goes workspace.

If .soloncode/settings.json

holds a real key, it does not belong in version control:

.soloncode/settings.json
.soloncode/logs/

Ship a settings.example.json

with placeholder values instead, and let people copy it locally.

One exposure path deserves explicit attention: if you bind the web UI to anything beyond localhost, set webAuthUser and webAuthPass. Leave them blank and authentication is off. An unauthenticated SolonCode web endpoint on your LAN hands over your conversations, your tool permissions, and — since the keys live in the settings file it manages — effectively your API credentials. Sandboxing (

sandboxMode

, sandboxAllowUserHome

, both default true

) and human-in-the-loop review are a separate line of defense. Getting a model connected is not a reason to switch either of them off.A coding agent makes many round trips per task, each carrying context and tool descriptions. So connectivity is necessary but not sufficient. The general settings that govern stability, with their documented defaults:

Setting Default What it controls
apiRetries
3 API retry count
modelRetries
3 model retry count
mcpRetries
3 MCP retry count
maxTurns
20 max rounds in a single task
autoRethink
true allow self-reflection retries
logLevel
INFO TRACE / DEBUG / INFO / WARN / ERROR
logMaxHistory
7 days of log archives kept

Retries help with flaky networks and nothing else. A 401 or a wrong model id will fail identically three times and just triple your log volume.

That 60-second timeout

default deserves a second look. For plain chat it is fine. For a reasoning model chewing on a long context behind a slow proxy, it is easy to hit. Raising it is reasonable; raising it to effectively-infinite is not, because an invisible hang is harder to diagnose than a fast failure.

Long tasks accumulate conversation turns and tool results. Compression summarizes older content to relieve context pressure. Two settings and a naming caveat:

compressionThresholdPercent

defaults to 75 — compression triggers when 75% of the context window is used. Both doc pages agree on this one.

The message-count trigger defaults to 100, but appears under two different names in the docs: the settings reference calls it summaryWindowSize

, while the compression guide calls it compressionThresholdMessages

. Similarly, sessionWindowSize

(how many recent messages a new instruction carries) is documented as 8 on one page and 12 on the other. I am not going to guess which is authoritative — check what your settings page actually shows and treat that as truth for your version.

The official tuning ranges, by model context window:

Context Message threshold Percent threshold Rationale
128k 30–50 65–70 balanced, fits most coding tasks
256k 60–100 70–75 keeps more tool chain, suits complex refactors
1m 100–200 75–80 compress less; watch cost and latency

And the symptom-to-knob mapping, which is the genuinely useful part:

Symptom Adjustment
agent keeps re-reading a file it just read raise the message threshold
model reports context overflow lower the percent threshold
summarization is slow or expensive raise both thresholds
small model flaky on complex tasks lower sessionWindowSize

If a task consistently gets cut off mid-way, maxTurns

may be too low. But if the model is spinning in circles, tighten the task description instead. More turns will not fix an underspecified request.

The official checklist is short: verify apiUrl

, apiKey

, the model name, and your network proxy. Expanded into something you can actually run through:

apiUrl

the chat endpoint, not the vendor's homepage? Did you drop the /v1

or /chat/completions

segment?standard=ollama

set, or the full /api/chat

address used?#

suffix.Still stuck? Set logLevel

to DEBUG or TRACE, reproduce the failure once, and read .soloncode/logs/

. Grep for timeout

, 401

, 403

, dialect

, model

. On dialect mismatch specifically, the docs name two causes: a wrong standard

, or a missing dependency package.

There is one more failure mode worth naming, because it looks like a config problem and is not: the connection tests green but the coding output is poor. Check whether you launched from the project root (wrong working directory means no project context), whether the project has an AGENTS.md

describing build and test commands, and whether the session is simply too polluted — a fresh session often fixes it. If none of that helps, you are looking at a model capability limit, and the fix is a different model, not a different config value.

Run these in your project root before trusting the setup with real work:

Step Input Pass condition
1 hello
clean response, no auth error
2 "list the top-level files in this workspace, change nothing" output matches ls
3 same question on a second model, if configured both answer
4 temporarily break the key, hit Test connection it fails — proving the button is honest
5 restore the key, test again green

Step 4 is the one people skip and the one that matters most. A test button you have never seen fail is a test button you cannot trust.

Once all five pass, add a second model and split your traffic: a cheap fast model as the default for reading code and small fixes, a stronger one you switch to deliberately for cross-module refactors and hard bugs. Running every task on your most expensive model is the fastest way to a surprising invoice, and it is rarely the difference between success and failure. Task description quality usually matters more than model tier.

Topic Link
SolonCode

Defaults and field names shift between versions, and the two documentation pages disagree on a couple of them today. When in doubt, the settings page in your installed build is the authority. Model ids and endpoint paths belong to your provider — re-check those in the console before you file a bug against the config.

── more in #developer-tools 4 stories · sorted by recency
── more on @soloncode 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/wiring-a-model-into-…] indexed:0 read:11min 2026-08-03 ·