Build with SwarmBuild guide
Build an AI agent for your website that can only do what you allow
A website agent faces strangers, so it should be able to do exactly what you allow and nothing else. Swarm calls that a sealed agent: no shell, no files, no web, only the tools your app defines and answers itself. You describe the agent and its tools in JSON, give your server a token that reaches only that agent, and your server answers each tool call with the visitor's own data. Ours answered "where is my order?" in 5.1 seconds with one tool call.
How the pieces fit
- The visitor types in a chat on your site.
- Your server (the gateway) holds the agent's token and passes the message on.
- The sealed agent on your Swarm machine reads it and may call one of your tools.
- Your server answers the tool call from your own database, as that visitor. The model never decides whose data it sees.
- The reply goes back to the visitor.
1. Describe the agent and its tools
A tool is a name, a description, a JSON Schema for its input and an effect. Swarm checks every call against the schema before your server sees it.
{
"tools": [
{"name": "lookup_order", "description": "Look up the visitor's order by its code.",
"input_schema": {"type": "object", "properties": {"order_id": {"type": "string", "pattern": "^[A-Z0-9]{6}$"}},
"required": ["order_id"], "additionalProperties": false},
"effect": "read", "timeout_ms": 5000}
],
"agent": {"name": "frontdesk",
"prompt": "You answer visitors' questions about their orders for a small online shop. Use lookup_order when they give an order code. Be brief.",
"tools": ["lookup_order"]}
}Load it on the Swarm machine. Our machine answered Sealed agent frontdesk saved with 1 client tool(s).
sudo swarmctl setup sealed-agent --stdin < frontdesk.json2. Give it a scratch folder and a narrow token
A sealed agent's conversations live in a workspace. Point it at a dedicated empty repository, never your real code:
mkdir -p /srv/frontdesk-scratch && cd /srv/frontdesk-scratch && git init -b main \
&& git commit --allow-empty -m scratch
sudo bash /var/lib/swarm-headless/install.sh workspace add /srv/frontdesk-scratch --for-user $USER
# then your AI registers it: swarm_add_workspace /srv/frontdesk-scratchMint the gateway token into a file only you can read. It can start and use this agent's conversations and answer its tool calls, nothing else: it cannot list conversations, reach another agent or change tools. When we tried to list sessions with it, Swarm answered 403.
(umask 077; sudo swarmctl setup sdk-token --agent frontdesk --name gateway \
--messages-per-minute 30 --sessions-per-hour 100 --max-concurrent-runs 4 > gateway-token.json)3. Answer it from your server
Install the SDK (npm install @swarm-agent/sdk, Node 22 or newer). Set SWARM_API_URL to the Swarm machine's API address (port 7781 on its loopback, or wherever you tunnel it). This is the whole gateway loop for one message:
import { readFileSync } from 'node:fs';
import { SwarmClient } from '@swarm-agent/sdk';
const { token } = JSON.parse(readFileSync('gateway-token.json'));
const swarm = new SwarmClient({ baseUrl: process.env.SWARM_API_URL, token });
// Your shop's data. Whose order a call may see comes from your session, never from the model.
const orders = { K7Q2M9: { status: 'shipped', carrier: 'DHL', eta: 'Friday' } };
const chat = await swarm.sessions.create({ agent_name: 'frontdesk', workspace_path: '/srv/frontdesk-scratch', title: 'Visitor chat' });
const { reply } = await swarm.agents.converse(chat.id, 'Hi, where is my order K7Q2M9?', {
lookup_order: async ({ order_id }) => orders[order_id] ?? { error: 'no such order' },
}, { timeoutMs: 60000 });
console.log(reply);What came back, 5.1 seconds after the message was sent:
{
"tool_calls": ["K7Q2M9"],
"reply": "Your order (K7Q2M9) has shipped via DHL and is expected to arrive this Friday."
}Why it is safe to face the public
- No built-in tools. The agent cannot run commands, read files or browse. If someone later gives it a built-in tool, its token stops working instead of gaining it.
- Calls are checked. Arguments are validated against your schema before your server sees them; your answer goes back to the model marked as untrusted.
- Identity is yours. Your gateway decides whose data a call may see. The model supplies only inputs like an order code.
- Limits hold whatever the model does. Messages per minute, conversations per hour, concurrent runs, and per-visitor caps are set on the token.
- A person can take over. With an operator token someone on your team takes a conversation, replies as themselves and hands it back.
Questions
How do I add an AI agent to my website?
Run a sealed agent on Swarm with the tools your site allows, mint a gateway token for it, and have your server pass visitor messages to it with the SDK's agents.converse, answering each tool call from your own data.
Can visitors make the agent run commands or read files?
No. A sealed agent has no built-in tools at all: no shell, files, web, delegation or memory. It can only reply and call the tools you defined, and your server answers those.
Does the website hold the Swarm token?
No. Your server holds it. Browser code never holds a daemon token; the token itself reaches only that one agent's conversations and tool calls.
How fast is it?
In our run, 5.1 seconds from message to reply, including one tool call, on Gemini 3.8 Flash. It depends on the model and on how fast your tools answer.
What does it cost?
Swarm is free and open source; the model runs on your API key or plan. Set per-visitor and per-token limits so one visitor cannot use up the budget.
Updated 28 October 2026