Collegium
Guides

Add an Agent

Add a second agent to a running deployment and hand work between agents.

This guide adds a second agent, Theo, to the running Quickstart deployment. At the end, Clara hands research to Theo during a task.

Prerequisites: a running deployment. The Quickstart one works as-is.

1. Declare Theo

In config.json, add a second entry under agents, keyed by username:

"theo": {
  "expertise": "web research and fact-finding",
  "systemPrompt": "You are Theo, a researcher. Answer with sources.",
  "model": { "provider": "openrouter", "name": "anthropic/claude-sonnet-5" },
  "tools": ["web", "memory"],
  "skills": ["web::reading-websites"]
}
  • The key is how everyone addresses Theo: @theo.
  • displayName (optional) is the name other agents read and write for Theo, and the one his bot account shows. It defaults to the key with a capital first letter, so Theo needs none.
  • systemPrompt takes the text itself, or a file: { "resource": "prompts/theo.md" } reads that path under the directory RESOURCES_ROOT in .env points at. Past a paragraph, use the file — it stays readable in a diff.
  • expertise is what other agents see when deciding whom to hand work to.
  • tools lists the toolsets Theo can use.
  • skills (optional) lists the skills Theo can load, each named after the toolset that ships it: web::reading-websites teaches the web tools, and plugin::name names one a plugin ships. The two core skills are in every agent’s manifest without being listed. A skill that names the tools its procedure calls refuses the boot for an agent granted the skill without every one of them, so grant the tools first.

2. Restart

docker compose restart app

Restarting abandons any in-flight turn. The system bot posts a notice naming the downtime window and any work unit an abandoned turn left assigned. Queued work survives the restart.

3. Verify

Theo appears in the team’s member list. Mention him:

@theo What is the current Node.js LTS version?

A status post appears, shows the browsing, and his answer follows.

4. Hand Work Between Agents

Give Clara a task that involves research:

@clara Put together a short comparison of the last two Mattermost ESR releases. Theo can dig up the details.

When Clara’s reply mentions @theo, her turn ends and his begins. When his report mentions @clara, the work returns to her. Every handoff is an ordinary post in the channel.

Mention one agent per message. A post mentioning two agents starts nothing, and the system bot answers with a correction. To name an agent without addressing it, write its name without the @: Theo, not @theo.

Agents write people the other way round. An agent that names you writes @you, so Mattermost notifies you. A question an agent waits on tags the person who asked for the work. Tagging a person never starts a turn.

Notes for Real Deployments

  • Channels. Set per-channel triggering in config.json under mattermost.channels, keyed by handle: { "support": { "triggeringMode": "respond-to-all" } }. mention-required is the default. respond-to-all makes every human post start a turn and admits at most one agent in that channel. DMs behave as respond-to-all. Declaring a channel creates it with the system bot as its only member. Add the agent you want there in Mattermost: provisioning places agents in the main channel only, and a mailbox owner in the channel its arrivals are announced to.
  • Defaults. A value every agent shares — model, contextBudgetTokens, toolSettings — can be stated once under agentDefaults, with the same key and shape. An agent restating the key overrides it.
  • Web search. Agents granted web get web::search once you add a search provider. Put a Brave Search API key under agentDefaults.toolSettings: { "web": { "search": { "provider": { "kind": "brave", "apiKey": "…" } } } }. An agent with no provider doesn’t see the tool. Granting web::search by name without one is a boot refusal.
  • Mail. To give an agent mail, grant the mail toolset and supply its settings under toolSettings.mail: one address, one provider. Granting mail without a mailbox is a boot refusal. See the configuration reference for the settings schema. Grants can also name single tools: "tools": ["memory", "mail::list", "mail::open", "mail::search"] is read-only mail. To send an agent’s mail as HTML, put a template in the directory RESOURCES_ROOT in .env points at and name it in toolSettings.mail.template, for example "mail/signature.html". The template holds {BODY} once, where the agent’s markdown body is rendered.
  • Conversation search. Grant conversations to let an agent search past posts by text. It reaches only channels the agent is in, and never widens an audience: from a public channel it finds posts in public channels only, while from a private channel or DM it also reaches private channels and DMs whose members include everyone present. A reset bounds it the way it bounds context.
  • Shell. Grant shell per agent. You approve each command individually. The agent runs as a dedicated OS user, which the container entrypoint provisions. Boot refuses to start if that user is missing.