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.

Knowledge & MCP

RAG pipeline​

Upload PDFs and ask questions about their content using vector similarity search.

RAG needs an embeddings offering in your model offering catalog (model_offerings.jsonc) -- author it with the in-app App Settings screen, chatwalaau models add, or by hand:

{
"id": "embed",
"provider": "azure-openai",
"operations": ["embeddings"],
"model_ref": "text-embedding-3-small"
}

The pipeline knobs remain plain .env values (they are not model routing):

CHROMA_DIR=.chroma
RAG_COLLECTION_NAME=default
RAG_TOP_K=5
RAG_CHUNK_SIZE=800
RAG_CHUNK_OVERLAP=200
# RAG_CHUNK_MIN_SIZE=200 # unset -> RAG_CHUNK_SIZE // 4; 0 disables tail-merge

With no embeddings offering, RAG search and ingest return an actionable message telling you to add one (the app otherwise starts normally).

Workflow:

  1. + -> Attach PDF to upload a document
  2. Submit an ingest job -- either ask the agent "Please ingest this document", or open the Pipelines portal (below) and submit a rag-ingest job with the file path
  3. The pipeline job runs: PDF parsing -> chunking -> embedding -> ChromaDB storage
  4. Ask: "What does the document say about X?"
  5. The agent answers with source citations (filename, page)

Highlights: file-based ChromaDB storage, a singleton embedding client (one credential + TLS handshake per process), overlap chunking with tail-merge, metadata-based citation, automatic de-duplication on re-ingest, and PDF file cards in chat. Ingestion runs on the Pipeline Jobs engine (below), which is built in.

Since v0.218.0 a search for a collection that does not exist answers Collection not found. and creates nothing. An agent can be limited to some collections, and answer only from them, with a knowledge scope. Since v0.220.0 a scope can be split into routes, and an API request can let the decision model pick one before the search.

Pipeline Jobs​

Data-processing tasks (RAG ingestion today; more job types over time) run on an in-process pipeline engine with a dedicated management screen. Open the Pipelines icon in the sidebar footer (next to Declarative Agents) to:

  • Submit a job from a job-type form (e.g. rag-ingest with a PDF path)
  • Watch live progress with a progress bar and status
  • Cancel a running job or delete a finished one
  • Review run history -- each execution keeps a captured log you can open

It is on by default (PIPELINE_ENABLED=true). Pipeline jobs are curated in-process job types (no shell, no CODING_ENABLED) -- distinct from the Cron Scheduler, which runs scheduled scripts and is off by default. Configuration:

# Pipeline Jobs (in-process data-processing engine)
PIPELINE_ENABLED=true
PIPELINE_JOBS_DIR=.pipeline # per-job JSON + output/{job}/{run}/ run logs
PIPELINE_OUTPUT_MAX_BYTES=1048576 # per-run captured-log cap
PIPELINE_MAX_CONCURRENT_JOBS=2

The agent can also manage jobs via the manage_pipeline tool (submit / list / get / cancel / delete); the agent tool and the REST API (/api/pipeline/*) share the same engine and store, so the chat and the portal never diverge.

Since v0.188.0 a job type can run its work in a child process that cancelling and a per-type time limit really stop, and can have its own concurrency slots. The ontology uses this for its ontology-entailment jobs, queued after every ontology save (one at a time, 600 s limit by default); they appear in the portal like any other job. Since v0.189.0 the ontology-shacl jobs validate ontologies with SHACL shapes after their saves the same way (one at a time, 300 s limit by default).

Under DEMO_MODE​

On a demo host the pipeline is read-only. The portal, the job list and the run history all stay available -- the feature is shown, not hidden -- but submitting, cancelling and deleting refuse with 409, and the manage_pipeline tool is not offered to the agent.

The reason is that every rag-ingest job writes into the same vector collection the bundled demo corpus is served from, so one visitor's upload would otherwise come back as another visitor's citation. Closing the REST endpoint alone would not have been enough: the agent tool writes through the same engine, so "ingest this PDF for me" in chat would have gone through.

MCP integration​

Connect external tools via the Model Context Protocol using the Claude Desktop-compatible config. ChatWalaʻau ships a bundled default (mcp_servers.default.jsonc) and prefers an operator override (mcp_servers.jsonc, gitignored) -- no manual copy on first run.

# Optional: defaults to mcp_servers.jsonc; set empty to disable MCP.
# MCP_CONFIG_FILE=mcp_servers.jsonc
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/workspace"]
},
"remote-api": {
"url": "https://api.example.com/mcp",
"headers": { "Authorization": "Bearer ${EXAMPLE_API_TOKEN}" }
}
}
}
  • JSONC -- // and /* */ comments are stripped; strict JSON is accepted unchanged, so existing Claude Desktop / Claude Code / Cursor configs reuse
  • stdio servers (with command) are spawned; HTTP/SSE servers (with url) are connected to
  • MCP tools appear alongside built-in tools and show a Plug icon
  • Server lifecycle is managed automatically (with zombie-process prevention)
  • Optional per-server fields: "load_prompts": true (for servers implementing prompts/list; default false), "load_tools": false, "request_timeout": 30 (seconds; when omitted, a call has no time limit and Stop ends it)
  • ${VAR} references (v0.206.0) -- in env, headers and url, ${NAME} is replaced by the variable from your .env (or the environment) when the file is loaded, so tokens stay out of the file. A server naming a variable that is not set is skipped with a warning naming it; the other servers still start. Literal values keep working.
  • "disabled": true (v0.206.0) -- the server stays in the file but is not connected (a stdio server is not started). "disabled_tools": ["name", ...] hides single tools. The MCP Servers screen writes both for you.

Your own Python MCP server (MCP SDK 2, v0.203.0)​

ChatWalaʻau's Python environment carries MCP SDK 2.x since v0.203.0 (Microsoft Agent Framework 1.23 requires it). This matters only if you run your own Python MCP server with ChatWalaʻau's own interpreter (a "command" that points at ChatWalaʻau's python). MCP SDK 2 removed mcp.server.fastmcp; change the server to:

# MCP SDK 1.x: from mcp.server.fastmcp import FastMCP; server = FastMCP("my-server")
from mcp.server.mcpserver import MCPServer

server = MCPServer("my-server")

The decorators (@server.tool(), @server.resource(...)) and server.run() stay the same. Servers started in their own environment (uvx, npx, a separate virtual environment, a binary) are not affected. A tool that should return structured content needs a typed return value (a TypedDict or a Pydantic model); a plain dict is returned as text.

Manage MCP servers in the app​

Open the MCP Servers screen from the Plug (MCP) icon in the sidebar footer (if the footer is crowded, look in the ... menu at its right edge).

Changed in v0.206.0

Servers are now added, edited, tested and removed from this screen, and turning a server or tool off is saved in mcp_servers.jsonc, so it survives a restart. Before, the screen could only switch tools off until the next restart.

Add or edit a server​

  1. Click Add server (or select a server and click Edit).
  2. Pick the transport. stdio runs a command on the server machine (for example npx with -y and a package name, one argument per line). HTTP connects to a URL.
  3. Add environment variables (stdio) or headers (HTTP). Each row takes the name of a variable in your .env, never the value: the screen saves ${NAME} (a header can carry a scheme, saved as Bearer ${NAME}). The row shows whether the variable is set. Add the variable to .env and restart before you rely on it.
  4. Click Test to connect the server alone and list its tools (nothing is saved).
  5. Click Save. The file is rewritten and the servers reconnect.

Good to know:

  • Saving rewrites the file without its comments. The previous file is kept next to it as mcp_servers.jsonc.bak. If you have no mcp_servers.jsonc yet, the first save creates it from the bundled default (which is never changed).
  • A value you wrote in the file by hand (a token typed in literally) is shown as "kept" and stays as it is when you edit the server. Moving it to .env and writing ${NAME} is recommended.
  • If the file changed on disk after you opened the screen, Save is refused; reopen the screen and try again.
  • Remove asks first. A workflow that names a removed or renamed server can no longer reach it.

Turn servers and tools off​

  • Toggle a whole server on the left, or single tools on the right (tool descriptions are shown when the server provides them), then Save. Saving asks for confirmation and shows a blocking indicator while the change is applied.
  • A tool switched off stays connected but is no longer offered to the model, which saves input tokens on every turn (each tool's name, description and schema are sent).
  • A server switched off is disconnected (a stdio server's process stops) and is listed as "disabled". Switch it on and Save to connect it again.
  • Add, Edit and Remove wait until toggle changes are saved or discarded.
  • Reload re-reads a file you edited by hand and reconnects the servers. A server that is configured but not connected shows a "Reload to apply" hint.

stdio servers and other machines​

A stdio server is a command the backend starts on its own machine. ChatWalaʻau therefore lets you add, edit or test stdio servers only from that machine (the Windows app and a browser on the same PC always qualify). From a phone on your LAN, a cloud deployment or a browser reaching a Docker container, stdio is shown locked; HTTP servers, Remove and the on/off toggles still work everywhere.

# Allow stdio edits from other machines. Then whoever holds an API key (scope api or admin) or the web login
# can run commands on this server. Leave it false on a LAN, cloud or Docker deployment.
# MCP_STDIO_REMOTE_EDIT=false
  • A request is "from this machine" only when it comes from loopback and carries no proxy forwarding header (X-Forwarded-For, Forwarded, X-Real-IP, CF-Connecting-IP). Keep your reverse proxy's X-Forwarded-For, so a tunnel or proxy on the same host never makes a remote visitor look local.
  • In the cloud, prefer remote (HTTP) MCP servers. A stdio server in a container needs its runtime (node for npx, uv for uvx) in the image.
  • The screen is an operator function protected like other write endpoints (localhost is exempt) and applies to every user of that server.

MCP Apps​

When an MCP tool declares a _meta.ui resource, its HTML View renders as interactive UI inside the chat message, in a secure double-iframe sandbox. ChatWalaʻau follows the stable MCP Apps specification (2026-01-26) and hosts Views with its official SDK (since v0.204.0), so Views built for other MCP Apps clients work here too.

# MCP_APPS_SANDBOX_PORT=8081 # optional sandbox proxy port
  • Double-iframe sandbox -- Views run on a separate origin with no access to host DOM, cookies, or storage; CSP blocks external resources unless the View's resource declares them
  • Auditable -- all View-to-Server interaction is proxied through the Host
  • Full tool results -- a View gets the tool's input and its complete result, including structuredContent; its own tools/call and resources/read receive the MCP protocol's keys (structuredContent, isError, mimeType, _meta)
  • Talks to the chat -- a View can send a message, which becomes your next turn (marked "Sent from the ... app"; refused while a reply is streaming), and can give the model context for your next turn without it appearing in the chat
  • Tool visibility -- tools a server marks as app-only are never given to the model, and a View can call only tools marked for apps
  • Display modes -- inline and fullscreen; Views resize themselves and follow the theme; session persistence rebuilds Views when you reload a chat
  • Progressive enhancement -- tools work as text when UI is unavailable

No configuration needed; MCP Apps activates automatically and the sandbox proxy starts alongside MCP servers, on the same host as the app.

Using MCP Apps from another machine or Docker

The sandbox is reached on the page's own host at MCP_APPS_SANDBOX_PORT. When the browser runs on another machine, that port must be reachable too. With Docker, publish it (-p 8081:8081) and set APP_HOST=0.0.0.0 with an API key, as for any network access. If the sandbox is not running, the View shows a notice and the text result stays.