Spens logoSpens

Custom agents

How to write agent templates for spens

You can add your own agent templates the same way you add environment templates: in a templates/ directory inside your workspace, or by passing a .json file path directly on the command line. Templates are discovered recursively under templates/ (nested folders such as templates/team/ are included), and a local agent template takes precedence over a built-in agent with the same name.

Agent template format

An agent template is a JSON file with "template_type": "agent". It defines how to install and configure a specific coding agent.

FieldRequiredDescription
template_typeyesMust be "agent"
nameyesTemplate name used on the command line and in session metadata
binary_namenoExecutable used to invoke the agent in interactive mode (e.g. claude). Defaults to name. Set this when the template name differs from the installed binary
installation_commandyesShell command that installs the agent binary. Runs as the unprivileged agent user, installing into its home
dependenciesnoShell commands to run before installation (e.g. installing prerequisites). Runs as root during build, with HOME pinned to the agent user's home
nono_base_confignonono.sh base profile to pull and extend
relocate_binarynoMoves the installed binary to a standard location and cleans up install artifacts: {"from", "to", "cleanup"}. cleanup is a path or list of paths to remove
config_filesnoStatic files written into the image at build time. A map of container path to file content
configurationnoOrdered list of host config mounts. Each entry has a source, a destination, an optional include glob list, and an optional exclude glob list. Only existing sources and matching files are mounted. source accepts the {workspace} token and the {spens_dir} token. destination paths starting with ~ expand to the agent user's home. When multiple entries target the same container file, the entry listed first wins
allow_foldersnoDirectories the agent is allowed to access
envnoEnvironment variables to set in the container, in KEY=value format
packagesnoAdditional system packages to install in the image
yolo_commandnoCommand template with a {prompt} placeholder, used to run the agent non-interactively when a prompt is passed on the CLI. The placeholder is filled at runtime, so the image is not rebuilt per prompt. If omitted, passing a prompt is an error. May also contain an {mcp_args} token, spliced with the session's injected MCP arguments (they are appended to the end otherwise)
mcpnoMCP configuration support: format (mcp-json, opencode-json, opencode-v2-json or codex-toml), transports (supported server transports), and deliver (the delivery mechanism: arg, overrides, env or inject, with its per-mode argument templates). An absent block means the agent does not support MCP injection via --mcp-config. See Spens with MCP servers

Yolo commands

The built-in agents use these yolo commands:

AgentYolo command
opencodeopencode run --auto {prompt}
codexcodex exec --sandbox danger-full-access {prompt}
claudeclaude -p {prompt} --dangerously-skip-permissions
pipi -p {prompt}
antigravityagy -p {prompt} --dangerously-skip-permissions

Worked example

Create templates/my-agent.json:

{
  "template_type": "agent",
  "name": "my-agent",
  "binary_name": "my-agent",
  "installation_command": "curl -fsSL https://example.com/install | sh",
  "dependencies": [],
  "nono_base_config": "nolabs-ai/my-agent",
  "relocate_binary": {
    "from": "~/.local/bin/my-agent",
    "to": "/usr/local/bin/my-agent",
    "cleanup": ["~/.my-agent", "~/.local/bin/my-agent"]
  },
  "config_files": {
    "~/.my-agent/config.toml": "setting = true\n"
  },
  "configuration": [
    {
      "source": "~/.config/my-agent",
      "destination": "~/.config/my-agent",
      "include": ["config.json", "*.toml"],
      "exclude": ["secrets.*"]
    }
  ],
  "allow_folders": ["~/.cache/my-agent"],
  "env": ["MY_AGENT_CERT=/certs/mitmproxy-ca-cert.pem"],
  "packages": ["ripgrep"],
  "yolo_command": "my-agent run --yes {prompt}"
}

Then run it:

spens node-24 my-agent .

On this page