MiniAgent

MiniAgent is the built-in coding agent: a fully self-contained backend compiled right into Agent (a C# library, a minimal Pi-style agent rewritten from scratch). It needs no external program and has nothing to install — Agent and MiniAgent are one whole and fully self-sufficient out of the box.

MiniAgent is part of Agent’s backend system and is selected with the AGENT_BACKEND=mini variable. For the general overview of backends, see the Backends page.


Why this matters for your business

Regular backends are third-party programs downloaded and installed through a package manager. MiniAgent is different: it lives inside Agent itself, which means:

  • Independence from third-party developers. The agent’s work does not depend on someone else’s projects and their updates — the engine is always at the server’s side.
  • Supply security. No packages installed from third-party sources — the very risk of receiving a compromised installer disappears.
  • Self-sufficiency out of the box. MiniAgent is already inside the product: nothing to download, install, or update separately.
  • Everything on your server. The agent runs wherever Agent runs: your data never leaves your infrastructure.

Capabilities

It is a full agent with everything real work needs:

  • Tools read, write, edit, bash, parallel_bash, grep, find, ls, glob, load_skill, todo_write, agent, and the background tasks agent_start, agent_check, agent_stop — reading, editing, and creating files, running commands, search, skill loading, and launching subagents;
  • Persistent sessions — the conversation is saved in JSONL format and resumes after a restart;
  • Model and reasoning-level switching on the fly — right in the middle of a dialog, losing nothing;
  • One thinking level for every chat — a single profile setting for the whole process; it wins over the model-name suffix and over the level stored in a session;
  • Automatic context compaction — long conversations do not “forget” their beginning;
  • Retries on transient provider failures and protection from lost replies — the pause between attempts and their number are configurable, and every retry is visible in the chat as its own line (more below);
  • Token and cost accounting — in the chat and in analytics;
  • Project context — reads CLAUDE.md/AGENTS.md itself (CLAUDE.md takes priority) and finds the .claude/skills skills on its own;
  • Interactive forms and buttons (agent.form/agent.button) — right in the system prompt, with no separate extensions;
  • Image reading — the read tool attaches an image file to the request (details in the note below);
  • Frugal file reading — how many lines read returns per call is configurable, and a long file is read in parts instead of filling the context at once;
  • Loading pages and searching the web — the agent opens the addresses it needs and searches the internet on its own: the fetch and search calls go through a configurable list of services, and when one service does not answer, the turn passes to the next one (more below);
  • External tools and rules — MiniAgent connects the MCP servers from mcp.yml itself and applies the hooks from hooks.yml: in mini chats they work exactly as they do for the command-line backends;
  • Subagents — the agent tool launches a nested session with its own context, visible as a child chat: several calls in one answer run simultaneously, and right beside them sit background tasks whose outcome arrives in the current turn by itself (more below).

Note: sending images into the chat is not wired up yet — images attached to a message are ignored with a warning in the log. At the same time the agent reads images from disk itself with the read tool: on models whose image input is allowed, the file is attached to the request (jpg, png, gif, webp, bmp up to 5 MB), while on text-only models a clear error comes back. A file over the limit is rejected with a hint to shrink it with a command.


Connecting it

MiniAgent is selected with the AGENT_BACKEND=mini variable. The easiest way is to create a model from a ready provider template that already carries the MiniAgent backend: Anthropic, DeepSeek, z.ai, BigModel, OpenRouter, xAI, MiniMax, Moonshot, OpenAI, OpenCode Go/Zen. The template fills in the backend and the connection parameters for you:

  • MINI_BASE_URL — the provider address;
  • MINI_API — the protocol format: anthropic-messages or openai-completions;
  • MINI_AUTH — the authorization type: api-key or bearer;
  • MINI_API_KEY — the access key.

The model is set in the “provider/model:thinking” format, for example MODEL=anthropic/claude-sonnet-5:medium. The :thinking suffix sets the reasoning level: off, minimal, low, medium, high, xhigh, max; without a suffix the level is medium. A model the templates do not know is assembled automatically from the parameters above; when a ~/.mini/models.json file exists (a Pi-compatible format), it takes priority. If no model is set at all, deepseek/deepseek-v4-flash is used. The default provider can be set with the MINI_PROVIDER variable — it applies when the model name has no “provider/” prefix.


Data

MiniAgent’s data is stored in the ~/.mini folder (overridable with the MINI_AGENT_DIR variable):

  • models.json — the model configuration;
  • agent-sessions — sessions in JSONL format;
  • skills — additional skills;
  • CLAUDE.md — the global context.

MiniAgent profiles

A profile is a named set of settings for the built-in agent: which context files to load, which tools it may use, how long a single call may run, the token ceiling for requests, and how many subagents may run at once. Profiles let you keep several modes of working in one project: a “safe” one without bash for sensitive repositories, a “draft” one with a long timeout for heavy tasks, a “read-only” one for reviews — and switch between them just by changing the model.

Profiles live in the miniagent.yml file in the project’s brand folder (.xedant/). The root map is profiles: — the key is the profile name, the value is its settings:

# miniagent.yml
profiles:
  safe:                       # safe mode: no bash, a short timeout
    disabledTools:
      - bash
    toolCallTimeout: 60
    loadAgentsMd: false

  readonly:                   # read-only: only the search tools are allowed
    enabledTools:
      - read
      - grep
      - find
      - glob
      - ls

The model picks the profile with a mini:name suffix in the AGENT_BACKEND variable of the model’s configuration on the Models page — for example, AGENT_BACKEND=mini:safe. The profile name is lowercased and looked up case-insensitively; the legacy alias mini-agent:safe works too. A plain AGENT_BACKEND=mini without a suffix, an empty suffix, or a nonexistent name all give the built-in defaults — a missing profile logs a warning. Only the MiniAgent backend understands the colon suffix; other backends take the AGENT_BACKEND value as a whole.


Profile settings

Every profile field is optional: a missing field, an empty {} profile, or a missing file all mean the built-in defaults.

FieldTypeDefaultWhat it does
loadClaudeMdbooltrueloads CLAUDE.md into the context
loadAgentsMdbooltrueloads AGENTS.md into the context
enabledToolslist of namesnone (all 11 enabled)the tool allowlist; an empty list is an error; mutually exclusive with disabledTools
disabledToolslist of namesnone (all enabled)the tool denylist; mutually exclusive with enabledTools
toolCallTimeoutint, seconds300the ceiling on a single tool call
maxOutputTokensint384000the request’s output-token ceiling; by default the ceiling comes from the model’s own description (384000); overrides the model’s maxTokens
thinkingBudgetint65536the thinking budget for every reasoning level except off; applied on anthropic endpoints
thinkingLevelstringthe level from the model name, else mediumone reasoning level for every session of the profile; wins over the :thinking suffix and over the level a session has stored; one of off, minimal, low, medium, high, xhigh, max
parallelBashThreadsint5how many commands of one parallel_bash call run at once
readMaxLinesint500how many lines one read call returns before truncation; the second cap is 50 KB per response
maxParallelAgentsint4how many subagents of one chat run at once; the rest wait in the queue
systemPromptstringbuilt-inreplaces the built-in base system prompt; empty also means built-in
sessionHeaderstringnone (X-Agent-Session, X-Opencode-Session on opencode)the name of the HTTP header carrying the session id on every provider request; a headers entry in models.json with the same name takes priority

The thinking level. The thinkingLevel field sets one level for every session of the profile — handy when the whole server must work at one level: thinking switched off for speed and savings, or turned all the way up for complex tasks, for example. The setting wins over both the :thinking suffix in the model name and the level stored in the session. The level affects not only the quality of the answer but also the bill: the higher it is, the longer the model thinks and the more tokens it spends. One more thing to know about DeepSeek-family servers: they used to always run at their own default level — thinking on, maximum effort — and the level chosen in the chat never reached them. Now the level arrives: thinking can be turned off or lowered.

How many lines the agent reads. The readMaxLines field limits how many lines one read call returns — 500 by default. The second cap is 50 KB per response: a file made of a few huge lines is truncated by size. When a file is longer, the agent receives a hint of where to continue and reads it on with further calls: it sees the whole big file, but the context is not filled with it in one go. Fewer lines per call — a cheaper conversation, but more calls to the file.

A profile manages exactly the 11 built-in tools: read, bash, parallel_bash, edit, write, grep, find, glob, ls, load_skill, todo_write. The agent, agent_start, agent_check, and agent_stop tools stand apart: they are added to every root chat always, and the profile lists never filter them — none of them can be enabled or disabled through a profile. Both enabledTools and disabledTools in one profile is an error (in the yml and in environment variables alike): allowing and forbidding the same tool makes no sense. An empty enabledTools is rejected — it would leave the profile with no tools at all — while an empty disabledTools only produces a warning. fetch and search never appear in either list either: they are not built-ins and stand on their own — each exists once its own catalogue holds at least one enabled service of its kind: fetch.yml for fetch, search.yml for search (more below).

Each setting’s priority: the model’s variable > the server process environment variable > the profile > the built-in default. The profile lays on top of the defaults, a MINI_PROFILE_* variable on top of the profile, and a variable set on the model itself on top of a server-wide one — so a value can be overridden for a single model without creating a separate profile. An empty value does not zero a setting: it counts as unset and the next source down answers.

The session header. Every provider request carries the session id in an HTTP header — the receiving provider can tell MiniAgent chats apart: group traffic, rate-limit requests, or keep per-session storage without parsing the conversation. By default the header is named X-Agent-Session; on opencode providers (a provider id starting with opencode or an address on opencode.ai) — X-Opencode-Session. The name is changed by the profile’s sessionHeader field or the MINI_PROFILE_SESSION_HEADER variable; an explicit headers entry in models.json with the same name beats the automatic stamp. The sessionHeader key has no editor in the settings dialog — you write it into miniagent.yml by hand or set the variable; the dialog passes a hand-set value through unchanged. A request sent before the session id exists carries no header.


Environment variables

Any profile setting can be overridden with a MINI_PROFILE_* variable — at the process level, for every mini chat on the server, or on a single model, in that model’s variables. In both cases it applies on top of the selected profile (or the defaults, when no profile is set):

VariableOverrides
MINI_PROFILE_LOAD_CLAUDE_MDloadClaudeMd
MINI_PROFILE_LOAD_AGENTS_MDloadAgentsMd
MINI_PROFILE_ENABLED_TOOLSenabledTools (comma-separated names)
MINI_PROFILE_DISABLED_TOOLSdisabledTools (comma-separated names)
MINI_PROFILE_TOOL_CALL_TIMEOUTtoolCallTimeout
MINI_PROFILE_MAX_OUTPUT_TOKENSmaxOutputTokens
MINI_PROFILE_THINKING_BUDGETthinkingBudget
MINI_PROFILE_THINKING_LEVELthinkingLevel
MINI_PROFILE_READ_MAX_LINESreadMaxLines
MINI_PROFILE_PARALLEL_BASH_THREADSparallelBashThreads
MINI_PROFILE_MAX_PARALLEL_AGENTSmaxParallelAgents
MINI_PROFILE_SYSTEM_PROMPTsystemPrompt
MINI_PROFILE_SESSION_HEADERsessionHeader

An empty variable value counts as unset — the setting comes from the next source down, the profile or the built-in default, so you can “clear” an override with an empty string. Both list variables at once (MINI_PROFILE_ENABLED_TOOLS and MINI_PROFILE_DISABLED_TOOLS) is a hard error, as is an unparseable value (not true/false, not a positive number): the session is not created, and the error names the variable.

Example — a 120-second tool-call timeout and bash disabled for all chats: set the variables MINI_PROFILE_TOOL_CALL_TIMEOUT=120 and MINI_PROFILE_DISABLED_TOOLS=bash.

MiniAgent, like the other backends, respects the network variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY: when the server reaches the internet through a proxy, provider requests go through it too, while addresses from NO_PROXY go direct. Details on the Models page.


The parallel_bash tool

parallel_bash is MiniAgent’s tool for running several independent commands in one call. The model decides which commands do not depend on each other (this independence contract is fixed in the tool’s description) and combines them into a single call:

parallel bash:
  - git status --short
  - ls pages/ | wc -l
  - df -h /project

The commands run concurrently: parallelBashThreads (5 by default) limits how many run at once, the rest wait in the queue. The call finishes after every command answers, and the result returns ordered [i] command sections — one per command, in input order, so the agent can match each output to its command. The trivial difference from bash: bash runs one command, parallel_bash runs a batch; both work on the shared ShellCommand core, and bash behavior is unchanged.


Loading pages and searching the internet

MiniAgent works not only with the files on the server: it can open pages on the internet and search for what it needs on its own. These are two separate tools — fetch for loading a page by address and search for searching. For a business this saves the main thing — time: no need to copy documentation, articles, and search results into the chat by hand. Just ask, and the agent brings the page content or a list of findings with links, and then works with it like ordinary text.

Page loading

fetch downloads a page by address and hands it to the model as readable text: the page markup is converted into plain text with light formatting, while content that already arrives as text, a data table, or markup for programs comes through as it is (the markdown: false argument returns the raw body unconverted). If the markup itself matters, the model can ask for the source content without conversion. A page too big for the conversation does not fit in: the agent receives it as a file and reads the pieces it needs with ordinary reading. In the compact view the call shows as the short line Fetch {url} with the address; in the normal view — as a call card with the same address and an expandable result.

Web search

search runs the query and brings a numbered list of findings: a title, an address, a short snippet, and the date when the engine provides one. If the engine answered the question itself, that answer arrives as an Answer: line above the list. The model decides how many results to ask for (the count argument, ten by default) and in what language to search (language, the two-letter code). In the compact view the call shows as the line Search {query} with the query text; the results expand right there, in the call card.

Several services and the fallback

Page loading and searching are handled not by the agent itself and not by one program but by a list of services — one you configure yourself. It is done this way because sites are very different: an ordinary page is enough to request directly, another one only answers through a proxy, a third is assembled by scripts and opens only in a real browser. Every service has a priority: the service with the lower number is tried first, and if it did not answer or answered with an error, the turn passes to the next one. So one broken key or an unreachable proxy does not stop the work — the next service in the list carries it. There is one exception: once a service has returned content, the HTML→Markdown conversion is a hard stop — a conversion failure is not replayed by the remaining services, because re-downloading the same address would reproduce the same failure.

The fetch.yml and search.yml files

Page loading and searching are configured in two different files of the project’s brand folder (.xedant/): loading in fetch.yml, searching in a separate search.yml. The two are built the same way, and each has its own services: section listing its services. An entry has five fields: name (the name the service is known by in messages), type (the service type), enabled (the switch), priority (the priority), and settings (the type’s settings — addresses, keys, time limits):

Here is what a fetching service looks like in fetch.yml:

# fetch.yml — page fetching only
services:
  - name: Direct HTTP
    type: Direct          # Direct | Proxied | BrowserEmulation | Nodriver |
                          #   RemoteBrowser | ScriptFetch (case-insensitive)
    enabled: true         # false never joins the chain (default: true)
    priority: 100         # lower is tried first (default: 100)
    settings:             # free-form map, validated against the type's schema
      UserAgent: "Mozilla/5.0 ..."
      TimeoutSec: "30"

And this is a searching service in search.yml — the section and the fields are the same, only the types and their settings differ:

# search.yml — internet search only
services:
  - name: Serper
    type: Serper
    enabled: true
    priority: 100
    settings:
      ApiKey: $SERPER_API_KEY   # the key comes from the environment

Secrets stay out of the files. Every settings value expands $VAR, ${VAR}, and ${VAR:-default} at call time — against the chat’s variables first, then the server process environment. An unset variable without a default keeps the literal text and logs one warning. So the file carries ApiKey: $SERPER_API_KEY, never the key itself.

Validation. Each entry has five keys: name (unique within its own file — attempts and warnings name the service by it), type (from the tables below, case-insensitive), enabled (default true — false never joins the chain), priority (default 100), and settings. A settings key the type does not know is a warning — the value is kept as written. A missing required key, a non-positive number, an off-catalog enum value, or a URL that is not an absolute http(s) address rejects the service; duplicate names within its own file and a non-positive priority are file errors. Both files are checked on save and at build — each file on its own, by the same rules as the other settings files, and the settings dialog refuses a save that breaks them.

It works out of the box — fetching. A fetch.yml with one enabled fetching service is created automatically on first start, so fetch works immediately without any setup; a file that fails to parse reads as the same default service, with one warning in the log. Searching ships with nothing — deliberately. search.yml is not pre-created: it appears when you save the first searching service. Ten of the eleven search types need an API key before they can do anything, so there is no built-in search service: until you add one, the search tool does not exist. A tool that errors on every call would be worse than a hidden one.

Fetch service types

TypeWhat it runsSettings (kind; default)
DirectPlain HTTP GET from this machineUserAgent (text; the built-in Firefox agent), ExtraHeaders (text; Key: Value per line), TimeoutSec (number; 30)
ProxiedThe same GET through the service’s HTTP proxyProxyUrl (url; required), ProxyUsername (text), ProxyPassword (secret), UserAgent (text; the built-in Firefox agent), TimeoutSec (number; 30)
BrowserEmulationA local Playwright browser renders the page (first use downloads it)BrowserType (chromium, firefox, webkit; chromium), WaitMs (number; 3000), UserAgent (text)
NodriverUndetected chromium drives the page through a self-provisioned Python venvWaitMs (number; 3000), TimeoutSec (number; 60)
RemoteBrowserAn external browser service renders the pageServiceUrl (url; required), Protocol (PlaywrightMcp, Zendriver; PlaywrightMcp), WaitMs (number; 3000), TimeoutSec (number; 60)
ScriptFetchA shell command fetches the URL and prints the JSON envelopeCommand (text; required), TimeoutSec (number; 60)

Search service types

TypeWhat it queriesSettings (kind; default)
SerperGoogle results through the serper.dev APIApiKey (secret; required), TimeoutSec (number; 30)
KeenableWeb results through the Keenable search APIApiKey (secret; required), TimeoutSec (number; 30)
SearXNGA self-hosted or public SearXNG instance, in its JSON formatBaseUrl (url; required), TimeoutSec (number; 30)
DuckDuckGoKeyless HTML scraping of DuckDuckGo results — fragile, expect rate limitingProxyUrl (url), TimeoutSec (number; 30)
BraveWeb results through the Brave Search APIApiKey (secret; required), TimeoutSec (number; 30)
TavilyWeb results plus an engine answer through the Tavily APIApiKey (secret; required), TimeoutSec (number; 30)
JsonSeoA search engine of your choice through the JsonSeo APIApiKey (secret; required), Engine (yandex, google, bing; yandex), Region (text), TimeoutSec (number; 30)
TinyfishWeb results through the Tinyfish APIApiKey (secret; required), TimeoutSec (number; 30)
ExaWeb results with highlights through the Exa APIApiKey (secret; required), TimeoutSec (number; 30)
AnysiteA live scrape of the engine of your choice — slow, credit-pricedApiKey (secret; required), Engine (bing, brave, baidu, startpage, yandex; bing), TimeoutSec (number; 120)
ScriptSearchA shell command runs the query and prints the results envelopeScriptKey (text; required), Args (text; a JSON object), TimeoutSec (number; 60)

The Fetch services and Search services tabs

Editing the list by hand in the file is not required: in the MiniAgent dialog, next to the profiles, there are the Fetch services and Search services tabs. The first tab writes fetch.yml, the second — search.yml: two independent files and two independent saves, each against its own last-read checksum. Everything else about them is identical:

  • The list of services — in priority order, with add, edit, duplicate, and delete; beside it the enable switch, the priority field (“A lower number is tried first”), and the hint that a new service’s priority is set one above the current maximum — that is, it is tried last;
  • The form follows the service type — pick a type and the fields appear on their own: the name is filled in from the type, required fields are marked, keys and passwords are masked and shown by a button, and every field shows its default value;
  • “Test” — runs one service: fetching is checked against a simple page, searching with a small query. You see success, latency, the explanation, and a sample of the answer. The test runs the saved file, so save your edits first — the dialog warns about that;
  • Copying and pasting — a service definition can be copied to the clipboard and pasted back or into another project, as JSON — one service or the whole set at once: identical settings travel between instances without manual entry;
  • Error and conflict protection — saving each tab validates only its own list by the same rules as the file (an unknown type, a missing required setting, a duplicate name, a non-positive priority) and is rejected naming the service and the field; if the file was changed outside the dialog (the project settings text tab, a text editor), the tab offers to reload exactly that file instead of silently overwriting the outside edit. Each file has its own update event, so editing one never resets the other. A save runs the file’s validation build.

When there are no services and when edits take effect

Disable every fetching service — and the fetch tool simply does not exist for new chats: the model request carries neither a tool description nor a mention in the instructions. Searching works the same way: while there is no search.yml file or all of its entries are disabled, there is no search tool in the chat. A missing fetch.yml does not switch fetching off, though: the server creates it at startup with the built-in Direct service. The settings are read once, at chat creation, so catalogue edits apply to new chats, and a conversation already underway finishes with the previous list.


Subagents

The agent tool lets the model launch a separate subagent — a nested session with its own context and its own journal. It is the same trick as “subtasks” on command-line agents: a big task is split into parts, and each part works in a clean context without cluttering the main conversation.

  • The call carries a task description and detailed instructions — the argument shape of a command-line agent’s subtask tool;
  • the nested run shows up as a separate child chat linked to the parent: its messages, spend, and cost appear in real time, while a subagent summary grows in the parent chat;
  • the subagent’s final reply (truncated to the shared output caps) returns to the parent as the tool result;
  • a subagent runs without the chat’s skill, without MCP servers, without hooks, and without the agent tool itself — it cannot launch a subagent of its own;
  • stopping the parent chat reaches the nested run too, and the child chat keeps everything that run managed to produce.

Several subagents at once

When one answer contains several agent calls, they start simultaneously: the cards of all the calls appear at once, and the results come back in call order. How many subagents of one chat run at a time is set by the profile’s maxParallelAgents setting (4 by default): extra calls queue up and start as soon as a slot frees. The limit is shared by the whole chat — ordinary and background tasks wait in the same queue.

Background tasks

Three separate tools exist for long work. agent_start queues a task and hands back its number at once. agent_check reports the task’s state, and once it has finished — its final answer or the error text. agent_stop stops a running task or cancels one that is still waiting for its turn.

  • The outcome arrives by itself. Nothing has to be polled: a finished task brings its result into the current turn on its own, and it is visible on the agent_start call line — as an expandable result, exactly like an ordinary call’s. While the chat still has unfinished background tasks, the turn does not close;
  • A short label instead of the number. In the chat, background calls are shown as a plain-language line — “Start …”, “Check …”, “Stop …” — with the task name the model came up with, not with its number;
  • The result is not lost. A task’s outcome is kept on the server: you can come back to it by the same number — in another turn, and after an application restart. Tasks cut short by a server shutdown are closed out with a stop note the next time it starts;
  • Stopping the chat takes everything down. If you stop the parent chat, all of its background tasks end: the running ones are stopped, the waiting ones are cancelled. The child chat keeps everything the subagent managed to produce, plus the stop note; a cancelled waiting task has no child chat at all.

MCP servers

MiniAgent connects the MCP servers enabled in mcp.yml itself — no Claude Code command line is needed for it. The same three transport types are supported: local processes (stdio), remote servers over http, and the legacy sse.

Servers connect not at startup but at the first message of a chat. Disabled entries are skipped. If a server did not start or did not answer, the chat keeps working and a warning naming the server goes to the log: one broken server neither drags the others down nor breaks the conversation. In commands, arguments, environment variables, addresses, and headers the entries $NAME, ${NAME}, and ${NAME:-default-value} are expanded — against the chat variables first, then the environment; an unset variable stays as is with a warning. When the chat stops, the connections are closed and the local server processes are killed, so stopping does not wait for them to exit.

How to set up servers and what lives in mcp.yml — on the MCP Servers page.


Hooks

The rules from hooks.yml apply in mini chats too: blocking a tool, checking before its call, actions on conversation events. The same catalog is passed both to the command-line backends and to MiniAgent, so rules do not have to be set up twice.

The list of events, deny rules, and the per-rule time limit — on the Hooks page.


The profiles dialog in settings

The dialog opens from the “MiniAgent” card in the Configuration group of the settings hub (the gear in the header) — more about the hub on the Settings page. The dialog edits the same miniagent.yml a text YAML editor would, but as a form:

  • Profile list — create, rename, and delete. The name follows the mask ^[a-z0-9][a-z0-9_-]*$: a lowercase letter or digit, then lowercase letters, digits, hyphens, and underscores — and it doubles as the mini:name suffix;
  • Profile editor — the loadClaudeMd/loadAgentsMd toggles, tool toggles with an “N of M tools enabled” readout (they edit disabledTools), numeric fields with default-value hints, and a system-prompt editor with a preview of the built-in one. Among the numeric fields there is “Max parallel agents” — how many subagents of one chat to run at once (4 by default, with the hint “Subagents of one chat running at once; extras queue. Default: 4”); zero or a negative number cannot be saved. The Reset to default button clears the prompt text — the built-in one is taken fresh from every application update, never copied;
  • Built-in defaults summary — shown next to the list;
  • Conflict protection — every save passes a checksum check (md5): when the file has changed in the meantime (an edit in another client, a text editor, or the Project Settings tab), the server answers 409 and offers to reload the dialog — your edits are never silently overwritten;
  • The same validation as YAML — saving from the form and editing as text pass the same rules (profile names, mutually exclusive lists, number ranges) and give the same errors; the validator runs as a pseudo-build.

Settings freeze at session creation: a live chat works with the profile it was created with, and edits apply to new sessions — switching the profile or the model recreates the session. One more subtlety: when the profile disables the load_skill tool, the “Start by loading the … skill” line disappears from the system prompt — demanding a skill load from a tool that does not exist makes no sense. And when the tool does run, the skill arrives whole, whatever its size: the general output cap does not apply to load_skill — capping the very call that pulls the skill into the context would defeat it.


Retry Settings

The provider does not always answer at once: the service is overloaded, there are too many requests, the connection dropped. Instead of ending the turn with an error right away, MiniAgent repeats the request — and often the answer arrives on the retry. How long to wait between attempts and how many attempts to make is up to you: the settings hub has a Retry card in the Configuration group (the gear in the header). More about the hub on the Settings page.

The card opens the Retry Settings dialog with two fields:

  • Retry interval — how many seconds to wait before retrying a failed request, 60 seconds by default;
  • Max attempts — how many times the request is sent in total (the first request plus its retries) before the error fails the chat, 10 by default. Only a whole number greater than zero is accepted, otherwise an error appears under the field;

The pause is always the same — it does not grow with every attempt. An empty field means “go back to the default”. The dialog footer shows where the settings file lives — Config location: and the path .xedant/retry.yml. The Cancel and Save Changes buttons close or save the dialog, and a successful save confirms with “Retry settings saved”. The file looks like this:

retryIntervalSeconds: 60
maxAttempts: 10

Only transient failures are retried: an overloaded service, rate limiting, 400, 429, and 5xx responses, dropped connections. A 400 that states a reason is retried too — that route proved unstable. Cases a retry cannot change — exhausted account limits and credits — the chat reports immediately, without waiting out the remaining attempts (at the default values that saves up to nine minutes of waiting).

Every retry is visible: a failed attempt shows in the chat as its own line with a yellow (warning) highlight, naming the model, the attempt number out of the total, the failure cause, and the wait before the next request. The line is not an error — the answer usually arrives on the retry, so the chat gets no “error” label; the message about the error and the error label on the chat appear only when the attempts run out (only your new message or a continue clears it). Interrupting the answer during the pause cancels the retry.

Every attempt is paid: the provider processes and charges each request, and the spend of failed attempts is added to the turn’s spend — the chat and the analytics numbers show the real bill. How the provider’s cache softens a retry is described on the Context Utilization page.

The same file can be edited as text in the project settings tab and in any editor — a change is picked up while the application runs. If the file is corrupt, the dialog shows the defaults and explains that saving replaces the broken file. If the file was changed elsewhere, the dialog warns: “retry.yml changed outside this dialog. Your edits were not saved.” — with a Reload button. Settings apply to new sessions: an active chat finishes with the policy it was created with, and a broken file does not break chats — the defaults keep working. The file is checked at build time as well: unknown keys and a number below one are caught, just like in the other settings files.


A practical example

The “safe” profile — bash off, a 60-second call timeout. Create it in the dialog: Settings → Configuration → MiniAgent → “New profile”, name it safe, turn the bash toggle off, set toolCallTimeout: 60, and save. The equivalent file:

profiles:
  safe:
    disabledTools:
      - bash
    toolCallTimeout: 60

Now assign it to a model: in the model wizard on the Models page, set the AGENT_BACKEND=mini:safe variable (in yml — a line in the variables: list). Chats on that model will run without shell commands and cap every tool call at 60 seconds — everything else stays built-in.


  • MCP Servers — external tools and data sources that MiniAgent connects on its own;
  • Hooks — deny and execute rules shared by the command-line backends and mini chats;
  • Settings — the MiniAgent card and the settings hub;
  • .xedant Folder — the project configuration files, including the fetch.yml and search.yml service catalogues;
  • Models — the AGENT_BACKEND variable, choosing a profile by model, and the image-input flag;
  • Skills — skills in the chat and the load_skill tool.

← Back: Backends