Agents

An agent is an instance of Xedant Agent on a managed factory. MultiAgent generates a dedicated compose.yml for every agent, deploys the container and watches its life cycle, while the agent’s chats land in the centralized interface.

Creating an Agent

The “Add Agent” button opens the wizard: first you pick the type — a standalone agent (an autonomous Agent instance) or one of the family products — the Research Agent, Analytics Agent, Data Agent, Proxy Agent, Chatbot, Telegram, Test Agent, CRM, News Agent or Portal Agent. Then the form: name, factory, image (filled in automatically for a product) and port — it is picked automatically from the ranges (5000+ for agents, 6000+ for products), so conflicts are ruled out. The wizard suggests a default name from the target factory’s brand wordmark (“Agent” on an English-brand factory). Optionally you set tags and the license (inherited from the factory by default).

Products deploy with a linked agent: the “Linked agent” setting points at the factory’s first standalone agent by default, and when the factory has no agents it offers “Create a new agent” — the wizard creates a full agent through the same mechanism, and the app receives its address and key for callbacks. Credentials (user password, manager password, JWT secret, API key) are generated automatically. Details in Products.

Life Cycle

  • Provision — generate compose.yml, pull the image and start the container;
  • Start / Stop / Restart — container control. “Start” appears only when the container is down, “Stop” and “Restart” only when it runs: there is nothing to restart in a stopped agent, so its button row keeps “Start”, “Recreate” and “Delete”;
  • Recreate — the single update action: it rewrites compose, pulls a fresh image and recreates the container. There is no separate “pull image” operation. The button became a list of two options — Graceful and Force;
  • Delete — stops and removes the container (if the factory is unreachable, the deletion still goes through), then removes the management record and the mirrored chats. The data folders on the factory are kept: only “Erase agent” removes them for good.

The difference between the options is chat business. Graceful is the ordinary recreate: when the agent has graceful updates on and its chats are busy, it is postponed and runs on its own once the chats go quiet. Force starts the recreate immediately, regardless of the chats, and cancels the update already scheduled — the way out when a chat hangs and there is nothing left to wait for. The same two options sit in the agent’s row menu of the navigation tree (“Recreate graceful” and “Recreate force”), and on a factory row they apply to all of that factory’s deployed agents and apps, one by one.

The row menu opens for any agent and app — a right-click on the row or the actions icon that appears on hover — no matter whether the container could be checked. That matters when a factory is unreachable: the items that read the record rather than the container (open, copy, move, erase) keep working. An unchecked state counts as deployed, so the menu offers “Start”, “Recreate” and “Delete”; “Stop” is offered only when the container is certainly running. When an operation fails, the connection error is shown honestly.

All operations run in the background, and progress arrives in the interface in real time — every step is visible: connecting to the factory, preparing the configuration file, downloading the image, starting the container. Provisioning, recreating and deleting also refresh the factory’s Nginx routing.

Standalone agents have a “Graceful updates” switch on the “General” tab (off by default; products don’t have it). While it is on, “Recreate” does not interrupt a working chat: when the agent is processing something or its last activity was less than 5 minutes ago, the update is postponed (a toast: “Update scheduled — it will run when the agent’s chats have been quiet for 5 minutes”), and a background service starts it on its own as soon as the chats go quiet for 5 minutes. A hung “processing” report does not hold the update forever: when the agent still reports processing but its chats have seen no activity for over 30 minutes, the report counts as stale and the update goes through — otherwise a hung chat would block the very update that fixes it. Internal configuration changes (database, SSL, git) are never postponed by a recreate.

The agent container’s status comes from Docker directly: running, restarting, stopped, paused, exited or dead.

While the container’s state is unknown — for example, right after a MultiAgent restart or during a connection break with the factory — the agent’s badge stays uncolored and no dot is drawn at its row in the navigation tree. Color is an assertion, and while we know nothing there is nothing to assert; the label next to the row says “Unknown” honestly. “Not deployed” is not a state but a sign that there is no container yet.

The state dot does not wait for a page reload: the agent list is re-read every time the browser reconnects to MultiAgent, and a background check runs every 10 seconds. A container started right on the machine shows up on the open page by itself. Saving environment variables or folders no longer wipes the state dot — the write returns the same known value the list does.

Editor Tabs

In the page header, next to the state badge, live container figures are visible: CPU load, memory used and disk space occupied (space is counted together with the image, so the number reflects the real volume). The figures refresh by themselves every 5 seconds, and hovering over the disk number hints how much the container has written and read. While the first measurement runs, a loading badge stands in place of the numbers, so figures of a previous agent do not flash instead of your own. The header has no link badges to apps or agents — links are still stored and available through the Agent API.

An agent’s or product’s name is changed right in the page header — a click opens the edit field: type the new name and press Enter; Escape cancels. The new name immediately lands in the browser tab title and in the navigation. The rest of the settings live on tabs:

  • Status — the container’s CPU, RAM and disk usage;
  • Logs — the last 300 lines of container logs;
  • General — name, tags, icon, image, options. The icon is picked in a searchable gallery and always paints the house gradient — the same cyan → blue → violet fill the real logos carry — while the background under it still shows the container’s state;
  • Git — the linked Forgejo repository and branches;
  • Connection — port, URL, address template;
  • Credentials — the agent’s access passwords;
  • Ports — the list of published ports; every row has a “Public port” switch that opens it to the outside of the machine;
  • Volumes — mounts on top of the auto-generated ones;
  • Environment — the agent’s own environment variables: KEY=VALUE lines that override the factory’s shared variables. An app (a product) has the same tab: its lines override both the factory’s shared variables and the template values, and a running app is recreated on its own so the values take effect;
  • Postgres — the agent’s database: storage mode (built-in, the factory’s shared database, or external), database name, user and password, a connection check and data migration from another factory’s database (standalone agents only);
  • Links — extra badges in the top-right corner of the agent’s tile on the factory home page: title, a route with a port or an external address, icon and color;
  • compose.yml — a preview of the final file with syntax highlighting;
  • Models — models and concurrent-chat limits;
  • Files — the factory file manager scoped to the agent;
  • Project Settings — the agent project’s settings;
  • Skills and MCP Servers — configuration dialogs of the agent itself (skills are the agent’s own skill files, not the MultiAgent catalog), opened from the agent page;
  • Tasks and Bots — the agent’s schedules and bots;
  • Prompts — the agent’s prompt queue.

compose.yml

The configuration file is generated from the factory’s template: ports come from the agent’s records; volumes and environment variables merge the automatic ones (factory folders, the Postgres string, the license) with your explicit values. While the central login is active on the factory, the SSO_PROXY_TOKEN secret is added to the environment — the app uses it to verify the identity headers nginx injects, so they cannot be forged from outside. The preview shows the final file before deployment — configuration mistakes are visible in advance.

Credentials

Every agent has two password operations: generating the user password (for signing into the agent’s web interface) and rotating the manager password — the password MultiAgent itself uses to call the agent’s API. Rotating the manager password recreates the agent’s container with the new value in its environment.

Docker.sock and Deployment

An agent can be given the machine’s /var/run/docker.sock (off by default, enabled per agent). This is needed when the agent itself must manage containers — for example, to deploy services from its own project. Keep in mind: with docker.sock the agent gets full control over the machine’s Docker — the socket belongs to the server and is shared by every factory on it — so enable it only for agents you trust.

Importing Agents

When a factory already runs agents deployed by hand, there is no need to recreate them. The “Import Agents” command scans the factory, finds agent containers, parses their compose files and registers the agents in MultiAgent, preserving ports, volumes and environment variables.

Copying and Pasting Agents

To make a second agent just like this one, there is no need to fill the wizard in again. The agent’s row menu has “Copy agent”: the agent’s definition — with all its settings and credentials — goes to the clipboard. The factory’s row menu has “Copy agents” (every agent and app of the factory at once) and “Paste agents”.

Pasting creates new rows on the factory you choose: on the same factory you get a copy, on another one a row just the same, but empty for now. Occupied slugs and ports resolve themselves — the new agent gets free ones, so nothing conflicts. Credentials travel too, so a copied agent keeps working without being set up again. The rows are created undeployed: the container is started from their page, as with any new agent.

Only the agent’s definition travels through the clipboard — settings and credentials, but not files and not the database. To move an agent together with its data there is a separate command — the next one.

Moving an Agent to Another Factory

An agent can be moved together with its files and database with the “Move agent” command in the agent row menu. The factory row menu has “Move agents” for this (all the factory’s agents and apps at once) and “Move all”. First the target factory is chosen, then the work runs by itself, and the whole progress is visible in the log — in the task panel, where the move can also be stopped with “Cancel”.

For each agent the move goes step by step: a row for the agent is created on the target factory, but not deployed — as when pasting from the clipboard; then data folders, the home folder and projects are transferred, with the amount already moved shown; for agents on the factory’s shared database, the database moves too. Occupied names and ports resolve themselves. The move leaves the source factory unchanged: the agent keeps working there, and you can remove it from there separately — with “Erase agent” — once the move has finished. At the end the log reports the outcome: how many were moved out of how many. If some row failed, the rest are still moved — the failed row is visible in the log, and the move can be repeated, overwriting the data in place. A move creates new records, so it is available only with a valid license.

Erasing an Agent

The “Erase agent” command in the agent row menu removes it from the factory for good: the container, all data folders, the database and the management record. In the factory row menu the same actions exist for all agents and apps at once — “Erase agents” and “Erase all”. A warning is shown before it starts: erasing cannot be undone. The progress runs in the task panel’s log, can be stopped with “Cancel”, and at the end the outcome shows: how many were erased out of how many.

If folders or the database failed to erase for some reason (the factory is unreachable, permissions are lacking), the agent’s record is kept and the failed row is marked red in the log: the agent stays in the list, and the erasure can simply be repeated — neither the record nor the data disappear silently. Erasing does not depend on a license: it only deletes.

Reverse Proxy and the Agent’s Address

The primary way in is a subfolder on the factory’s Nginx. Every agent gets an address of the form {base}/{slug}/: the factory’s Nginx container (installed from the Nginx tab) proxies the subfolder to the agent’s container over the internal docker network, and a certificate — self-signed, your own pair, or Let’s Encrypt — covers HTTPS. Apps connect container-to-container, so no ports need publishing to the outside: an undeployed or crashed agent returns 502 only on its own subfolder. Details on the Nginx Routing page.

The agent’s ports are closed to the outside world by default: a new row is published only inside the server itself (at the 127.0.0.1 address). From the outside the agent opens through its subfolder, and neighboring factories on the same machine do not see its ports. A port can be opened to the world with the “Public port” switch on the row you need, on the Ports tab — the change takes effect on recreate. The exceptions: the Nginx web server itself and the backup receiver are always public, while the shared Postgres database, on the contrary, is always closed.

When the central login is enabled on the factory, agents and products are locked “behind the central login” by default: the visitor signs in once on the factory’s login page and the agent’s subfolder is already open — the agent’s own login is not needed. You can lift the protection from a specific agent (or product) with the “SSO protected” switch on the “Connection” tab. Service machine paths /{slug}/api/… and /{slug}/svelteChatHub stay open — they have their own authorization (JWT or API key), so managing agents through MultiAgent keeps working. Direct access at host:port, bypassing nginx, is not locked either: the agent’s own login applies there. More about protection in the “App protection” section of the Nginx Routing page.

The older scheme still works as a fallback: every agent is reachable directly at http://{server}:{port} (a self-signed certificate can be enabled with one switch for encryption), and the “Address” field on the connection tab accepts any URL of yours — for example when the agent sits behind an external tunnel. An overridden address is honored everywhere: API tests, proxy requests, chat synchronization and compose.yml generation.

MultiAgent also works as a relay between the browser and the managed agents’ APIs: requests like /api/agents/{agentId}/proxy/... are forwarded to the agent’s API on the manager’s behalf (if the sign-in has expired, it refreshes itself and retries). Because of that, the browser and external integrations talk to agents through MultiAgent — no need to open agent ports to the outside.

Image Catalog

Instead of a fixed image catalog there is a product catalog: from the Add Agent wizard, one dialog installs the eleven family products — MultiAgent (6000), Research (6010), Analytics (6020), Data (6030), Proxy (6040), Chatbot (6050), Telegram (6060), Test (6070), CRM (6080), News (6090) and Portal (6100) — each with its real logo, a port from the product’s range and generated credentials. Product templates live on the MultiAgent disk in the AGENT_PRODUCTS folder and are added simply by dropping in a new folder. For a standalone agent the image is picked from the factory’s catalog — and you can extend it with your own images. The catalog also carries the debug builds of the private registry2 registry, after the public entries — they exist to try a new version before its release.

Forgejo Repositories

Every agent can be linked to a git repository: an existing one on the Forgejo Git server, or a new one MultiAgent creates itself. The access key is issued and stored automatically. The repository is mounted into the agent as its project folder — every commit the agent makes goes straight into git.

Extra Links

An agent’s or app’s tile on the factory home page can carry your own badges — quick links to places related to the app. Every link used to take a tile of its own, so one agent with three links ate four slots; now the badges sit in a small row in the top-right corner of the agent’s own tile, with the name shown on hover. A link is defined on the “Links” tab and has four parts: a title (the tooltip), a route with a port — then the link opens on the factory at {base}/{slug}/ and leads to that port; an external address — when no route is needed, the badge simply opens that address; an icon and color — from the Material Symbols set, or your own color. This is how, say, links to an agent’s control panel or status page appear on its tile with no manual web-server edits. Next to the add button there is “Apply configuration”: it applies the links’ routes to the factory’s web server right away.

Database Migration

A standalone agent can receive data from a database on another factory. On the “Postgres” tab pick the source factory, the database container (usually agents-postgres) and the database you need, then press “Migrate” and confirm. MultiAgent itself takes a copy of the database, transfers it to the target factory, clears the target database, restores the data and hands it back to the agent — every step is visible in the progress feed. The agent’s container stops for the migration: after it completes, simply start the agent again. When something goes wrong, the failed step is handled and the target database stays untouched.

← Back to documentation