The tuning values on this page are configured in the in-app App Settings screen
(sidebar footer, sliders icon) and stored in app_settings.jsonc -- not in .env.
A value left in .env is ignored and named once in the startup log; run
chatwalaau settings migrate --write to carry an existing configuration across.
Feature enable-gates and secrets stay in .env.
See Configuration -> Application settings.
Agent Tools
The agent can call built-in tools, and you control which are enabled and how risky ones are gated.
Image generation & editing
Enable generation and editing (via the Azure OpenAI Images API) by adding a single
image offering to your model offering catalog (model_offerings.jsonc) -- author
it with the in-app App Settings screen, chatwalaau models add, or by hand.
GPT-Image-2.5-Sunburst (the most capable model for generation and precise editing)
is the suggested model; put your deployment name in model_ref:
{
"id": "image",
"provider": "azure-openai",
"operations": ["image"],
"model_ref": "gpt-image-2.5-sunburst",
"api_version": "preview"
}
- image_generate -- create images from text: quality up to
xhigh/max, any size that meets the model's rules, background, and 1-10 images per request - image_edit -- change an existing session image. It can also take up to 15 more images as references and an optional mask. Ask in chat, e.g. "change the background to a beach, keep the product's shape and logo".
- Image editor -- click Edit on a generated image (see below)
- Images are always PNG, render inline and persist across reloads
With no image offering, the image tools are simply not available (the app starts normally); add the offering to turn them on.
The tools were called generate_image / edit_image. A declarative agent or harness
tools: list that still names an old tool is shown a warning with the new name and does
not activate until you update it. Old conversations keep their images.
The image editor
Click Edit on an image to change part or all of it. The editor is as large as the App Settings window.
- Mask tab -- paint the area that may change (brush S/M/L, eraser). The tint stays even however often you paint over the same spot. Leave it empty for a whole-image edit. If the image's colours make the mask hard to see, pick another colour and set the opacity (10-90%). This only changes what you see, not the area that is edited.
- Annotate tab -- draw rectangles or freehand marks. Each is labelled A, B, C... and adds a note box to the side panel, so you can say what happens to each region. The mask and the marks are used together in one edit.
- Change / Preserve -- write what must be different and what must stay exactly as it is, e.g. Change: the background only. Preserve: the product's shape, logo and colors. Both are multi-line: Enter adds a line and Ctrl+Enter generates. An IME confirmation never submits.
- References -- add up to 14 images and refer to them as Ref 1, Ref 2... in your text.
- Quality / Background / Images -- choose them for this edit, or leave them on Default (...). The edit keeps the source's shape.
Generate calls the image API directly, so it works whichever agent or workflow is selected. Your message appears at once with the masked preview, the annotated image and the references. The result is saved to the conversation like any other answer, so you can ask the agent to refine it next.
The editor remembers: press Edit on the same image again and your mask, marks, references and text are back. A newly generated image opens a fresh edit. Drafts travel with export/import and fork.
Customize image output
Image defaults live in one place: App Settings -> Model Offering Catalog -> your image offering -> Image output defaults.
| Field | Choices | Default |
|---|---|---|
| Size | 2048x1152 (16:9), 1920x1440 (4:3), 1024x1024 (1:1) | 2048x1152 |
| Quality | low, medium, high, xhigh, max | xhigh |
| Output Format | png (fixed -- image editing requires PNG) | png |
| Background | opaque, transparent | opaque |
A field left on Default (...) uses the value shown in brackets. When a user asks for something specific in the conversation ("make it square", "transparent background"), the model's value wins for that request. A value your deployment has been observed to reject is shown as not supported and cannot be selected.
xhigh and max take longer and cost more; sizes above 2560x1440 are experimental.
Transparency depends on the deployment: if it is refused once, the app remembers it and
disables the choice.
In model_offerings.jsonc:
{
"id": "image",
"provider": "azure-openai",
"operations": ["image"],
"model_ref": "gpt-image-2.5-sunburst",
"api_version": "preview",
"image_defaults": {
"size": "2048x1152", // any WxH: edges multiples of 16, 1:3..3:1, long edge <= 3840
"quality": "xhigh", // low | medium | high | xhigh | max
"background": "opaque" // opaque | transparent
}
}
The Built-in agent card no longer has an Image output section, and the Format /
Compression options and the auto value are gone. An older file that still contains
format, compression or auto keeps loading; those entries are ignored with a log
notice.
If your image model requires a different Images API version, set the offering's
api_version to the version your Azure deployment supports (preview selects the v1
surface).
Weather
Rich weather card widgets powered by Open-Meteo (free, no API key). The agent geocodes a city and fetches current conditions or a 7-day forecast on demand.
Coding tools
File operations and shell execution, restricted to a workspace directory:
CODING_ENABLED=true
CODING_WORKSPACE_DIR=C:\path\to\workspace
# CODING_FILE_READ_MAX_BYTES=1048576 # 1 MiB default
file_read caps output at CODING_FILE_READ_MAX_BYTES; when the cap or a line
limit is hit, the response ends with a [TRUNCATED BY BYTES: ...] /
[TRUNCATED BY LIMIT: ...] marker telling the agent how to paginate with
offset=N.
When a turn calls several tools at once, every result comes back (v0.147.0). Before that release the results of a parallel tool call were packed into a single message on the way to the browser and only the last one survived, so a tool that ran successfully could appear to have returned nothing. The loss happened in transit, not in storage, so older chats need no repair.
Files you get back (v0.152.0). When the agent creates a file for you, it saves
it in the workspace and links it in its answer as
[report.pdf](workspace:output/report.pdf). The chat shows that link as a file control
with Download (and Open for PDFs and images). Downloading needs the
File Explorer to be enabled
(FILE_EXPLORER_ENABLED=true); without it the control explains why it is unavailable.
Images the assistant generates stay in the chat
An image you asked the assistant to generate is not a workspace file. It is saved with
the conversation and shown in the chat right away, so the assistant does not copy it into
the workspace and does not add a download link for it -- use the image itself (right-click,
or the actions on the image) to save it. Only files the assistant creates with the coding
tools or a skill get the workspace: link above, including an image its code draws, such
as a chart. Before v0.158.1 a generated image was also copied into the workspace, which ran
extra shell commands and left a spare copy there.
Tools run without an approval step
As of v0.160.0 there is no approval card. A tool the agent has is run as soon as the agent calls it, on every surface -- the chat, Harness agents, Microsoft Teams, the OpenAI-compatible API and the CLI. Removing the approval step also removed the errors some long, tool-heavy turns hit after an approval.
What decides whether a tool can run is whether the agent has it:
| To keep the agent from... | Do this |
|---|---|
| running shell commands or writing files with the coding tools | set CODING_ENABLED=false |
| running skill scripts | set CODING_ENABLED=false |
| using a particular tool | leave it out of the agent's tool selection (Agents manager) |
| writing files from a Harness agent | turn File write tools off in the Harness editor |
| having a shell and file tools in a Harness agent at all | leave CODING_WORKSPACE_DIR unset |
The shell and file tools stay confined to the workspace directory. If you still have
TOOL_APPROVAL_* or AUTONOMOUS_LOOP_* keys in your .env, the server logs a warning at
startup naming each one; they have no effect, and chatwalaau env sync --write removes them.
Conversation compaction
Long sessions are compacted in memory before each model call (the on-disk session JSON is never altered) so the agent keeps responding instead of failing at the context-window limit.
Since v0.149.0 there is no strategy to choose. Every chat runs the same two-stage pipeline, in this order:
- Trim tool history. Older tool-call groups are excluded, keeping the newest K.
- Slide the window. The newest N of whatever step 1 left keeps its place; everything older drops out.
Configured in App Settings -> Chat & session (they left .env in v0.131.0):
| Setting | Default | Meaning |
|---|---|---|
| History compaction | on | Runs the pipeline. Turning it off restores the model's full view of history -- nothing on disk ever changed |
| Compaction: tool-call groups kept | 12 | K. Newest tool-call groups step 1 keeps (1..64) |
| Compaction: message groups kept | 25 | N. Newest message groups step 2 keeps, counted after step 1 (1..64) |
| Compaction: keep the system prompt | true | Exempts system messages from step 2. Note: an agent's own instructions are sent outside the message list, so they survive regardless of this setting |
The two numbers are coupled: 2 x K < N. Saving a pair that breaks the rule is
rejected with an explanation, so raising the tool-call budget may mean raising the
message budget too. The margin is not decoration -- see below.
Since v0.150.0 the last three rows are disabled in the screen while History compaction is off, carrying a Needs History compaction chip, because the pipeline never reads them in that state. Their values are kept, so switching compaction back on restores the budgets you set rather than the defaults.
All four are badged Rebuilds agents: the pipeline is built when the agents are, so saving runs an in-place rebuild to make it take effect. The badge only became true in v0.148.0; from v0.131.0 to v0.147.0 the rebuild re-used the strategy built when the process started, so a save reported success while the running agents kept the previous value until a restart. Saving now applies to the next turn everywhere the main agents serve: the chat UI, the OpenAI-compatible API, Teams, webhook-triggered runs, and the Prompt nodes of a workflow.
Why two steps
They cover different failures, and neither one covers both. Measured against the pinned agent framework:
| Session | Step 1 alone | Step 2 alone | Both |
|---|---|---|---|
| 1000 tool rounds in one turn | bounded | bounded, but the question is lost | bounded, question kept |
| 1000 chat turns, no tools | not compacted at all | bounded | bounded |
Step 1 only ever touches tool history, so it leaves a text conversation completely alone. Step 2 bounds that conversation but counts your request as one item of the same rank as a tool round, so on a long tool run it eventually drops the question being answered. Run in this order, each covers the other's gap.
Your request is not compacted away
Compaction runs before every model call, which in a turn that uses tools means once per tool round -- not once per turn. Before v0.146.0 that cost you the question: a turn that called four or more tools lost it partway through and could finish with a fluent answer to nothing.
v0.146.0 fixed this by pinning the request back after each pass. v0.149.0 removes
that pin, because the pipeline no longer needs it. Step 1 caps how many tool-call
groups can be in play at all, so your request can only ever be a bounded distance
from the end of the window -- and 2 x K < N is what guarantees it stays inside.
Measured with K=12: the request survives 120 tool rounds from N=13 upward, and is
lost at N=11 and N=12. That is why the rule is enforced when you save the numbers.
Known limit, stated plainly. The margin covers standalone interim assistant
messages too -- the tolerance is N - K - 1, which is 12 at the defaults. A turn
that emits more than that many separate narration messages between tool calls
could still lose its question. Narration that accompanies a tool call is part of
that tool call's group and does not count toward the limit.
Nothing stored was ever affected by any of this -- compaction has always worked on an in-memory copy -- so older chats were complete on disk the whole time.
Upgrading from before v0.149.0
Nothing is required of you.
- If you had compaction turned off (
COMPACTION_STRATEGYset tonone,offordisabled), it stays off: the setting is rewritten asCOMPACTION_ENABLED = falseon the first start, with a line in the log saying so. - If you had a strategy name selected, it no longer exists; the key is dropped with a warning and the pipeline runs.
- If you had set
COMPACTION_KEEP_LAST_GROUPSexplicitly to a number that breaks2 x K < N(the old default of4does), both compaction budgets reset to their defaults with one warning naming the old values and the new. No other setting is touched.
The tool-result strategy -- the only one that replaced old tool groups with a
summary rather than dropping them -- is removed and has no replacement.
Long-running work
For work that runs for a long time -- many tool calls, a large refactor, a multi-step investigation -- select a Harness Agent as the run target. It keeps its own plan and progress, works on every model provider, and can use Agent Skills.
Earlier releases had a BG button next to the context indicator that ran a turn as a server-side background response on Azure OpenAI and OpenAI models. It is gone: it worked on only two providers and turned Agent Skills off while it was on. Agent Skills are now available on every turn.
Prompt Templates
Save and reuse prompts from the chat interface (stored as JSON files):
TEMPLATES_DIR=.templates
Open the + menu -> Use template, or click the FileText icon on any user message to save it as a template. Insert to Chat pastes a template into the input for editing before send.
Agent Skills
Portable domain-knowledge packages following the Agent Skills specification, loaded on demand:
SKILLS_DIR=.skills
.skills/
my-skill/
SKILL.md # required: instructions + metadata
scripts/ # optional: executable code
references/ # optional: documentation
assets/ # optional: templates, resources
Skills use progressive disclosure (~100 tokens per skill when idle) to keep context-window usage low.
Scripts under a skill are executed only when CODING_ENABLED=true, and they run without
an approval step. .py, .sh, .bash, .js, .mjs and
.cjs are recognised. As of v0.141.0 all of this -- the scripts, the extensions,
your Skills modal selection -- works identically in
Harness agents, which previously used a separate loader
that had none of it.
The script tool (run_skill_script) is offered to the model only when at least one of
your visible skills has a script (v0.162.0). A set of instruction-only skills therefore
never produces invented script calls such as script_name: "noop".
A skill script runs inside its own skill folder, so a file it writes with a
relative path stays there -- out of your reach, and flagged as a local change by the
install ledger. Since v0.152.0 the agent is told the absolute workspace path and passes
it as the script's output location, so the file lands in the workspace and comes back
as a Download control. Skills written for OpenAI-hosted sandboxes, which link their
files as sandbox:/..., work without editing.
SKILLS_DIR emptySKILLS_DIR= (blank) means no skills. Before v0.141.0 an empty value resolved to
the folder the server was started in, and skills were searched for there.
SKILL.md per skillA skill folder is a boundary. If you put another SKILL.md in a subfolder of a
skill, it is not discovered as a second skill -- everything below a skill folder
belongs to that skill. Use sibling folders (or one grouping level,
.skills/<group>/<skill>/SKILL.md) when you want two separate skills.
A skill's scripts/, references/ or assets/ folder is only read when it is a
real folder under the skill. If it is a directory junction (mklink /J), a symbolic
link, or another reparse point -- which includes some OneDrive-backed paths -- those
files are silently left out, and the backend log records:
Skipping resource directory '...': symbolic link or reparse point detected in path
under skill directory '...'
The skill itself still loads; only the linked files drop out. Copy or move the real files under the skill folder to include them. This is an upstream safety rule and cannot be turned off.
Manage skills at runtime
A Skills icon in the sidebar footer (moved there in v0.166.0 from the chat
input row; look in the ... menu if the footer is crowded) opens a management modal
where you can enable or disable skills while the server is running -- no file
edits, no restart. The /popup and /sidebar windows do not show the sidebar, so this
manager is not reachable from them; skills keep working there. Skills are organized by folder group (A/B/SKILL.md shows as group A,
skill B; B/SKILL.md is ungrouped). A group checkbox bulk-toggles every skill
under it, and each skill shows its description as an overview.
Disabling unused skills bounds the per-turn token cost: a disabled skill leaves the advertised set entirely (and disabling every skill removes the skill tooling too). Save shows a confirmation, then a brief rebuilding indicator while the agents are reconstructed; the next message advertises only the skills you kept.
The selection applies to every lane: chat, declarative agents and Harness agents alike. Before v0.141.0 Harness agents ignored it and advertised skills you had switched off.
A Harness conversation's transcript lives in memory inside that agent, so replacing the agent discards it. Save and Reload here rebuild every agent -- which is the only way a gating change can reach a Harness run that is already going. Finish or abandon a Harness run before changing your Skills selection. Ordinary chats are unaffected: their history is stored separately.
As of v0.151.0 the selection is durable: it is saved beside your skills (in
SKILLS_DIR) and applied before the first agent is built, so a restart no longer
re-enables everything. Skill files on disk are never modified by it. The management
endpoints (GET / PUT /api/skills) are auth-gated; localhost stays zero-config.
(This is the Skills counterpart of the MCP Tool Management modal.)
Nothing is disabled on your first start after the upgrade -- there is no saved selection yet, so the server behaves exactly as before. The file appears the first time you press Save or install a skill.
Reload (footer + empty state) re-reads SKILL.md from your skills directory and
rebuilds the agents -- so a skill folder you added or removed on disk is picked up
without a restart. Reload asks for confirmation and shows the same blocking indicator.
The icon is always shown when the endpoint is reachable, so even with no skills yet you
get an empty state with your skills directory and a Reload button. A skill found on disk
but not loaded yet (added since the last build) appears with a disabled toggle and a
"Reload to apply" hint until you reload.
Install skills from a catalog
The same modal can fetch a catalog of skills published on GitHub and install them for you. The left pane lists Installed first, then one entry per source:
| Source | Repository |
|---|---|
| OpenAI | openai/skills |
| Anthropic | anthropics/skills |
| Hugging Face | huggingface/skills |
| gstack | garrytan/gstack |
| NVIDIA | nvidia/skills |
Press Refresh catalog to build it. This is a snapshot with a timestamp, shown above the list -- nothing refreshes it on its own. If one repository is unreachable or rate-limited, that source keeps its previous entries and is marked stale with the reason; the others still update.
Installing writes to <SKILLS_DIR>/<group>/<skill>/, where the group is the source
(.skills/openai/pdf/). Upstream layouts differ -- some publish under skills/,
OpenAI under skills/.curated and skills/.system -- and they are all flattened to
that one shape, because a skill nested any deeper is never discovered.
Each row carries status chips that combine:
| Chip | Meaning |
|---|---|
| Installed | Present on disk and recorded in the install ledger |
| Update available | The catalog's revision differs from the one you installed |
| Locally modified | The files on disk differ from what was installed |
| Not in the current catalog | Installed, but the current catalog does not list it -- it keeps working and will not receive updates |
| Missing on disk | Recorded as installed, but the folder is gone (see the persistence note below) |
| Disabled | Installed but switched off, so it is not advertised |
Install and remove are buttons; enable and disable stays a toggle. They do different things: one changes what is on disk, the other changes what each message advertises to the model.
Before installing, the confirmation shows the skill's license -- or says License unknown, which it never guesses -- and warns you when the skill ships executable scripts, since those can be run once installed.
Reinstalling deletes the existing folder and writes the upstream copy, so a file that upstream removed does not survive. If you have edited the skill locally, it asks "This skill has local changes. Overwrite?" first.
Agent Skills are identified by name, and the framework keeps only the first of a
duplicate. Installing a pdf skill when another source's pdf is already installed is
refused outright, because the second copy would sit on disk and never load. Remove the
existing one first. There is no override for this.
SKILLS_DIR -- mount it if it must surviveInstalling places files in your skills directory. On a container platform that directory is ephemeral unless you mount persistent storage there, so a restart can take your installed skills with it. ChatWalaʻau cannot change that, and does not pretend to: it records what it installed, and a skill whose folder has vanished is shown as Missing on disk with a reinstall button rather than silently forgotten.
The catalog, the install ledger and your enable/disable selection are all stored as
hidden files inside SKILLS_DIR, so mounting that one directory covers everything.
SKILLS_DIR is the only skills setting that lives in .env; the rest are in App
Settings, because those two paths resolve under it.
The whole write side -- catalog refresh, install, reinstall, remove -- is switched off in demo deployments, and by turning Skill installation off in App Settings (the Agent Skills group). Browsing still works, so the screen still shows what is installed.
Demo mode outranks the switch and cannot be flipped from any screen, which is what makes it safe for the switch itself to live in App Settings.
There is deliberately no "install from URL" field: installing a skill puts third-party code on your server, so the installable set is limited to the sources above. To use a different repository, put your own JSON source table on the server and name it in the Source table file setting -- the setting names a file, it never carries one.