// XEM Guides

Author a Chat Template

Chat templates pin the system prompt, the allowed tool set, and the approval cadence for a specific procedure. This walkthrough takes you from a blank page to a working, version-controlled template callable from any chat in your project. Expected time: 15 minutes.

Prerequisites

  • An API key with the management scope.
  • A working xeroctl install on your workstation (run xeroctl --version to confirm).
  • At least one operational workspace in the project, identified by its external id (ws_<hex>).
  • Familiarity with workspaces and approvals.

Scenario

Your team drains Kubernetes nodes for maintenance a couple of times a week. The procedure is repetitive: cordon the node, drain gracefully with a short grace period, verify no stuck pods, then proceed to maintenance. We will encode this procedure as a chat template so the next operator runs it with a consistent system prompt and an approval gate.

Step 1: Draft the Template

Create a file drain-node.json on your workstation.

json
{ "name": "drain-kubernetes-node", "scope": "project", "system_prompt": "You are a Kubernetes operator. When asked to drain a node, cordon it first, drain with grace-period 60, verify no stuck pods, and stop. If the drain fails, do not retry without human input.", "allowed_tools": [ "k8s_get_nodes", "k8s_describe_pod", "k8s_cordon_node", "k8s_drain_node" ], "approval_policy": "elevated", "metadata": { "description": "Safely drain a node for maintenance", "tags": ["kubernetes", "node-maintenance"] } }
  1. The system prompt is imperative and bounded: it states what to do, in what order, and what to refuse.
  2. The allowed_tools list is the full set of tools the model may call during a session bound to this template, nothing else. Tool names must match the platform registry exactly (the Kubernetes tool family uses the k8s_* prefix; see the Kubernetes tools reference for the full list).
  3. The approval_policy is elevated: destructive operations (such as k8s_drain_node) require human approval before dispatch.
  4. The scope field in the file is informational only. The effective scope is decided by the upload route: if you pass --workspace to xeroctl templates create the template is workspace-scoped, otherwise it is project-scoped. When the two disagree the route wins and the CLI prints a note.

Step 2: Upload the Template

bash
xeroctl templates create --file drain-node.json

Transcript on success:

text
template drain-kubernetes-node created version: 1 scope: project id: tmpl_01HX...

The CLI returns the template ID and the version. Every edit creates a new version; the ID is stable.

Step 3: Test Against a Chat

Apply the template to a new chat:

bash
xeroctl chat new --workspace ws_01HXXXXXXXXXXXXXXXXXXXXXXX \ --template drain-kubernetes-node \ --message "Drain node worker-07 for maintenance"

The --workspace flag takes the workspace external id (ws_<hex>); a workspace display name will 404. Find the id with xeroctl workspaces list.

Watch the SSE output. The model will use the template's system prompt and work through the drain procedure. When it reaches k8s_drain_node, the approval engine pauses the invocation and emits an x_ask_user.question frame.

Approve it from another terminal. List the open approvals to find the id, then approve it with a short justification (see Approvals for the full decision payload):

bash
xeroctl approvals list xeroctl approvals approve <approval_id> --decision approve \ --justification "Scheduled maintenance for worker-07"

Step 4: Iterate and Version

You noticed during testing that the system prompt is not explicit about which namespaces are in scope. Edit drain-node.json:

json
{ ... "system_prompt": "You are a Kubernetes operator. When asked to drain a node, cordon it first, drain with grace-period 60, verify no stuck pods in any namespace, and stop. Assume cluster-wide namespace scope unless the operator restricts it.", ... }

Push the update:

bash
xeroctl templates update drain-kubernetes-node --file drain-node.json

Version 2 replaces version 1 as the active version. New chats pick up version 2 automatically; in-flight chats keep the version they started on.

Step 5: Promote Platform-Wide

Other projects in your organization could use this template too. Promote it from project scope to platform scope:

bash
xeroctl templates promote drain-kubernetes-node --scope platform

Platform-scope templates are visible to every project in the deployment. Promotion is one-way: platform scope cannot be demoted without deleting and recreating at project scope.

Next Steps

  • Publish more templates and keep them together in a git repository; synchronize with xeroctl templates apply-from-dir <directory> (the directory is a positional argument; add --workspace ws_<hex> for workspace-scoped syncs). The command walks every *.json file in the directory and reports each one as created (new name), updated (existing name with changed fields), or unchanged (existing name with identical fields), no template is ever deleted by this command.
  • See Approvals for tuning the elevated policy's SLA and escalation chain.
  • Browse the built-in tool catalog -- Cloud, Kubernetes, OpenStack, and Ecosystem, to find tool names your templates can reference.