Everything as code
Keep a complete AI setup in a repository and import it into a clean environment.
Every example in this section was built from pieces - credentials, groups, gateways, connections, services, skills. The setup below puts all of them into files a repository can hold and a clean environment can import, so recreating production in staging takes a checkout and an import.
The pieces
Every piece is kept in a file, and each kind of piece has its own form and deployment method:
| Piece | Form | How it deploys |
|---|---|---|
| Security, groups, gateways, LLM connections | One enmasse YAML | Imported - on demand or on startup |
| Services | Python files | Hot-deployed |
| Skills | A SKILL.md per directory under config/repo/skills | Files - copied or checked out in place |
| Secrets | Environment variables | Never in the repository |
The YAML refers by name to services and skills that are deployed as files - enmasse provides the configuration, the files provide the content, and the names link the two.
The YAML
The complete configuration of a support setup - an agent credential, its group, a gateway with two tools and a prompt, and the LLM connection the tools use:
security:
- name: agent.support
type: apikey
username: support-agent
password: Zato_Enmasse_Env.Support_Agent_Key
groups:
- name: support-agents
members:
- agent.support
llm:
- name: Support LLM
model: gpt-4o-mini
address: https://api.openai.com/v1
secret: Zato_Enmasse_Env.Support_LLM_Key
timeout: 15
max_tokens: 2048
mcp_gateway:
- name: support
url_path: /mcp/support
services:
- example.support.get-ticket
- example.support.summarize-ticket
security_groups:
- support-agents
skills:
- ticket-triage
validate_input: true
is_audit_log_active: true
max_response_size: 2000
Two properties matter:
- No secrets - the
Zato_Enmasse_Env.prefix reads each secret from an environment variable where the import runs, so this file is safe in git and each environment brings its own keys. - Importing the gateway also creates the REST channel that makes it reachable - the YAML above is complete.
The repository
support-ai/
├── enmasse.yaml
├── services/
│ └── support.py # the two services the gateway names
└── skills/
└── ticket-triage/
└── SKILL.md # the prompt the gateway serves
Import into a clean environment
With a fresh environment and the two environment variables set, the files go in first and the configuration follows:
# Services hot-deploy by being placed in the pickup directory
cp services/support.py ~/env/qs-1/server1/pickup/incoming/services/
# Skills are files under the server's config
cp -r skills/ticket-triage ~/env/qs-1/server1/config/repo/skills/
Then the YAML imports as one unit - in the Dashboard through System > Config > Import enmasse, or, in containers, as a mount point: enmasse.yaml under /opt/hot-deploy/enmasse/ imports on startup, as the DevOps guide describes. Either way the environment now serves /mcp/support, the agent's key works, the prompt is listed and the audit log is on - nothing was configured by hand.
Running the import again is safe - it creates what does not exist and updates what does, matching by name. That makes the YAML the reviewable unit of change: raising max_response_size is a one-line diff, a pull request and a re-import.
Failure behavior
Because the YAML refers to services, skills and secrets by name, a name can point to something that is not there yet:
- A service in the gateway's list that is not deployed yet is not an error - the gateway imports, and the tool appears once the service is hot-deployed. The export marks such services with a
Not deployednote, as sharing with clients shows. - A skill named in
skillsthat has no directory yet is not served until the files arrive -prompts/listshows what is there. - A missing environment variable does not stop the import - the value becomes a placeholder that names the missing variable, so the first call that needs the secret fails and the placeholder in the error points straight at which variable was not set.
See also
| Feature | What it does |
|---|---|
| GitOps | The llm and mcp_gateway enmasse sections in full |
| Multi-agent isolation | The same layout grown to several agents and gateways |
| Self-hosted models | Per-environment YAML that swaps the model backends |