Skip to main content
Moved to App Settings in v0.129.0

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.

Renamed in v0.168.0

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.

FieldChoicesDefault
Size2048x1152 (16:9), 1920x1440 (4:3), 1024x1024 (1:1)2048x1152
Qualitylow, medium, high, xhigh, maxxhigh
Output Formatpng (fixed -- image editing requires PNG)png
Backgroundopaque, transparentopaque

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
}
}
Changed in v0.168.0

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).

Typed decisions (Microsoft-Decision-1)​

New in v0.195.0. Microsoft-Decision-1 is a Microsoft Foundry model built to classify, route, gate and score -- not to write text. Give it an input and typed questions, and it returns probabilities. It is fast and inexpensive (input tokens only).

Turn it on by deploying Microsoft-Decision-1 in your Foundry resource and adding a single decision offering in App Settings > Model Offering Catalog > Decision (or chatwalaau models add --operation decision):

{
"id": "decision-1",
"provider": "azure-openai",
"model_ref": "microsoft-decision-1", // your deployment name
"endpoint": "https://my-foundry.services.ai.azure.com", // optional: the Foundry resource
"operations": ["decision"]
}
  • At most one decision offering; it serves no other operation and uses the azure-openai provider. Authentication uses api_key_env when set, otherwise the shared Azure credentials.
  • Without endpoint the offering uses AZURE_OPENAI_ENDPOINT. If calls answer not found, set the endpoint of the Foundry resource where the model is deployed.

Every agent then gets decision_evaluate. One call asks one or more questions about one input (state: text or a JSON object). Three question types can be mixed:

TypeQuestionResult
noulIs this true? (yes / no)the probability of true
choiceWhich option is it? (criteria: {label: description})the chosen label and a probability per option
scoreHow much? (criteria: levels, lowest first)a score, the nearest level and its label

For example, triaging a support mail with three questions at once:

{
"urgency": {"type": "noul", "instructions": "Does the customer need urgent help?"},
"team": {"type": "choice", "instructions": "Which team should handle the request?",
"criteria": {"billing": "Payment and invoice issues",
"technical": "Software and integration issues"}},
"priority": {"type": "score", "instructions": "How high is the priority of this request?",
"criteria": ["Routine, no time pressure", "Important, some time pressure",
"Urgent, immediate attention needed"]}
}

Ask in chat, e.g. "Sort these three support mails by team and urgency". The call is shown as Evaluating decisions, and the answers appear as a table in the chat: question, answer, probability and the other options. An answer below 60% is marked uncertain.

  • The call is checked before it is sent: a question that breaks a rule comes back to the agent with the list of problems, and nothing is billed. bool, boolean and yes_no are read as noul.
  • Limits are in App Settings > Decision: questions per call (20), options per choice question (50), levels per score question (11), input size (100,000 characters).
  • Each call adds a Helper record (purpose decision_evaluate) to the token usage ledger.
  • Custom Prompt agents and harnesses can select the tool (category decision).
  • Since v0.220.0 the same offering can also route the questions of a document desk on /v1/responses ("route": "auto"): one choice question picks the business area, and only its documents are searched. See routing questions. Those calls are recorded under the calling API key (purpose responses_route).
  • No reasons are returned -- only numbers. Use the probabilities as an input to your judgement, validate questions on your own examples, and do not use the result as the sole basis of a decision about a person (credit, employment, housing, healthcare, legal).

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.

Computer Use (Windows)​

With COMPUTER_USE_ENABLED=true on your own Windows machine, the agent can also see and operate desktop applications -- one batch of clicks and keystrokes per decision, waiting for the screen to settle instead of sleeping, and stopping on Ctrl+Alt+End or when you move the mouse (v0.170.0). See Computer Use.

CodeAct: a compute sandbox​

Models guess at long arithmetic, date differences and regular expressions. With App Settings > CodeAct turned on (v0.172.0), every agent also gets one tool, execute_code: it runs a short Python snippet in an isolated worker process and returns what the code printed and the value of its last expression.

import datetime
(datetime.date(2026, 12, 25) - datetime.date(2026, 9, 26)).days # -> 90
  • For: exact arithmetic, dates and durations, unit conversion, counting, sorting and aggregating data the agent already has, reshaping JSON, regular expressions.
  • Nothing reaches your machine. There are no files, no network, no OS access and no other tools inside the sandbox. The agent calls its other tools directly, as usual, and puts their results into the code.
  • A Python subset. json, re, math, datetime, collections, itertools, base64, dataclasses, random, time, hashlib and decimal are available; statistics and csv are not, and code cannot sleep. Variables do not survive from one call to the next.
  • Bounded. Each execution is stopped after 10 seconds or 64 MB (both adjustable in the same group: 1-60 s, 32-1024 MB). One snippet runs at a time, and it never pauses the other chats on the server.
  • Everywhere. It works the same on every model provider, for Core and Custom agents, workflow Prompt nodes, Live delegation, the OpenAI-compatible API, Teams, schedules and Harness agents. It is off by default and never offered in demo mode.
  • Per model: set the offering's CodeAct capability to Not available for a model with weak function calling (deployment capabilities).

Each call is one tool card, Running code... / Ran code; expand it to see the code and its result.

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 toolsset CODING_ENABLED=false
running skill scriptsset CODING_ENABLED=false
using a particular toolleave it out of the agent's tool selection (Agents manager)
writing files from a Harness agentturn File write tools off in the Harness editor
having a shell and file tools in a Harness agent at allleave 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:

  1. Trim tool history. Older tool-call groups are excluded, keeping the newest K.
  2. 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):

SettingDefaultMeaning
History compactiononRuns the pipeline. Turning it off restores the model's full view of history -- nothing on disk ever changed
Compaction: tool-call groups kept24K. Newest tool-call groups step 1 keeps (1..64). 12 before v0.217.0
Compaction: message groups kept50N. Newest message groups step 2 keeps, counted after step 1 (1..64). 25 before v0.217.0
Compaction: keep the system prompttrueExempts system messages from step 2. Note: an agent's own instructions are sent outside the message list, so they survive regardless of this setting
Compaction: keep skill instructionsonKeeps the instructions of the skills a turn loaded when step 1 trims older tool calls (v0.217.0)
Compaction: skills kept4How many loaded skills, newest first, keep their instructions (1..16)

Skill instructions are kept (v0.217.0)​

A skill's instructions arrive as the result of a load_skill tool call, so before v0.217.0 step 1 treated them like any other old tool output: after K more tool rounds they dropped out of the model's view, while the turn was still following them. The model then reloaded the skill, and sometimes answered only I'm sorry, but I cannot assist with that request.

Now a last pass puts back, for each skill (and each skill resource), the newest successful load that the two steps removed, up to Compaction: skills kept. The pass only puts groups back, never removes any, so the request guarantee below and the meaning of K and N are unchanged. A load mixed with another tool call in the same step, or a failed load, is not kept. Each time compaction changes what the model sees, the server log shows one line such as Compaction: tool_call_excluded=2 window_excluded=0 skill_context_kept=1 (pdf) included_groups=26.

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:

SessionStep 1 aloneStep 2 aloneBoth
1000 tool rounds in one turnboundedbounded, but the question is lostbounded, question kept
1000 chat turns, no toolsnot compacted at allboundedbounded

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 25 at the defaults (12 before v0.217.0). 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_STRATEGY set to none, off or disabled), it stays off: the setting is rewritten as COMPACTION_ENABLED = false on 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_GROUPS explicitly to a number that breaks 2 x K < N (the old default of 4 does), 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.

The Background (BG) toggle was removed in 0.156.0

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.

Leaving SKILLS_DIR empty

SKILLS_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.

One SKILL.md per skill

A 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.

Windows: junctions and reparse points are skipped

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. 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.

Saving or reloading ends a Harness conversation in progress

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.)

Upgrading from v0.150.0 or earlier

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:

SourceRepository
OpenAIopenai/skills
Anthropicanthropics/skills
Hugging Facehuggingface/skills
gstackgarrytan/gstack
NVIDIAnvidia/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:

ChipMeaning
InstalledPresent on disk and recorded in the install ledger
Update availableThe catalog's revision differs from the one you installed
Locally modifiedThe files on disk differ from what was installed
Not in the current catalogInstalled, but the current catalog does not list it -- it keeps working and will not receive updates
Missing on diskRecorded as installed, but the folder is gone (see the persistence note below)
DisabledInstalled 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.

A skill name can only be installed once

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.

Installed skills live in SKILLS_DIR -- mount it if it must survive

Installing 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.

Where installation is unavailable

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.