Skip to content

Template Reference

The bodies of the files you author for Polytoken (facets, subagents, and skills) are templates. A skill body renders as a template only when the skill opts in through polytoken frontmatter; without that key, Polytoken includes the body verbatim. The legal frontmatter keys for each file type are in the tables at the end of this page.

Templates catch typos at render time: referencing a variable that does not exist raises an error rather than rendering blank, so a broken prompt never reaches the model. Guard optional values with the functions below or with a conditional.

VariableTypeHolds
model_namestringThe active model’s name.
model_variantstringThe model family, for example claude, openai, or gemini.
model_providerstringThe configured provider the model runs through, for example anthropic or zai. Empty when no model is active.
model_idstringThe upstream model identifier the provider sees, for example claude-opus-4-5 or gpt-5.6. This is the model’s provider-side name, not the provider itself.
max_tool_batch_sizenumberHow many counted tool calls the model may issue in one assistant message.
supports_visionbooleanWhether the model accepts images.
can_read_imagesbooleanWhether Polytoken returns images from file reads to this model. True only when the model accepts images and the provider accepts image results.
VariableTypeHolds
facet_namestring or nullThe active facet’s name. In a subagent template, the subagent definition’s name. Null in a skill body rendered inside a subagent prompt.
subagent_namestring or nullThe subagent’s name. Set in a subagent definition body and in a skill body rendered inside a subagent prompt. Null elsewhere.
project_pathstringThe project’s root directory.
cwdstringThe project’s root directory in facet, AGENTS.md, and skill templates. In a subagent template, the subagent’s working directory.
session_idstring or nullThe current session’s identifier. Null outside a main-session facet template.
current_datestring or nullToday’s date in YYYY-MM-DD form. Null outside a main-session facet template.
is_non_interactivebooleanWhether the session that renders the template has no human in the loop. Main-session facet templates and skill bodies carry the session’s value; a skill body referenced from a subagent prompt inherits that parent session’s value. Subagent definition bodies and AGENTS.md templates render false.
spice_levelnumberThe configured daemon.spice_level: 0, 1, or 2. The default is 1.
promptstring or nullIn a subagent definition body, the subagent’s task prompt, rendered as a
template before the body renders. In a main-session facet template, the prompt that started this turn. Null in an AGENTS.md template and in a skill body.
subagent_batchobject or nullFor a subagent launch, the one-based clone ordinal and shared count; a single launch carries ordinal 1 and count 1. Null outside a subagent launch.
model_groupobject or nullFor a group-backed subagent launch, the group name, one-based launch candidate ordinal, and candidate count. Null for direct model selections and outside a subagent launch.
VariableTypeHolds
available_toolslistThe names of every tool the model can use this turn.
available_undeferred_toolslistThe tools whose full definitions Polytoken includes in the prompt this turn.
available_deferred_toolslistThe tools available through tool search.
tool_librarylistEach tool, with its name, description, and an example when one exists. Deferred tools carry no example.
available_mcp_serverslistThe names of the MCP servers in your configuration, whether or not Polytoken has connected to them.
available_subagentslistEach subagent, with its name and description.
available_skillslistEach skill, with its name and description.
VariableTypeHolds
project_varsobjectProject-local variables from .polytoken/project_vars.yaml.
auto_drain_notificationsbooleanWhether Polytoken delivers finished background work as soon as it is ready.
plan_integration_enabledbooleanWhether plan handoff activates a saved-session goal. When false, a handed-off plan activates no goal, and Polytoken omits goal-related instructions from facet prompts.
source_controlstringThe project’s source control system: git, jj, sl, or none. Detected from the project root. Does not change when the working directory moves or for subagents.
harness_typestringThe kind of client driving the session, as free text: tui for the terminal interface, outpost for sessions launched by Outpost, and exec for exec mode. Empty for sessions recorded before Polytoken tracked it. An attaching client can update the value.
orchestratorslistThe terminal orchestrator environments the client detected, sorted, for example tmux, zellij, or herdr; a client can supply other labels. Empty when the session runs in a plain terminal. An attaching client can update the value.

Every variable above exists in every template. A context without a value carries null or an empty list instead of omitting the key. Printing a null value emits the literal text none, so guard optional values with a conditional. session_id, current_date, and the turn prompt appear only in a main-session facet template. In a skill body, every availability list except available_skills is empty, so has_tool() and has_mcp() return false there. In an AGENTS.md template, available_deferred_tools is empty too.

Polytoken renders every task prompt passed to a subagent before it renders the subagent definition body. The body receives the rendered task as prompt. A counted batch renders each task and body once per clone. Use a MiniJinja raw block when task data must contain literal template delimiters:

{% raw %}Keep {{ literal_syntax }} unchanged.{% endraw %}

Launch metadata is immutable. subagent_batch identifies the clone in the batch, while model_group identifies the candidate selected at launch. Provider failover and reload can change the current route without changing those recorded launch values or the rendered text.

Put project-specific template data in .polytoken/project_vars.yaml. You can omit the file. When Polytoken cannot use the file because the file is invalid or fails a safety check, Polytoken logs a warning and starts project_vars as an empty object. A symlinked project_vars.yaml fails the safety check when daemon.follow_symlinks_for_configs is off. When the file is absent, project_vars starts as an empty object without a warning. Write a YAML mapping at the top level.

team:
name: Core Platform
escalation: "#polytoken-core"
features:
reviewer_prompt: true

Templates can read nested values with dot or bracket syntax:

Team: {{ project_vars.team.name }}
Escalation: {{ project_vars["team"]["escalation"] }}

When a template renders an object or list directly, Polytoken emits JSON. Prefer reading the scalar value you need.

If a project_vars path is missing, Polytoken logs a warning and renders an empty value instead of failing the template. This lenient missing-key behavior is specific to project_vars; other missing template variables still fail under strict rendering. Polytoken caps missing-path warnings per render and logs a suppression warning after the cap. Guard optional extension points with a conditional:

{% if project_vars.features.reviewer_prompt %}
Use the project reviewer prompt.
{% endif %}

Polytoken reads project_vars.yaml as raw project data, not as config: it never merges the file with global config, and environment variable syntax such as ${TOKEN} stays literal. YAML scalar coercion still applies, so quote values such as "yes" or "on" when you intend strings. Treat project_vars.yaml as trusted prompt input, like AGENTS.md or a skill body. Do not put secrets in project_vars.yaml; templates can render these values into model prompts.

The shipped plan facet reads project_vars.plan_facet.plan_spec_override when Polytoken renders the facet prompt. When the value is truthy, Polytoken uses it instead of the shipped handoff-plan format: true, a nonzero number, a nonempty string, or a nonempty list or mapping all count, and lists and mappings render as JSON. Polytoken does not merge the value with the shipped format, so write the complete plan-format instructions in the value as a nonempty string.

plan_facet:
plan_spec_override: |
## Plan artifact specification
Write a handoff plan with these sections:
- Goal
- Implementation steps
- Acceptance criteria
- Validation

The override changes only the plan format. The shipped plan facet still keeps its read-only planning behavior and its handoff workflow. To replace the whole facet, write .polytoken/facets/plan.md instead.

The override is literal text. Polytoken does not render the value as another template pass, so the model sees MiniJinja syntax inside the value as written. Use a YAML block scalar for multi-line instructions.

These functions are available in every template:

FunctionReturnsEffect
has_tool(name)booleanWhether a tool with that name is available this turn.
get_tool(name)object or nullThe named tool’s library entry, or null when no library entry exists for the name.
has_mcp(name)booleanWhether an MCP server with that name appears in your configuration.
is_model_variant(variant)booleanWhether the active model belongs to that family.
has_skill(name)booleanWhether a skill with that name is available.
at_least_spice_level(level)booleanWhether the configured daemon.spice_level is level or higher.
is_web_search_available()booleanWhether a web search provider is configured for the session (configuration presence, not runtime health).
is_decision_agent_available()booleanWhether a decision backend is configured for the session (configuration presence, not runtime health).
using_orchestrator(name)booleanWhether name appears in the session’s orchestrators list. false when the session runs in a plain terminal.

The two availability functions answer truthfully wherever system prompts, subagent definitions, and skill bodies render; in AGENTS.md renders they always report false, so do not gate AGENTS.md content on them.

One function is available in facet and subagent templates when Polytoken renders system-prompt text:

FunctionReturnsEffect
transclude(uri)stringIncludes a prompt fragment. The uri can be a polytoken:// shipped-resource address or a project file path. File paths resolve relative to the directory of the file that contains the transclude() call, and the included file renders as a template with the current context. Polytoken strips valid YAML frontmatter from an included file and renders only the body; a leading --- block that does not parse as YAML is content and stays. Polytoken confines file paths to the calling file’s directory subtree and rejects ../ escapes, mirroring the @file resolution rules. Using a file path inside a shipped polytoken:// resource is an error, because shipped resources have no filesystem location. An include fails the render when it forms a cycle, nests too deeply, grows past Polytoken’s size ceiling, or names a directory.

The frontmatter of each authored file type has its own set of legal keys. The tables below list them.

JSON Schema: JSON | YAML

NameTypeDescription
namestringDisplay name of the facet.
descriptionstringOptional short description shown in the daemon catalog.
polytoken.modelstringModel this facet uses, overriding the session default.
polytoken.autonomous_hintstringGuidance for the autonomous permission classifier: in Autonomous mode, Polytoken adds this text to the classifier’s context for each tool call made in this facet, steering the allow, ask, and deny decision.
polytoken.auto_facet_hintstringBackwards-compatible alias of autonomous_hint.
polytoken.compaction_hintstringGuidance Polytoken appends to the compaction summary prompt when this facet is active, naming the context the summary should preserve for this facet’s work.
polytoken.colorstringAccent color for the facet, used in the sidebar and indicators.
polytoken.color_lightstringAccent color for the facet on light backgrounds.
polytoken.color_darkstringAccent color for the facet on dark backgrounds.
polytoken.fallback_modelsstring listModels Polytoken tries, in order, if the primary model is unavailable.
polytoken.toolsstring listTools this facet exposes, as tool names or tag! groups (for example tag!ALL).
polytoken.tools_denystring listTools to exclude after tools expands. Applied last.
polytoken.undeferred_toolsstring listTools to always send in full, even under native-deferred tool loading.
polytoken.facet_transitionsmapRules for switching to other facets from this one, keyed by target facet name.
polytoken.skills_allowstring listSkills this facet can invoke, as skill names or tag! groups.
polytoken.skills_denystring listSkills to exclude from skills_allow.

JSON Schema: JSON | YAML

NameTypeDescription
namestringDisplay name of the subagent.
descriptionstringShort summary of what the subagent does.
polytoken.modelstringModel this subagent uses, overriding the session default.
polytoken.autonomous_hintstringGuidance for the autonomous permission classifier: in Autonomous mode, Polytoken adds this text to the classifier’s context for each tool call made by this subagent, steering the allow, ask, and deny decision.
polytoken.auto_facet_hintstringBackwards-compatible alias of autonomous_hint.
polytoken.fallback_modelsstring listModels Polytoken tries, in order, if the primary model is unavailable.
polytoken.toolsstring listTools this subagent can use, as tool names or tag! groups.
polytoken.tools_denystring listTools to exclude after tools expands.
polytoken.undeferred_toolsstring listTools to always send in full, even under native-deferred tool loading.
polytoken.allow_subagent_spawnbooleanWhether this subagent may spawn its own subagents.
polytoken.exit_tool_schemaJSON Schema objectCustom schema for the subagent’s exit tool, replacing the default. Declaring this key also makes Polytoken log a warning when the subagent finishes without calling its exit tool, and warn at load when a status/kind/outcome enum carries values the exit check does not recognize; unrecognized-status payloads are retried and then salvaged to the parent. See the Subagents page in the manual.
polytoken.skills_allowstring listSkills this subagent can invoke, as skill names or tag! groups.
polytoken.skills_denystring listSkills to exclude from skills_allow.
polytoken.inherit_toolsbooleanWhether this subagent inherits the caller’s tools instead of using tools.

JSON Schema: JSON | YAML

NameTypeDescription
namestringDisplay name of the skill. Must match the skill’s directory name.
descriptionstringShort summary of what the skill does. Required.
licensestringLicense identifier for the skill.
compatibilitystringCompatibility information for the skill.
metadatamapFree-form metadata as key-value pairs.
polytoken.jinjabooleanAccepted for compatibility with older skill files. The presence of the polytoken key itself turns template rendering on; this value does not change that.
polytoken.disable_model_invocationbooleanWhen true, the model cannot invoke this skill on its own; only explicit references load it.
polytoken.tagsstring listTags that group this skill for tag! references.

JSON Schema: JSON | YAML

NameTypeDescription
polytokentrueSet to true to let Polytoken render this file as a template. Omit it to include the file verbatim.