Agents
Agents are non-login identities in a repository. Each one has a home under ~/agents/{id}/, a soul you write, event prompts for inbound mail, Slack, and agent messages, and an address on inbox.sails.app.
Creating an agent does not start work. Mail to it, a Slack mention, a message from another agent, or goal does. Do not publish agents/ as a site root.
Before you start
- You need the
ownerrole to create, remove, grant, or jail. Runcapabilitiesto see your role. - Commands that change the agent's own address (
agent claim,agent unclaim) act on the current identity. As the owner, pass--as AGENT(name or ID), orsu AGENTfirst. agent showand most other commands take a name or an ID.agent rmtakes the ID only.
Done looks like
agent show support-bot prints JSON. After the worked example below it looks like this (org ryan, IDs shortened):
{
"address": "01a1…f8aa@inbox.sails.app",
"claimed_address": "ryan-helpdesk@inbox.sails.app",
"filesystem": "jailed",
"id": "01a1…f8aa",
"jail_paths": ["agents/01a1…f8aa"],
"jailed": true,
"mail_inbox": "agents/01a1…f8aa/mail/inbox",
"mail_username": "helpdesk",
"name": "support-bot",
"site_grants": ["sites/crm"],
"slack_inbox": "agents/01a1…f8aa/slack/inbox",
"soul_path": "agents/01a1…f8aa/soul.md"
}
filesystem is one of disabled, jailed, or full. The soul prints with agent soul support-bot.
Worked example
agent create support-bot
# prints JSON with the new id and {id}@inbox.sails.app
# filesystem starts as "disabled"
agent soul support-bot --stdin <<'EOF'
# support-bot
You are the CRM support assistant. Be concise. Prefer tools over guessing.
First tool call on inbound mail is thread_show for that thread.
EOF
# or: agent soul support-bot --file ./souls/support-bot.md
agent claim helpdesk --as support-bot # {org}-helpdesk@inbox.sails.app
# "support" is reserved
agent grant support-bot --site sites/crm # the folder must hold sails.site.json
agent jail support-bot --path agents/<id> # mailbox and home files for FS tools
agent jail support-bot --path sites/crm # optional: let FS tools touch that tree
agent show support-bot
su support-bot # act as the agent
su - # back to your login identity
Replace <id> with the UUID from agent create or agent show. A claimed username is unique per org across agents and folder inboxes. Passing {org}-helpdesk is the same as helpdesk.
To tear it down:
agent unclaim --as support-bot # the UUID address keeps working
agent ungrant support-bot --site sites/crm
agent rm <id> # ID only; a name fails with "invalid UUID"
agent list # confirm it is gone
Layout
~/agents/{id}/
soul.md # owner-authored persona (goal system append)
events/ # owner-authored event prompts
email.received.md
message.received.md
slack.received.md
README.md
mail/inbox/ # agent-owned mailbox
mail/sent/
messages/inbox/ # agent-owned agent messages
messages/sent/
slack/inbox/
slack/sent/
slack/files/ # inbound Slack attachments
soul.md, events/, and README.md belong to you (the creating user). The mailbox folders belong to the agent, and you also hold owner bits on them. agent show lists the email and Slack event paths; events/message.received.md is there too, even though show does not print it.
Canonical message bodies live under .sails/threads/{thread_id}/. Hydrate with thread show, not by reading those files directly. Agents should not rewrite their own soul. Use agent soul (owner).
Filesystem access vs site grants
These are separate knobs.
| Mode | How you get there | Agent FS tools | Repo mount VFS |
|---|---|---|---|
disabled | default on create; agent jail AGENT --disable; or unjail the last path | omitted (bash_exec, read_file, write_file, edit_file, search) | none |
jailed | agent jail AGENT --path PATH (additive) | those tools, scoped to the paths | allowlisted prefixes only |
full | agent unjail AGENT with no --path | unrestricted | entire workspace |
Watch the two forms of unjail. agent unjail AGENT --path PATH removes one prefix, and removing the last one drops the agent to disabled, not full. agent unjail AGENT with no path opens the whole workspace. agent jail AGENT with no flags just prints the current mode and paths.
agent grant AGENT --site SITErecords that the agent may use that site's*.tool.sh/*.mcp.shtools. It does not open the disk.- Tool discovery is not limited to granted sites.
search_tools,describe_tool, andcall_toolsee every*.tool.sh/*.mcp.shin$HOME. Agents cannot runsecurity: definertools. - During a tool run,
call_toolmay still read and write that tool's tree even when FS tools are disabled. The agent still cannot useread_fileorbash_execon those paths until jailed. mail inbox,message inbox, and stub reads stay available when filesystem tools are disabled.- Paths outside the repo mount (
/skills,/tmp, …) are not gated by the jail. - When jailed, a goal's
--path(or cwd) must stay inside the jail.
When filesystem is disabled (the create default), the agent acts through search_tools / describe_tool / call_tool. Do not have it try write_file.
Commands
From agent --help:
Usage: agent create NAME
agent list
agent show ID|NAME
agent claim USERNAME [--as ID]
agent unclaim [--as ID]
agent soul AGENT
agent soul AGENT --file PATH
agent soul AGENT --stdin
agent grant AGENT --site SITE_PATH
agent ungrant AGENT --site SITE_PATH
agent grants [AGENT]
agent jail AGENT [--path PATH]...
agent jail AGENT --disable
agent unjail AGENT [--path PATH]
agent slack connect --team-id T... [--team-name NAME]
agent slack disconnect
agent slack bind AGENT --bot-token xoxb-... --signing-secret SECRET [--app-id A...] [--bot-user-id U...]
agent slack unbind AGENT
agent slack manifest AGENT
agent slack status
agent rm ID
| Command | Who | Notes |
|---|---|---|
agent create NAME | owner | Scaffolds the home folder; filesystem disabled |
agent list / agent show ID|NAME | member | JSON. show adds filesystem, jail_paths, site_grants. Quote names with spaces |
agent soul AGENT | member | Print soul |
agent soul AGENT --file PATH / --stdin | owner | Replace soul; file stays owner-owned |
agent claim USERNAME --as AGENT | owner or su'd agent | {org}-USERNAME@inbox.sails.app. Not a UUID or reserved word |
agent unclaim --as AGENT | owner or agent | UUID address remains |
agent grant / ungrant AGENT --site SITE_PATH | owner | Site folder must contain sails.site.json |
agent grants [AGENT] | owner (or agent for self) | JSON list of grant rows |
agent jail / unjail / jail --disable | owner | Filesystem allowlist (see table above) |
agent slack … | owner | Workspace link and per-agent bot. See Talk to an agent in Slack |
agent rm ID | owner | Drops membership, claim, grants, jails, and agents/{id}/ |
su AGENT / su - | write+ member | Switch effective identity |
Write members and agents may schedule at / cron as themselves. With filesystem access (jailed or full), agents may ship create|update|delete for a non-root path they can write inside the jail. Custom --hostname and ship verify stay owner-only.
Failure modes
These are the real messages from the CLI.
| What you see | What it means | What to do |
|---|---|---|
agent claim/unclaim: run as an agent (`su AGENT`) or pass --as ID | You ran claim as yourself | Add --as support-bot (name or ID), or su support-bot first |
mail username 'support' is reserved | Reserved word | Pick another username |
mail username cannot be a UUID (UUID addresses always work without claiming) | You tried to claim the ID | Skip the claim; {id}@inbox.sails.app already works |
agent grant: `sites/x` has no sails.site.json (expected …/sites/x/sails.site.json) | Path is not a site root | Grant the folder that holds sails.site.json |
agent grant: --site SITE_PATH is required | Missing flag | agent grant AGENT --site sites/crm |
agent rm: invalid UUID | You passed a name | agent rm <id> with the UUID from agent show |
agent not found: NAME | Typo, or the agent was removed | agent list to see what exists |
agent show <id> still prints after agent rm | A stale record by ID; the agent and its folder are gone | Trust agent list and agent show NAME, which no longer find it |
No bash_exec / read_file on the agent | Filesystem still disabled, or you unjailed the last path | agent jail AGENT --path … (typical first path: agents/{id}) |
| Site tools work but disk does not | You only ran agent grant --site | A grant is not a jail. Add jail paths separately |
| Agent suddenly has the whole workspace | You ran agent unjail AGENT with no --path | agent jail AGENT --disable, then jail the paths you meant |
Agent rewrote soul.md | Wrong owner path | Owner runs agent soul … --file / --stdin (rewrites and reassigns ownership) |
You published agents/ | Wrong site root | Publish a sites/… folder with sails.site.json, never agents/ |
How to: Give an agent a job, Talk to an agent in Slack, Message another agent, Mail from an agent.