# Agents A container that stays running, a repository it owns, and a name. Making one is a row on a screen; what it may reach was decided before it existed. ## Making one — The row under the last agent It is a row rather than a command because that is where somebody who wants an agent is already looking — with none at all it is the only row there is, and the console opens on it. The panel behind it takes a name and `⏎` builds it: a container, a repository of its own, nothing in its memory, and exactly what `defaults` in the config allows it to reach. The name is the whole of what the keyboard decides here, which is why the pane says so. It may name an agent and it may not grant it a thing. A name that is taken, or that is not a name, is refused in the pane with the name still in the prompt to be fixed, and what is built appears where the `+` was, which is where the cursor already is. A plane with no `defaults` makes an agent that cannot reach the model, and says so at the moment it is made rather than mid-turn. `squad chat maxi` at a shell is the same offer from the other end: naming an agent that does not exist is what someone types when they want one, so it asks. ## What one is made of — A repository it owns On its first boot an agent gets a repository in its own volume, at `/home/agent/.self`: - **agent.yaml** — name, model, and the capabilities it asks an operator for - **soul.md** — who it is; appended to the system prompt on every turn - **skills/** — SKILL.md folders, loaded by pi - **memory/** — what it chose to remember, partitioned by users, projects and reference - **tools/** — scripts it wrote for itself It is scaffolded once, git-initialised, and then left alone: what the agent learns and what it can do are files it edits and commits itself. The control plane never writes there again, because the second write would be the control plane overwriting the agent's own work. That repository is the agent, not its desk. Turns start next door, in a second volume at `/home/agent/workspace`, and the house rule goes in as argv on every turn: one directory per project, nothing loose at the top, and tidy what you find untidy rather than leaving it. It is said by the plane rather than written into `soul.md` because the agent may rewrite its soul, and a rule the subject can edit is not a rule. Both volumes outlive the container, which is replaced every time the image changes. > **Nothing in that repository grants anything.** `agent.yaml` lists capability *requests*, and an operator answers them in [the config file](https://squad.mormon.garden/docs/config.md) the agent cannot reach. An agent that can edit its own definition can otherwise grant itself capabilities, which is one of the three problems the whole design is shaped around. ## Declared, or made here — Two kinds of agent, and one of them is in your file An agent can be a block in `config.yaml`, which is where a description, its own grants, its schedules and a tighter ceiling are written. Or it can be a name typed at the row above, which the plane writes down in its state directory — since the config file is the operator's and no plane may write it. *deploy/config.yaml* ```yaml agents: - id: scout description: Watches the issue tracker and answers questions about it. grants: - id: github-issues host: api.github.com pathPrefix: /repos/acme/website/issues methods: [GET, POST] injection: kind: bearer token: { ref: GITHUB_TOKEN } ``` `description` is used the first time the agent boots, to write its `soul.md`. After that the repository is the agent's and this file stops having an opinion about who it is. An agent's own grants add to the defaults rather than replacing them, and one it declares with the same id wins — which is how a single agent is narrowed without narrowing the rest. ## Starting over — /clear throws the conversation away and leaves the agent standing ``` > /clear scout has forgotten the conversation. The repository is untouched: scout's soul, its skills and whatever it wrote down to remember are what outlive a conversation, and are why throwing one away costs little. So is everything /model, /mcp, /limit and /serve have set. The next thing said starts it again on nothing. ``` It says that every time, and the saying is half the command: a clear nobody is sure of the cost of is one that gets put off until the context is a mess. An agent that has talked itself into a corner is rarely one worth deleting, and before this the only way out of the corner took the repository with it. A conversation lives in three places and all three go together — what the model is shown at the start of the next turn, the transcript on disk that outlives the console, and the pane you are reading. The turn in flight is stopped first, and that is not a courtesy: the session is written out at the end of a turn, so a conversation deleted underneath a running one would come straight back with everything in it a minute later. ## Taking one away — There is one kind of delete and it is the whole one ``` > /delete Deleting scout stops its container and throws it away, along with the repository inside it: everything it wrote, remembered and made for itself. There is no copy of that anywhere and nothing here can put it back. Nothing has been deleted yet. ╭──────────────────────────────────────────────────────────────────────╮ │ delete scout? y / n │ ╰──────────────────────────────────────────────────────────────────────╯ y delete n cancel ^C quit ``` The container, the repository inside it, and the conversation — because a delete that left the name sitting in the column is one you were told worked and have to do again. So it asks first, in the prompt itself, and the question has the whole keyboard until it is answered: `y` deletes and every other key walks away, including the return that was pressed a moment ago to ask it. The asking lives in the console rather than in the plane, and that is the point of it: a plane that took `/delete scout` from anywhere would let one line be the whole of an agent. Whatever is typed after the command is dropped and the bare form goes down first, so a command reaches no further than the conversation it was typed in. An agent you declared in the config goes the same way, which takes one more step than it sounds: your file is yours and no plane may write it, so there is nowhere to take the name out of. The deletion is written down instead, in `deleted.json` beside the state, and every start from then on skips the name. The answer says so, because the line is still in your file and taking it out is the only thing left to do about that agent. At a shell, `squad rm scout` takes the container and leaves the volume, because the volume is the agent. `--purge` deletes that too, and asks for the agent's name to be typed first so a reflexive `y` cannot do it.