STATEK Prompt Definition Guide
STATEK prompt definition files keep agent instructions and model metadata outside Python code. They are Markdown files loaded from STATEK_PROMPT_FILES_DIR or from StatekSettings(prompt_files_dir=...).
A prompt file is matched to an agent by filename stem:
prompts/
calendar_assistant.md
dispatcher.mdcalendar_assistant.md applies to Agent(role="calendar_assistant", ...).
Prompt files can change what code an agent writes and what tools it can ask the model provider to call. Treat them as executable configuration: review changes, keep secrets out of prompt text, and deploy with the same sandboxing, permissioning, resource limits, and operational controls you use for agent code.
File Format
A prompt file has metadata comment lines followed by a required # System Prompt heading:
# MODEL: openai/gpt-5-mini
# TEMPERATURE: 0.2
# CHAT_STYLE: DIRECT
# DESCRIPTION: Helps users inspect and update calendar state
# System Prompt
ROLE: Calendar assistant and Python workspace operator.
GOAL: Help users inspect calendar objects and make safe scheduling changes.
Available variables: {shared_var_names}
Available functions:
{brief_tools}Rules verified in the prompt parser:
- Files must be
.mdfiles in the configured prompt directory. - Metadata lines before
# System Promptuse# KEY: value. - Metadata keys are uppercased by the parser.
# System Promptis required and is matched case-insensitively.- Content below
# System Promptis parsed as the agent system prompt. - A file without
# System Promptraises a parsing error. - Unknown metadata keys are preserved in the metadata dictionary, but STATEK gives them no framework behavior unless application code reads them.
Loading Behavior
Configure prompt loading through settings:
from statek.settings import StatekSettings
settings = StatekSettings(prompt_files_dir="./prompts")or with the environment:
STATEK_PROMPT_FILES_DIR=./promptsIn a typical application, prompt files are the versioned source of truth for an agent's instructions and model metadata. Give each file the same stem as the agent role, such as calendar_assistant.md for Agent(role="calendar_assistant"), and STATEK uses that definition for the role.
This lets the Python agent definition focus on tools, context, and durable workspace setup, while product behavior lives in Markdown that can be reviewed and updated separately. Once prompt files are configured, treat inline _system_prompt and _metadata values as development defaults rather than the production definition.
Prompt changes affect new job definitions created from the updated agent configuration. Existing job definitions keep the metadata they were created with, so a running or already-defined job does not silently switch models or behavior just because a prompt file changed.
Advanced: update_prompt_config(...) can refresh already-created agent objects from prompt definitions during operational workflows, but existing job definitions still preserve their captured configuration except for explicitly supported refresh behavior.
Metadata Reference
MODEL
MODEL is required when creating job definitions.
Use one model:
# MODEL: openai/gpt-5-minior a complete difficulty mapping:
# MODEL: L:gpt-5-mini,MH:gpt-5When a mapping uses difficulty labels, all three levels must be covered exactly once. Labels are L, M, H, or the full names low, medium, high.
PROVIDER
PROVIDER selects the provider when the provider is not embedded in MODEL.
# PROVIDER: OPENAI
# MODEL: gpt-5-miniIf the model string already embeds provider information, provider selection follows the model name.
TEMPERATURE
TEMPERATURE is parsed as a float from 0.0 through 1.0 and sent to providers that support it:
# TEMPERATURE: 0.2Values outside that range raise a request error.
REASONING
Truthy REASONING values enable provider reasoning or thinking parameters where implemented:
# REASONING: trueOpenRouter receives a reasoning field. Claude-compatible requests receive a thinking field.
CHAT_STYLE
CHAT_STYLE controls chat and code formatting:
# CHAT_STYLE: DIRECTSupported values are CONSOLE, MARKDOWN, MD_DIALOG, and DIRECT. See Chat Styles for how each style represents Python execution, console output, dialog, examples, and formal tool calls.
LLM_TOOLS_SCOPE
LLM_TOOLS_SCOPE controls which tool calls are sent to the model provider:
# LLM_TOOLS_SCOPE: SYSTEM
# LLM_TOOLS_SCOPE: APPLICATION+show_example
# LLM_TOOLS_SCOPE: ALL-panicSupported categories are:
SYSTEM: registered system toolsAPPLICATION: tools supplied by the application agentALL: system and application tools
You can add explicit tool names with +tool_name and remove names with -tool_name. Hidden tools cannot be exposed by explicit addition.
DESCRIPTION
DESCRIPTION is short capability text for routing or discovery:
# DESCRIPTION: Routes incoming requests to the best specialist agent.update_prompt_config(...) applies it to matching agents as their description.
DEFAULT_DIFFICULTY
DEFAULT_DIFFICULTY selects the static difficulty when no example or dynamic escalation applies:
# DEFAULT_DIFFICULTY: MAccepted values are L, M, H, low, medium, and high. If it is absent, STATEK falls back to STATEK_DEFAULT_DIFFICULTY, which defaults to M.
AUTO_LANG_HINT and AUTO_LANG_RULE
These are advanced language controls for localized jobs.
AUTO_LANG_HINT: False disables the language hint appended to user messages or push log messages for non-English locales. AUTO_LANG_RULE: False disables the language rule appended to the outgoing system prompt for non-English locales.
Locale Selection
Locale is selected when a job is created. It is not a # LOCALE: prompt-file metadata key.
Use locale when the application already knows the user's preferred language and country from account settings, tenant policy, request metadata, or a dispatcher decision. The locale is stored on the job definition and affects the request STATEK sends to the model.
In application code, pass a StatekLocale object:
from statek import create_new_job
from statek.locale import resolve_locale
job = create_new_job(
agent=calendar_assistant,
shared_vars={"message": incoming_message, "calendar": calendar},
locale=resolve_locale("PL-PL"),
)External client code can pass either a StatekLocale object or a locale string. StatekClientAPI resolves strings with resolve_locale(...) before creating the job:
from statek.statek_client_api import StatekClientAPI
job = StatekClientAPI().submit_new_job(
agent=dispatcher,
shared_vars={"event": incoming_event},
locale="ES-ES",
source="webhook",
)When a job creates a child job and does not pass an explicit locale, STATEK inherits the parent job's locale. Pass a different locale only when the child job should deliberately switch language behavior.
Locale changes two automatic prompt behaviors:
- for languages with a hardcoded rule, STATEK appends that rule to the outgoing
system_prompt - for languages with a hardcoded hint, STATEK appends that hint to user messages and push-log messages
English locales and jobs without locale leave the prompt unchanged. Languages without a hardcoded rule or hint also do not receive automatic injected text, even when the language and country codes are valid. Current automatic rules and hints are defined for Polish, German, French, Spanish, and Italian.
Prompt metadata can disable either automatic behavior:
# MODEL: openai/gpt-5-mini
# AUTO_LANG_RULE: False
# AUTO_LANG_HINT: False
# System Prompt
ROLE: Calendar assistant.
GOAL: Help the user manage scheduling requests.Use AUTO_LANG_RULE: False when your prompt already contains the complete language policy. Use AUTO_LANG_HINT: False when appending a reminder to each user-facing message would be noisy or your application already injects localized request text.
System Prompt Sections
The system prompt body can be plain text or a parsed set of sections. The intro text before the first section is always included.
STATEK recognizes four section delimiter styles:
<identity>Identity text.</identity>
--- RULES ---
Rules text.
*** WORKFLOW ***
Workflow text.
## Output
Output text.Markdown headings from ## through ###### are section delimiters. # System Prompt is the prompt-file boundary, not a system prompt section.
When STATEK formats a prompt for a job, sections without difficulty metadata apply to every job. Sections with difficulty metadata apply only when the current job difficulty matches.
Target line-based sections with a difficulty prefix:
--- MH:RETRIEVAL ---
Use the broader retrieval workflow for medium and high difficulty tasks.
## L:Fast Path
Prefer the shortest safe answer path.Target XML sections with attributes:
<retrieval difficulty="high">
Use the high-effort retrieval workflow.
</retrieval>
<examples target_difficulties="LMH">
Example usage notes.
</examples>Valid labels are L, M, H, low, medium, and high. Compact labels such as LMH and delimited values such as low, high are accepted where the parser expects difficulty lists.
Current Agent.system_prompt(...) formatting emits dashed sections by default:
--- RULES ---
Rules text.CHAT_STYLE does not change prompt section parsing. It changes chat history, examples, code blocks, console output, and tool execution shape.
Placeholders
STATEK expands common placeholders when formatting the system prompt for a job:
{brief_tools}inserts concise tool descriptions.{tools}inserts normal tool descriptions.{detailed_tools}inserts Python-style tool details.{shared_var_names}expands from the job'sshared_vars.
Other {name} placeholders can be supplied through job params or other format context.
# MODEL: openai/gpt-5-mini
# System Prompt
You operate on the durable Python workspace.
Available variables: {shared_var_names}
Request id: {request_id}
Available functions:
{brief_tools}A matching job definition can pass context for those placeholders:
job_def = agent.create_job_def(
shared_vars={"ticket": ticket, "customer": customer},
request_id="REQ-1042",
)If a placeholder line starts with #, tool descriptions are embedded as a Python block comment. This is useful when you want tool docs inside a code-oriented prompt.
Difficulty And panic()
Difficulty is a routing label for model selection and prompt section selection. It is not a guarantee of quality or deterministic behavior.
Resolution order:
- If the current job has a matching example difficulty, use it as dynamic difficulty.
- If dynamic difficulty already exists, a lower example difficulty does not downgrade it.
- If a higher matching example difficulty appears, it can raise the dynamic difficulty.
- If no dynamic difficulty applies, use job metadata
DEFAULT_DIFFICULTY. - If metadata does not define it, use
STATEK_DEFAULT_DIFFICULTY.
panic() is a system tool that escalates the current job one step:
- low to medium
- medium to high
- high raises an error
Use panic() when the current model or prompt section set is not enough for the task. It is an escalation mechanism, not a general retry button.
panic() is only available to the model when the LLM tool scope exposes that system tool, for example:
# LLM_TOOLS_SCOPE: SYSTEMor:
# LLM_TOOLS_SCOPE: ALLor:
# LLM_TOOLS_SCOPE: +panicChat Styles
CHAT_STYLE affects how chat history, code, console output, examples, and tool execution are represented. See Chat Styles for practical guidance and examples.
CONSOLE: console output is shown with>prefixes.MARKDOWN: Python examples use fenced Python blocks; console output is plain text.MD_DIALOG: Markdown dialog style with Python code blocks and console XML blocks.DIRECT: Python execution uses thepython_clitool; Python code fences in model responses are ignored.
Related settings:
STATEK_CHAT_STYLE=DIRECT
STATEK_EXAMPLES_STYLE=MARKDOWN
STATEK_XML_BOX_CONSOLE=console_output
STATEK_XML_BOX_EXAMPLE=code_blockSTATEK_CHAT_STYLE is the default job chat style when a job definition does not override it. STATEK_EXAMPLES_STYLE controls example formatting, falling back to chat style when absent. STATEK_XML_BOX_CONSOLE and STATEK_XML_BOX_EXAMPLE wrap console or example output in configured XML tags where the formatter supports boxing.
Minimal Prompt File
# MODEL: openai/gpt-5-mini
# TEMPERATURE: 0.2
# CHAT_STYLE: DIRECT
# LLM_TOOLS_SCOPE: APPLICATION
# DESCRIPTION: Helps users inspect and update calendar state.
# System Prompt
ROLE: Calendar assistant.
GOAL: Help the user answer scheduling questions using Python.
Available variables: {shared_var_names}
Available functions:
{brief_tools}Advanced Prompt File
# MODEL: L:gpt-5-mini,MH:gpt-5
# DEFAULT_DIFFICULTY: M
# TEMPERATURE: 0.1
# CHAT_STYLE: DIRECT
# LLM_TOOLS_SCOPE: SYSTEM
# DESCRIPTION: Researches internal documents and summarizes verified findings.
# System Prompt
ROLE: Research assistant.
GOAL: Inspect available context and produce source-grounded answers.
Available variables: {shared_var_names}
--- L:FAST PATH ---
Use the smallest useful lookup. Prefer direct answers when the needed object is already in context.
--- MH:RETRIEVAL ---
When the answer is not already visible, list available documents or examples before making a claim.
<verification difficulty="high">
Cross-check important facts against at least two available sources when the tools expose them.
</verification>
--- AVAILABLE FUNCTIONS ---
{brief_tools}Because CHAT_STYLE is DIRECT, Python execution should happen through the python_cli system tool when it is exposed. With LLM_TOOLS_SCOPE: SYSTEM, the model can use system tools such as python_cli, show_example, and panic() when those tools are registered for the active chat style.
Dispatcher Pattern
Dispatcher prompts are useful when one durable job decides whether to answer directly, continue an existing thread, or start a specialist job. Keep them narrow: load context in warmup code, print the relevant facts, and tell the dispatcher to make one routing decision.
# MODEL: openai/gpt-5-mini
# TEMPERATURE: 0.1
# CHAT_STYLE: DIRECT
# LLM_TOOLS_SCOPE: SYSTEM
# DEFAULT_DIFFICULTY: L
# DESCRIPTION: Routes incoming requests to the best specialist agent.
# System Prompt
ROLE: Request dispatcher.
GOAL: Route the current request to an existing job or the best specialist agent.
The warmup code already prepared and printed:
- the incoming request
- recent active jobs
- available specialist agents
- relevant example names
--- ROUTING POLICY ---
- Continue an existing job only when the request is clearly a follow-up.
- Start a new specialist job for a fresh self-contained request.
- Prefer the narrowest specialist that has the needed tools.
- Use `default_example_id` only when a printed example is reasonably similar.
--- OUTPUT ---
Call exactly one routing function. Do not perform unrelated exploration.
--- AVAILABLE FUNCTIONS ---
{brief_tools}This pattern keeps application-specific business rules in your application prompt while avoiding private domain details in shared documentation.
Example File Snippet
Example files can carry metadata that show_example and difficulty resolution use. See Examples Machinery for the full file format and runtime tools:
# seq_id: 0
# name: Summarize one document
# difficulty: low
```python
docs = list_recent_documents(limit=3)
print(docs)
```
> [0] onboarding.md
> [1] billing.md
```python
summary = summarize_document(docs[0])
print(summary)
```Example difficulty is optional. When present, it can raise the job's dynamic difficulty for prompt section selection and mapped model selection.
Related Configuration
Prompt definitions often work with these settings:
STATEK_PROMPT_FILES_DIR=./prompts
STATEK_EXAMPLES_DIR=./examples
STATEK_DOCUMENTS_DIR=./documents
STATEK_CHAT_STYLE=DIRECT
STATEK_EXAMPLES_STYLE=MARKDOWN
STATEK_DEFAULT_DIFFICULTY=MUse prompt files for role instructions and model metadata. Keep durable objects, tool implementations, warmup behavior, provider credentials, and permission boundaries in application code and deployment configuration.
Use Documents Machinery when an agent should list and retrieve file-backed reference material at runtime instead of embedding it directly in the prompt.