Repository navigation
v0.8.2
Added
-
agents: namespaces — a server now serves any number of them, and a
user works in one at a time. Everything lives inside a namespace (agents,
LLM configs, skills, sessions, files, vector stores, workflows, MCP servers,
tool settings, MCP registrations); only users, API tokens and the namespaces
themselves are installation-wide. Workflows, MCP servers and vector stores
follow the namespace of the request like every other store; a new namespace
starts without any of them (the bundled MCP registrations are seeded into the
default namespace only). The helper agents a namespace needs — the title
generator, the summarizers — are created there on first use, on the
namespace'sagent-default(or first) LLM config. A chat's title is now
generated by a task of its own (agent.title), submitted together with the
first turn and run in parallel with it from the user's message alone: it
shows in the task monitor, survives a restart, runs in the turn's namespace,
and the turn's handle resolves once both are done — so the title is there
when the answer is. The task monitor — the header badge, its
dialog and the live updates — shows the tasks of the namespace you are in. In the Admin UI the header shows the current namespace:
switch from the menu, create a new empty one and fill it from the Registry,
or open Namespaces & members to see who works where. Your profile lists
the namespaces you may work in, with Switch to and Invite… on each row;
the invite dialog takes the other user's user name (someone who never
signed in is refused). Only the creator of a namespace invites, removes members, renames
it — and deletes it, with everything in it: the directory under the data
directory, or every row of it in Postgres and its pgvector tables. Any
other member can leave. Whoever loses a namespace this way is back in the
default one. A namespace cannot be calledsystem,ns,api,adminor
v1. The header switch is a POST. Fixes from a review of the branch: the
live task stream no longer shows a namespace its viewer was removed from;
the working-directory root follows the namespace of the call instead of
the one at start-up; a turn waits at most three hours again; MCP tool catalogs and pooled
connections are kept per namespace, so editing a server in one namespace
no longer drops another's connections; a malformedX-Mindconnect-Namespace
header is a 400. Two users creating a namespace with the same id at the
same moment get one namespace, not the second record over the first; and
a store's embedding config is always read in the store's own namespace.
A call to the REST API or the Responses API without a
namespace works in the default one — never in the one its user last chose
in the Admin UI; only the Admin UI follows the session and the remembered
choice. The choice is
remembered per user, so it survives a new browser session and a restart. The default namespace
(mindconnect.namespace,local) is open to every signed-in user, so an
installation that never creates another behaves as before. API clients name
the namespace in the address —https://host/ns/acme/api/…and, for
OpenAI-compatible clients, the base URLhttps://host/ns/acme— or in an
X-Mindconnect-Namespaceheader; the server answers with the namespace it
worked in under the same header, and with403when the caller is not a
member. Embedders see none of this: the builder still takes one namespace.
Storage moved: users and API tokens now live under
<data.base-dir>/system/(Postgres: without anamespacecolumn) instead of
insidelocal/; on an existing install sign in again and re-issue tokens.
No migration is shipped: a Postgres database from 0.8.0 or 0.8.1 still
hasmc_userandmc_api_tokenwith the namespace in their primary key,
and the new code cannot write to those tables — every sign-in record,
namespace switch and token creation fails. Drop both tables before starting
this version (DROP TABLE mc_user, mc_api_token;); they are recreated
empty, users reappear on their next sign-in. -
agents: the model's reasoning is shown in the chat — as a collapsed
card above the answer, like a tool call, whose header runs while the model
thinks and reads "thought for 4.2 s" once the first token arrives. Open it
to read along. A Qwen3, DeepSeek-R1 or gpt-oss model on LM Studio, Ollama,
vLLM or Groq used to leave the chat sitting on "AI is thinking" with nothing
to show for it — the OpenAI-compatible gateway now picks the reasoning up
from thereasoning_contentandreasoningfields as well as from inline
<think>tags in the content (which no longer leak into the answer). The
card comes back on reload, duration included: the message keeps its
reasoning inmetadata.thinkingandthinkingMs, on an answer and on a
tool-call turn alike. The REST stream carries it as athinkingframe, the Responses API as areasoning
item withresponse.reasoning_summary_text.deltaevents; the CLI stays
quiet. Claude's adaptive thinking shows the same way when the config asks
for it (thinkingDisplay: summarized). -
agents:
reasoning_efforton every OpenAI-compatible LLM config
(OpenAI, Azure, Groq, xAI, OpenRouter, Ollama, LM Studio, …) — a select in
the Admin UI form next to the provider's other parameters, or
"additionalParams": {"reasoning_effort": "high"}in the config JSON. Which
levels apply depends on the model. Local servers ignore the field; OpenAI
is only sent it with a reasoning model (gpt-5, o-series), since it rejects
it on any other. -
agents: an LLM config can name fallback models. When the provider
rate-limits it (HTTP 429) or reports itself overloaded (529) and the config's
own retries are used up, the same request is re-sent through the next config
infallbackModels, in order, until one answers — normally a config at
another provider, whose limit is a different limit. Configure it in the Admin
UI (Fallback models (on rate limit) in the chat settings: tick chat
configs and move them into the order they are tried) or as a
"fallbackModels": ["openai-default", "gemini-default"]list in the config
JSON. Omitting it keeps the previous behaviour: the rate-limit error reaches
the caller. A fallback is only taken before anything has streamed, so a
partial answer is never duplicated. -
agents: two providers more —
XAI(the Grok models) and
MOONSHOT(the Kimi models). Both speak the OpenAI API, so they arrive
with everything the others have: endpoint prefilled (https://api.x.ai,
https://api.moonshot.ai— set the base URL tohttps://api.moonshot.cnfor
Moonshot's mainland-China endpoint), model list in the form, retry, rate
limit and fallbacks. The provider dropdown now names the models a vendor is
known for, so Grok and Kimi are findable under XAI and MOONSHOT. The apps
register the OpenAI-compatible gateway as the default for every provider
rather than listing them one by one, so the next one is a single enum
constant. -
agents: the Admin UI's LLM-config form reads the model list from the
provider, so a model is picked rather than typed. LM Studio already did
this through its native API; now every provider that publishes a listing does
— OpenAI, Groq, Mistral, DeepSeek, Together, OpenRouter, Perplexity,
Fireworks and Ollama through/v1/models, Anthropic and Gemini through their
equivalents. Only models fitting the config type are offered — image,
text-to-speech, moderation and legacy completion models are left out — a
model the provider no longer lists stays selectable, and a listing that fails
leaves a text field carrying the reason. OpenRouter's list needs no API key.
Azure OpenAI keeps free text: its configs name a deployment, not a model. -
agents: registries — a Registry screen that installs LLM configs,
agents, workflows and whole packages from a GitHub project. A registry is a
repository, not a server: an index (registry.json) and the entity files it
points at, added by itsowner/repo(owner/repo@v1.2.0pins a tag, a
private one names the environment variable holding its token). Browse it
under Agents, LLM configs, Workflows and Packages, import — a package
installs the agent, its sub-agents, the workflow they run and the LLM config
they share, dependencies first and each entity once, with a report that says
line by line what was imported, updated, removed, skipped or failed. A
package's Contents tab lists everything it would install, marks what is
already here, and lets you untick entries to leave them out; Remove takes
a package out again, deleting the included entries and keeping the rest. An
entry that something outside the package still uses — the alias every agent
runs on, the config behind it — says Used by … and starts unticked.
Importing keeps what is already here unless overwrite is chosen, an overwrite
keeps local ids so that sessions and aliases keep working, and an API key
that came with a registry file is dropped rather than used. An application
ships registries as files underinitial-data/registries/; the admin UI
comes with mindconnect-ai/mc-registry,
the default agents, LLM configs and workflows plus an example package. Off
for an installation that wants no outbound calls
(mindconnect.registry.enabled=false); format and settings in the docs under
Registry. -
agents: skills — know-how written down once and loaded when it is needed,
instead of carried in a system prompt from the first token on. Only a skill's
name and description stand in the prompt, a line each; the instructions
arrive when the model calls the newskilltool for that name, so ten skills
cost ten lines until one is used and can be written out at the length the
work actually needs. Three sources, read fresh every round: the skills this
installation stores (the new Skills screen in the admin UI, or
/api/skills), a user's ownSKILL.mdfiles under
mindconnect.agent.skills.user-dir, and a project's in.mindconnect/skills/
under the session's working directory — same name means one skill, with the
more specific source winning, so a repository can say how its own reports are
written. The file format is the portable one: front matter forname,
descriptionandtools, the body for the instructions, either as
<name>/SKILL.mdbeside the files it refers to (the skill is handed over
with its directory, so a template or checklist is onefile_readaway) or as
a lone<name>.md. An agent gets skills from its newskillssetting
({"enabled": true, "names": [...]}, empty names meaning every skill there
is) in the edit form or overPUT /api/agents/{id}; theskilltool is then
injected and taken away with the setting, never assigned by hand, and it
offers the model exactly the names that agent may load. A skill grants
nothing: the tools it names are a hint, and the agent's own bindings still
decide what it may call. A first example skill is seeded on a fresh install,
and any stored skill can be fetched as aSKILL.mdto commit into a
repository. See Skills. -
agents: the Migrations page in the admin UI can apply a single field.
Every row of a diff table has its own Apply that takes just that value
from the bundled seed and keeps the rest of the stored record — so a changed
model name no longer costs you the API key you typed into the LLM config.
Backed byPOST /admin/api/migrations/apply-field?id=…&field=…. -
agents: the chat composer's "+" is a menu — files, images, tools and
sub-agents, instead of the attach dialog alone. The chat's agent is the
template the chat starts from: Tools lists every tool the registry can
hand out, each row Off, On (offered to the model up front) or Search
(left fortool_searchto find), and a group's switch sets all its tools at
once; Sub-agents lists every agent that may be called, each Off or On,
with a Test that sends it one message in a dialog and shows its answer.
Both start from what the agent brought and may add tools and agents it never
had; the dialog stays open while you switch. Add images is the attach
dialog with the file chooser narrowed to pictures. Chat endpoints added:
GET /chat/api/sessions/{id}/tools-dialog,.../subagents-dialog,
.../subagents/test-dialog?agent=;
POST .../tools?tool=&state=OFF|ON|SEARCH,.../tools/group?group=&state=,
.../subagents?agent=&on=,.../subagents/test;
GET .../attach-dialogtakes?kind=files|images.
Changed
-
agents: an embedded runtime built with
AgentRuntimeBuildernow forgets
finished task trees — a turn with its tool calls and sub-agent turns — at
the queue's next maintenance tick. The outcome lives in the conversation;
the task records only grew the process with every turn.taskRetention(Duration)
keeps them longer,taskRetention(null)for the life of the process, as
before. The Spring apps are unchanged. In the same spirit the in-memory LLM
trace store keeps at most 50 traces per conversation, the cap the file store
already had. -
agents: the Traces dialog is a table — one row per LLM call with
turn id, agent, model, duration, tokens and how it ended, newest first,
sortable by any column, paged by 20 and filtered by a search field (turn,
agent, model, finish, status); sub-agent calls are rows like any other.
Clicking a row opens that call in its own dialog with request, response and raw event
stream. The master-detail view it replaces grouped calls per turn and hid
most of them behind previews; it also read every request and response
body just to draw the list, which the table no longer does. -
agents: an agent's skills setting is a mode: All skills (the
default — an agent that never set it, or was stored before the field,
now has every skill instead of none), Specific skills (only the ones
ticked; none ticked is none) or None. In JSON that is
{"skills": {"mode": "SPECIFIC", "names": [...]}}on the agent and in
PUT /api/agents/{id}; the previous{"enabled": ..., "names": [...]}is
still read, so stored agents keep what they had. The seeded utilities —
the title generator and the summarizers — are set to None:
they answer in one shape and have no use for a skill. -
agents: in the agent form, Skills, Callable Agents and
Response Reviewers are checkbox lists instead of multi-selects — one
row per candidate, ticked or not, deprecated agents left out. The
reviewers' rows can be moved up and down, since they run in that order —
and only agents in thereviewergroup are offered there, plus whichever
the agent already names. File an agent under that group (it is in the
Group list now) to make it a candidate. -
agents: the admin UI's sidebar groups Registry and Migrations under
one Install entry — the two ways agents, workflows and LLM configs arrive
in an installation. The group opens by itself on either page. -
agents: delegating and tool search are explicit. An agent's
callableAgentsroster names the agents it may call — an empty roster now
means none, not all — and the runtime givesrun_agent,run_agentsand
list_agentsexactly to an agent whose roster names someone; they are no
longer listed as tools and are dropped from an agent file that still lists
them. Likewise an agent getstool_searchexactly when one of its tools is
deferred, and it finds only those: thetoolSearchsetting and its
registry-group filter are gone from agent files, the admin form and
PUT /api/agents/{id}(which takescallableAgentsandcallableByAgents
instead). An agent you relied on to reach every other agent needs its
roster filled in. -
agents: agents have a
callableByAgentsflag. The runtime's own helpers
(title generator, summarizers, the answer-relevance checker) set it to
false: no roster picker offers them andrun_agentrefuses them. -
agents: the seeded
default-chatsearches the web itself with
web_searchand hands single pages tourl-readerand codebase sweeps to
explorer, instead of sending every web question throughweb-researcher
and every file hunt throughfile-finder. -
agents: the chat's settings dialog is the agent, the model and the
system prompt — three fields, no tabs. The tool multiselect that used to
need a second tab moved into the composer's "+" menu, where tools are
switches rather than a form; the dialog
says so in a closing line. Applying it never writes the tool list any more,
so a chat that comes here to change its model keeps whatever it switched on
in the Tools picker. An LLM config that is an alias now reads as what it
points at (agent-default → openai-default) instead of
agent-default (null / null), and an agent is listed with what it is for
rather than by name alone. -
agents: every provider now knows its own API endpoint, so Base URL is
prefilled when a provider is picked in the Admin UI —
https://api.mistral.ai,https://api.groq.com/openai,
http://localhost:11434— and switching provider replaces a URL that was
only the previous provider's default. A URL you typed yourself is never
overwritten.baseUrlis now optional in a config JSON as well: left out,
the provider's endpoint applies instead of the call failing against anull
host. -
agents: a rate limit is now readable in the log.
HTTP 429used to be
logged as a bare status and a body; it now names the config and the model
that was limited, the provider'sRetry-Afterhint, and what happens next —
how many retries are left and which fallback models follow, or that neither
is configured, which is the case an admin can fix. The retry and fallback
steps log their own line, so one rate limit reads as one story from limit to
answer. -
agents: the admin UI's collapsible headings — tool and agent groups,
migration rows, trace cards — read at body size in the theme's text colour
instead of the framework's small grey detail style.
Fixed
- agents: deleting a session deletes its conversation, messages and LLM
traces too. It used to remove the session's memory, summaries, todos and
directory but leave the transcript and every recorded LLM call behind,
unreachable and growing — in every persistence mode.ConversationManager
gaineddeleteConversation,MessageRepositorydeleteByConversationand
ConversationRepositorydeleteById; a custom adapter of either has to
implement them. - agents: the admin UI keeps its menu after saving an agent, an LLM
config or a skill. Since saves started refusing a stale version, the detail
page they answered with came back without the app shell, and the only way
to the sidebar was the browser's back button. A session's memory, traces
and todos pages, opened outside their dialog, get the shell too. - agents: an agent reaches only the skills its setting allows. The
skill
tool could also be found withtool_searchor assigned by hand from the tool
catalog, and that copy carried no names — it offered every skill, even to an
agent with skills switched off, and sat beside the injected one as a second
tool of the same name, which a provider can reject. The setting is now the
only way an agent gets the tool. - agents: the Skills screen lists every stored skill again, including
one switched off or hidden behind a user'sSKILL.mdof the same name —
before, such a skill disappeared from the list and could only be reached by
its URL. Saving a second stored skill under a name one already has is
refused (a toast in the admin UI,409from/api/skills), since an agent
looks skills up by name and would silently get only one of them; a name no
model could type is a400from the API instead of a500. - agents: the Migrations page no longer reports every LLM config's
apiKeyas changed forever. The store encrypts keys on save, and the diff
compared that ciphertext with the bundled plain value — so applying never
made the row go away. Keys are now compared by what they decrypt or resolve
to, and the diff shows only that a key differs, never the value. - agents:
bashreliably notices a process the command left holding
its output after the shell exited — and kills it, or says it could not.
Whether that happened used to depend on timing: if the shell exited while
the tool was between two reads of the pipe, the JVM closed the pipe on its
own, the call returned without a word, and the process ran on unseen. The
same race madeBashToolOutputTestfail now and then in CI. - agents:
list_agentsanswers with the roster the calling session
actually runs under. It read the agent from the registry, so an agent that
lives in its session — a project's agent started as a sub-agent — was
shown every registered agent, and then refused byrun_agentwhen it
picked one outside its roster. - agents: attaching a file or switching a chat's working directory
mid-turn no longer swaps the composer's Stop button for a Send button.
Anything that redraws the composer now renders it in whichever state the
session is actually in. - agents: editing the system prompt of a chat that has no agent behind it
is kept. The settings dialog submitted it and the handler then rebuilt the
chat's agent from its own previous prompt, so the edit vanished on Apply
with no error — a chat bound to an agent was unaffected. - agents: leaving an agent behind ("no agent" in the settings dialog) no
longer changes what the chat can do. It kept only the tools the registry can
resolve on that machine, so a chat detaching on a host without Gmail
credentials silently lost the agent's Gmail tools, and it dropped the
agent'scallableAgentsroster, which handed the chat the run of every
registered agent. Both are carried over now, bindings and all.
What's Changed
- Registries: import LLM configs, agents, workflows and packages from a GitHub project by @beisdog in #81
- Skills — instructions an agent loads when it needs them by @beisdog in #83
- Fix skill review findings: tool binding, Skills screen, unique names by @beisdog in #84
- LLM configs: rate-limit fallbacks, provider model lists, xAI and Moonshot by @beisdog in #85
- The Migrations page can apply a single field, and stops flagging every api key by @beisdog in #86
- Fix/uploads are files too by @beisdog in #87
- bash keeps the pipe open between reads, so a process left holding it is seen by @beisdog in #88
- Chat "+" menu with explicit tools and sub-agents; derive delegation and tool search by @beisdog in #89
- Show the model's reasoning in the chat, and reasoning_effort on OpenAI-compatible configs by @beisdog in #90
- Group Registry and Migrations under an Install entry in the admin sidebar by @beisdog in #91
- Keep the admin shell after a save, checkbox pickers, and skills as a mode by @beisdog in #92
- Close the thinking card on every outcome, keep its duration, stop counting reasoning twice by @beisdog in #93
- feat(agents): show LLM call traces as a table with a per-call dialog by @beisdog in #94
- feat(agents): namespaces — a server serves any number of them, a user works in one at a time by @beisdog in #95
- ci: run the Postgres tests against a service container by @beisdog in #96
- fix(agents): delete a session's conversation and traces with it, bound the embedded runtime's task and trace stores by @beisdog in #97
- feat(agents): search, sort and page the traces table on the server by @beisdog in #98
Full Changelog: v0.8.1...v0.8.2