STATEK
Chat Styles

STATEK Chat Styles

Chat style controls how STATEK talks to an LLM about code, console output, dialog, examples, and tool calls.

It does not choose the provider or model. It does not change the durable job model. The agent still works inside a persisted Python session, and Python tools are still ordinary callables available in that session. Chat style changes the shape of the conversation STATEK sends to the model and the shape of responses STATEK expects back.

This matters because models have different capabilities. Some models are strong at writing code but weak at formal tool calling. Some are good at provider tool calls. Some are better when conversation and code are separated. STATEK supports all of those patterns.

Configure a Style

Prompt definitions can set CHAT_STYLE:

# MODEL: openrouter/deepseek/deepseek-chat
# CHAT_STYLE: MARKDOWN
 
# System Prompt
You inspect the durable Python workspace by writing Python in fenced code blocks.
Use the available variables and functions before answering.

Application code can also set a job definition's chat style directly, and STATEK_CHAT_STYLE can provide the default when the job definition has no override:

STATEK_CHAT_STYLE=MARKDOWN
STATEK_EXAMPLES_STYLE=MARKDOWN

STATEK_EXAMPLES_STYLE controls example formatting and falls back to the active chat style when it is not set.

Choosing a Style

Use MARKDOWN when the model can write Python reliably but does not support provider tool calling well. The model submits code in fenced Python blocks, and that code can call application functions, inspect objects, assign durable variables, and print results. This gives many of the same benefits as tool calling, often with more composability because the model can combine multiple Python operations in one durable step.

Use DIRECT when the model supports reliable formal tool calls. In this style, normal assistant text is dialog, and Python execution happens through the python_cli system tool. Inline Python code fences in model responses are ignored.

Use MD_DIALOG for dialog agents that need to mix user-facing conversation with background Python work. Prose can become the dialog response, while fenced Python blocks can perform durable work.

Use CONSOLE mainly for simple or legacy console transcript flows. It is supported, but it is usually not the best default for new code-first agents.

Markdown-style Python execution is not provider tool calling. The model writes Python, and STATEK executes that Python inside the durable job. Formal provider tool calling is separate and controlled by provider support, LLM_TOOLS_SCOPE, and chat-style-compatible tools.

MARKDOWN

MARKDOWN expects executable Python inside fenced python blocks. Console output is shown back to the model as plain text.

This is a practical default for code-capable models without reliable tool calling:

# CHAT_STYLE: MARKDOWN

A model can respond with Python:

```python
events = calendar.events_for(today)
matching = [event for event in events if "planning" in event.title.lower()]
print(matching)
```

On the next turn, the same job can reuse events and matching because they live in the durable Python workspace:

```python
meeting = matching[0]
slot = find_empty_slot(calendar, after=meeting.ends_at)
meeting.move_to(slot)
print("Moved to:", meeting.starts_at)
```

This can be more expressive than a single formal tool call. The model can inspect state, call multiple Python functions, transform results, and keep intermediate variables for the next step.

DIRECT

DIRECT treats assistant text as dialog. Python execution happens through the python_cli system tool, which is available only for DIRECT style.

Use DIRECT with models that support formal tool calls well:

# CHAT_STYLE: DIRECT
# LLM_TOOLS_SCOPE: SYSTEM

The model requests a tool call equivalent to:

python_cli(code="""
events = calendar.events_for(today)
print(events)
""")

STATEK executes that code inside the same durable job context. Variables assigned in one python_cli call are visible in later calls:

python_cli(code="""
meeting = calendar.find_meeting("Weekly planning", day=today)
print(meeting)
""")

In DIRECT, Python fenced blocks in assistant text are not executed. That protects dialog text from being accidentally parsed as Python, but it means the prompt and tool scope must make python_cli available when the agent is expected to run code.

MD_DIALOG

MD_DIALOG is for dialog-oriented agents that can both talk to a user and run Python in the background. It uses Markdown code blocks for executable Python and boxes console output.

For example:

I will check that before changing anything.
 
```python
meeting = calendar.find_meeting("Weekly planning", day=today)
candidate = calendar.find_empty_slot(after=meeting.ends_at)
print(candidate)
```

The Python block prepares state for the next step. The prose can be handled as user-facing dialog by the dialog agent flow.

DialogAgent.create_job_def(...) defaults to MD_DIALOG unless an explicit style or prompt metadata overrides it.

CONSOLE

CONSOLE represents console output with > prefixes and leaves code unwrapped:

print(user)
> User(display_name="Ari")

This style is useful when you want a compact console transcript format or when maintaining older examples. For new code-first agents, prefer MARKDOWN or DIRECT unless a console transcript is the clearest fit.

Tools and Style

There are two ways an agent can use tools:

  • Python tools: call functions from Python code, such as find_empty_slot(calendar, after=meeting.ends_at).
  • Provider tool calls: ask the model provider to call a named tool through the provider's formal tool-calling API.

MARKDOWN and MD_DIALOG are strong fits for Python tools because the model writes executable Python. A model without formal tool calling can still use the application surface through Python:

```python
results = search_documents(query=request_text, limit=5)
print(results)
```

DIRECT is designed around formal tool calls. In DIRECT, python_cli is exposed as a system tool when selected by LLM_TOOLS_SCOPE, and python_cli is the route for Python execution:

# CHAT_STYLE: DIRECT
# LLM_TOOLS_SCOPE: SYSTEM

LLM_TOOLS_SCOPE controls which formal provider tools are sent to the model. It does not change what Python functions are available inside executed Python code.

Examples and Console Boxing

Examples are formatted with the active chat style unless STATEK_EXAMPLES_STYLE is set:

STATEK_CHAT_STYLE=DIRECT
STATEK_EXAMPLES_STYLE=MARKDOWN

This is useful when a DIRECT agent should still read examples written as Markdown code-and-console transcripts.

Console and example output can also be wrapped in XML-style tags where the formatter supports it:

STATEK_XML_BOX_CONSOLE=console_output
STATEK_XML_BOX_EXAMPLE=example

Use boxing when it makes boundaries clearer for the model. Avoid adding markup unless it improves reliability for the models you run.

Practical Rules

Match the style to the model, not the provider name. Providers can expose many models with different tool-calling quality.

Use MARKDOWN when you want a code-first agent on a model that can write Python but should not depend on formal tool calls.

Use DIRECT only when the model reliably calls tools and your prompt metadata exposes the right tools, especially python_cli when Python execution is required.

Use MD_DIALOG when the same job needs user-facing text and background Python execution.

Keep prompts explicit. Tell the model whether it should submit fenced Python, call python_cli, or answer in dialog text. The more direct the prompt is about the chosen style, the less recovery work the job has to do later.

Where to go next

Read Prompt Definitions for CHAT_STYLE metadata, Tools for Python and provider tool surfaces, Model Providers for provider setup, and Security before exposing side-effecting tools.